I'm doing a project for school in C and basically what I need to do is to create a grid of agents (Humans, Zombies or none) and randomly pick which ones I manually control or are "AI" controlled. Basically humans need to run from zombies and zombies have to chase humans to infect them, game ending when there are no humans left.
Problem is, before each turn it should be randomly selected who plays first, and for that I need to shuffle the agents (not touching the grid because the agent positions remain the same, the only thing that changes is their position in the array that I should be using to pick who plays first).
I'm having some troubles with the shuffle because I call the function and after I shuffle the agents I print their Ids. It just give me many many 0s and in between some random numbers like 3, 6, 10, etc and a few more only.
Here's the code:
main file:
#include "showworld.h"
#include "example.h"
#include "shuffle.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/** Horizontal world size. */
#define WORLD_X 20
/** Vertical world size. */
#define WORLD_Y 20
/**
* Structure defining agent properties.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
* */
typedef struct {
AGENT_TYPE type; /**< Agent type. */
unsigned char playable; /**< Is agent playable? */
unsigned short id; /**< Agent ID. */
} AGENT;
/**
* Structure defining world properties.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
* */
typedef struct {
AGENT *grid; /**< World is a grid composed of agents. */
unsigned int xsize; /**< Horizontal world size. */
unsigned int ysize; /**< Vertical world size. */
} WORLD;
/* This function is an implementation of the definition provided by the
* ::get_agent_info_at() function pointer. It only works for AGENT and WORLD
* example structures defined in this file. */
unsigned int example_get_ag_info(void *world, unsigned int x, unsigned int y);
int main() {
/* An instance of a WORLD structure. */
WORLD my_world;
/* An instance of a SHOWWORLD world display. */
SHOWWORLD *sw = NULL;
/* A by-dimensional array of agents, representing agents in a grid. */
AGENT agent_grid[WORLD_X][WORLD_Y];
/* Number of agents created so far. */
unsigned int nagents = 0;
/* Initialize world display. */
sw = showworld_new(WORLD_X, WORLD_Y, example_get_ag_info);
/* Initialize random number generator. */
srand(time(NULL));
/* **************************************************************** */
/* Cycle through all cells in grid and randomly place agents in it. */
/* **************************************************************** */
for (int i = 0; i < WORLD_X; ++i) {
for (int j = 0; j < WORLD_Y; ++j) {
/* Possible agent in grid. By default we assume there is none. */
AGENT ag = {None, 0, 0};
/* Obtain a probability between 0 and 99. */
unsigned char probability = rand() % 100;
/* There is 10% probability of creating an agent. */
if (probability < 10) {
/* If we got here, an agent will be placed at (i,j). */
/* Randomly define agent type. */
ag.type = (rand() % 2 == 0) ? Human : Zombie;
/* Give 10% probablity of agent being playable by user. */
ag.playable = (rand() % 10 == 0);
/* Assign agent ID and then increment number of agents so
far. */
ag.id = nagents++;
}
/* Assign possible agent to grid at (i,j). */
agent_grid[i][j] = ag;
}
}
/* ******************************* */
/* Populate the my_world variable. */
/* ******************************* */
/* A bidimensional array of agents can be interpreted as a pointer to
agents. */
my_world.grid = (AGENT *) agent_grid;
/* World size is defined by constants in this example. */
my_world.xsize = WORLD_X;
my_world.ysize = WORLD_Y;
/* ********************************************************************* */
/* Show world using the simple_show_world() function. This function can */
/* be used in the first part of the project. */
/* ********************************************************************* */
showworld_update(sw, &my_world);
shuffle(my_world.grid, nagents);
/* Before finishing, ask user to press ENTER. */
printf("Press ENTER to continue...");
getchar();
/* Destroy world display. */
showworld_destroy(sw);
/* Bye. */
return 0;
}
/**
* This function is an implementation of the ::get_agent_info_at() function
* definition. It only works for ::AGENT and ::WORLD structures defined in this
* example.
*
* It basically receives a pointer to a ::WORLD structure, obtains the AGENT
* structure in the given coordinates, and returns the agent information in a
* bit-packed `unsigned int`.
*
* @note This is an example which will probably not work in a fully functional
* game. Students should develop their own implementation of
* ::get_agent_info_at() and agent/world data structures.
*
* @param w Generic pointer to object representing the simulation world.
* @param x Horizontal coordinate of the simulation world from where to fetch
* the agent information.
* @param y Vertical coordinate of the simulation world from where to fetch
* the agent information.
* @return An integer containing bit-packed information about an agent, as
* follows: bits 0-1 (agent type), bit 2 (is agent playable), bits 3-18 (agent
* ID). Bits 19-31 are available for student-defined agent extensions.
* */
unsigned int example_get_ag_info(void *w, unsigned int x, unsigned int y) {
/* The agent information to return. */
unsigned int ag_info = 0;
/* Convert generic pointer to world to a WORLD object. */
WORLD *my_world = (WORLD *) w;
/* Check if the given (x,y) coordinates are within bounds of the world. */
if ((x >= my_world->xsize) || (y >= my_world->ysize)) {
/* If we got here, then the coordinates are off bounds. As such we will
report that the requested agent is of unknown type. No need to
specify agent ID or playable status, since the agent is unknown. */
ag_info = Unknown;
} else {
/* Given coordinates are within bounds, let's get and pack the request
agent information. */
/* Obtain agent at specified coordinates. */
AGENT ag = my_world->grid[x * my_world->xsize + y];
/* Is there an agent at (x,y)? */
if (ag.type == None) {
/* If there is no agent at the (x,y) coordinates, set agent type to
None. No need to specify agent ID or playable status, since
there is no agent here. */
ag_info = None;
} else {
/* If we get here it's because there is an agent at (x,y). Bit-pack
all the agent information as specified by the get_agent_info_at
function pointer definition. */
ag_info = (ag.id << 3) | (ag.playable << 2) | ag.type;
}
}
/* Return the requested agent information. */
return ag_info;
}
Here's shuffle function
#include "example.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(AGENT *agents, unsigned int nagents) {
printf("%s\n\n", "------------- Shuffling agents ----------------");
unsigned int i=0;
unsigned int j=0;
AGENT temp;
srand(time(NULL));
for (i = nagents - 1; i > 0; i--) {
j = (rand() % i);
temp = agents[i];
agents[i] = agents[j];
agents[j] = temp;
}
for (i = 0; i < nagents; i++) {
printf("\n\t%d", agents[i].id);
}
Here's showworld file:
#include "showworld.h"
#include <stdio.h>
#include <stdlib.h>
/* The implementation of `SHOWWORLD` type used in this simple text-based world
* visualization code. In this simple case, we only need to keep track of the
* world dimensions and of the function pointer which knows how to read an
* agent from the world data structure.
*
* For a more complex implementation, for example based on the g2 library,
* it would also be necessary to keep the g2 device.
* */
struct showworld {
unsigned int xdim;
unsigned int ydim;
get_agent_info_at aginfo_func;
};
/* Create a new display/visualization object for the simulation world.
*
* This function obeys the `showworld_new()` prototype defined in
* `showworld.h`. */
SHOWWORLD *showworld_new(
unsigned int xdim,
unsigned int ydim,
get_agent_info_at aginfo_func) {
SHOWWORLD *sw = NULL;
sw = malloc(sizeof(SHOWWORLD));
sw->xdim = xdim;
sw->ydim = ydim;
sw->aginfo_func = aginfo_func;
return sw;
}
/* Destroy a display/visualization object for the simulation world.
*
* This function obeys the `showworld_destroy()` prototype defined in
* `showworld.h`. */
void showworld_destroy(SHOWWORLD *sw) {
free(sw);
}
/* Update the simulation world display/visualization.
*
* This function obeys the `showworld_update()` prototype defined in
* `showworld.h`. */
void showworld_update(SHOWWORLD *sw, void *w) {
printf("\n");
/* Cycle through all the rows */
for (unsigned int y = 0; y < sw->ydim; ++y) {
/* Cycle through all the columns for the current row */
for (unsigned int x = 0; x < sw->xdim; ++x) {
/* Get state of the world (in bit packed fashion) using the user
supplied function. */
unsigned int item = sw->aginfo_func(w, x, y);
/* Extract the agent type (2 bits). */
AGENT_TYPE ag_type = item & 0x3;
/* Extract whether the agent is playable (1 bit). */
unsigned char playable = (item >> 2) & 0x1;
/* Extract the agent ID (16 bits). */
unsigned short ag_id = (item >> 3) & 0xFFFF;
/* Determine the agent type. */
switch (ag_type) {
/* If no agent is present at (x,y) just print a dot. */
case None:
printf(" . ");
break;
/* If human agent present at (x,y) print 'h' or 'H'. */
case Human:
if (playable) {
/* Uppercase 'H' for player-controlled human agent. */
printf("H");
} else {
/* Lowercase 'h' for AI-controlled human agent. */
printf("h");
}
/* Print the agent ID in front of the 'h'/'H'. */
printf("%02X ", ag_id);
break;
/* If zombie agent present at (x,y) print 'z' or 'Z'. */
case Zombie:
if (playable) {
/* Uppercase 'Z' for player-controlled zombie agent. */
printf("Z");
} else {
/* Lowercase 'z' for AI-controlled zombie agent. */
printf("z");
}
/* Print the agent ID in front of the 'h'/'H'. */
printf("%02X ", ag_id);
break;
/* Print '?' if unknown type detected. This should *never*
happen. */
default:
printf("? ");
}
}
/* Print two newlines after each row. */
printf("\n\n");
}
/* Print a newline after world is shown/updated. */
printf("\n");
}