home · contact · privacy
Some code grouping and commenting to explain program flow.
[plomrogue] / src / roguelike.c
index 54c62c2fd919e277b492150db8fe6803ffc3873a..206c0289243c1d152d56b1a53dd8e273c21f8501 100644 (file)
@@ -55,6 +55,10 @@ void save_game(struct World * world) {
   write_uint16_bigendian(world->player->x, file);
   write_uint16_bigendian(world->monster->y, file);
   write_uint16_bigendian(world->monster->x, file);
+  write_uint16_bigendian(world->monster->next->y, file);
+  write_uint16_bigendian(world->monster->next->x, file);
+  write_uint16_bigendian(world->monster->next->next->y, file);
+  write_uint16_bigendian(world->monster->next->next->x, file);
   fclose(file); }
 
 void record_action (char action) {
@@ -67,22 +71,26 @@ void next_turn (struct World * world) {
 // Increment turn and move enemy.
   world->turn++;
   rrand(1, world->seed * world->turn);
-  char d = rrand(0, 0) % 5;
-  uint16_t ty = world->monster->y;
-  uint16_t tx = world->monster->x;
-  if (1 == d)
-    ty++;
-  else if (2 == d)
-    ty--;
-  else if (3 == d)
-    tx++;
-  else if (4 == d)
-    tx--;
-  if (tx == world->player->x && ty == world->player->y)
-    update_log(world, "\nThe monster hits you.");
-  else if (is_passable(world->map, ty, tx)) {
-    world->monster->y = ty;
-    world->monster->x = tx; } }
+  char d;
+  struct Monster * monster;
+  uint16_t ty, tx;
+  for (monster = world->monster; monster != 0; monster = monster->next) {
+    d = rrand(0, 0) % 5;
+    ty = monster->y;
+    tx = monster->x;
+    if (1 == d)
+      ty++;
+    else if (2 == d)
+      ty--;
+    else if (3 == d)
+      tx++;
+    else if (4 == d)
+      tx--;
+    if (tx == world->player->x && ty == world->player->y)
+      update_log(world, "\nThe monster hits you.");
+    else if (is_passable(world->map, ty, tx)) {
+      monster->y = ty;
+      monster->x = tx; } } }
 
 void update_log (struct World * world, char * text) {
 // Update log with new text to be appended.
@@ -115,9 +123,12 @@ void move_player (struct World * world, char d) {
   if ('e' == d) {
     dir = "east";
     tx++; }
-  if (ty == world->monster->y && tx == world->monster->x)
-    success = 2;
-  else if (is_passable(world->map, ty, tx)) {
+  struct Monster * monster;
+  for (monster = world->monster; monster != 0; monster = monster->next)
+    if (ty == monster->y && tx == monster->x) {
+      success = 2;
+      break; }
+  if (2 != success && is_passable(world->map, ty, tx)) {
     success = 1;
     world->player->y = ty;
     world->player->x = tx; }
@@ -247,9 +258,11 @@ unsigned char meta_keys(int key, struct World * world, struct WinMeta * win_meta
 
 int main (int argc, char *argv[]) {
   struct World world;
-  world.interactive = 1;
+
+  // Read in startup options (i.e. replay option and replay start turn).
   int opt;
   uint32_t start_turn;
+  world.interactive = 1;
   while ((opt = getopt(argc, argv, "s::")) != -1) {
     switch (opt) {
       case 's':
@@ -261,12 +274,23 @@ int main (int argc, char *argv[]) {
       default:
         exit(EXIT_FAILURE); } }
 
+  // Initialize log, player and monsters.
   world.log = calloc(1, sizeof(char));
   update_log (&world, " ");
   struct Player player;
   world.player = &player;
-  struct Monster monster;
-  world.monster = &monster;
+  struct Monster monster1;
+  struct Monster monster2;
+  struct Monster monster3;
+  world.monster = &monster1;
+  monster1.next = &monster2;
+  monster2.next = &monster3;
+  monster3.next = 0;
+  monster1.name = 'A';
+  monster2.name = 'B';
+  monster3.name = 'C';
+
+  // For interactive mode, try to load world state from savefile.
   FILE * file;
   if (1 == world.interactive && 0 == access("savefile", F_OK)) {
     file = fopen("savefile", "r");
@@ -274,19 +298,29 @@ int main (int argc, char *argv[]) {
     world.turn = read_uint32_bigendian(file);
     player.y = read_uint16_bigendian(file);
     player.x = read_uint16_bigendian(file);
-    monster.y = read_uint16_bigendian(file);
-    monster.x = read_uint16_bigendian(file);
+    monster1.y = read_uint16_bigendian(file);
+    monster1.x = read_uint16_bigendian(file);
+    monster2.y = read_uint16_bigendian(file);
+    monster2.x = read_uint16_bigendian(file);
+    monster3.y = read_uint16_bigendian(file);
+    monster3.x = read_uint16_bigendian(file);
     fclose(file); }
+
+  // For non-interactive mode, try to load world state from frecord file.
   else {
     world.turn = 1;
     if (0 == world.interactive) {
       file = fopen("record", "r");
       world.seed = read_uint32_bigendian(file); }
+
+    // For interactive-mode in newly started world, generate a start seed from the current time.
     else {
       file = fopen("record", "w");
       world.seed = time(NULL);
       write_uint32_bigendian(world.seed, file);
       fclose(file); } }
+
+  // Generate map from seed and, if newly generated world, start positions of actors.
   rrand(1, world.seed);
   struct Map map = init_map();
   world.map = ↦
@@ -294,10 +328,13 @@ int main (int argc, char *argv[]) {
     for (player.y = player.x = 0; 0 == is_passable(&map, player.y, player.x);) {
       player.y = rrand(0, 0) % map.height;
       player.x = rrand(0, 0) % map.width; }
-    for (monster.y = monster.x = 0; 0 == is_passable(&map, monster.y, monster.x);) {
-      monster.y = rrand(0, 0) % map.height;
-      monster.x = rrand(0, 0) % map.width; } }
+    struct Monster * monster;
+    for (monster = world.monster; monster != 0; monster = monster->next)
+      for (monster->y = monster->x = 0; 0 == is_passable(&map, monster->y, monster->x);) {
+        monster->y = rrand(0, 0) % map.height;
+        monster->x = rrand(0, 0) % map.width; } }
 
+  // Initialize window system and windows.
   WINDOW * screen = initscr();
   noecho();
   curs_set(0);
@@ -318,6 +355,7 @@ int main (int argc, char *argv[]) {
   toggle_window(&win_meta, &win_info);
   toggle_window(&win_meta, &win_log);
 
+  // Replay mode.
   int key;
   unsigned char quit_called = 0;
   if (0 == world.interactive) {
@@ -349,6 +387,8 @@ int main (int argc, char *argv[]) {
         quit_called = meta_keys(key, &world, &win_meta, &win_keys, &win_map, &win_info, &win_log);
         if (1 == quit_called)
           break; } }
+
+  // Interactive mode.
   else {
     uint32_t last_turn = 0;
     while (1) {
@@ -372,12 +412,12 @@ int main (int argc, char *argv[]) {
         if (1 == quit_called)
           break; } }
 
+  // Clean up and exit.
   free(map.cells);
   for (key = 0; key <= world.keyswindata->max; key++)
     free(world.keybindings[key].name);
   free(world.keybindings);
   free(world.keyswindata);
   free(world.log);
-
   endwin();
   return 0; }