int main(int argc, char *argv[]) { dungeon_t d; time_t seed; struct timeval tv; uint32_t i; uint32_t do_load, do_save, do_seed, do_image; uint32_t long_arg; char *save_file; char *pgm_file; memset(&d, 0, sizeof (d)); /* Default behavior: Seed with the time, generate a new dungeon, * * and don't write to disk. */ do_load = do_save = do_image = 0; do_seed = 1; save_file = NULL; d.max_monsters = 10; /* The project spec requires '--load' and '--save'. It's common * * to have short and long forms of most switches (assuming you * * don't run out of letters). For now, we've got plenty. Long * * forms use whole words and take two dashes. Short forms use an * ` * abbreviation after a single dash. We'll add '--rand' (to * * specify a random seed), which will take an argument of it's * * own, and we'll add short forms for all three commands, '-l', * * '-s', and '-r', respectively. We're also going to allow an * * optional argument to load to allow us to load non-default save * * files. No means to save to non-default locations, however. * * And the final switch, '--image', allows me to create a dungeon * * from a PGM image, so that I was able to create those more * * interesting test dungeons for you. */ if (argc > 1) { for (i = 1, long_arg = 0; i < argc; i++, long_arg = 0) { if (argv[i][0] == '-') { /* All switches start with a dash */ if (argv[i][1] == '-') { argv[i]++; /* Make the argument have a single dash so we can */ long_arg = 1; /* handle long and short args at the same place. */ } switch (argv[i][1]) { case 'r': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-rand")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%lu", &seed) /* Argument is not an integer */) { usage(argv[0]); } do_seed = 0; break; case 'l': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-load"))) { usage(argv[0]); } do_load = 1; if ((argc > i + 1) && argv[i + 1][0] != '-') { /* There is another argument, and it's not a switch, so * * we'll treat it as a save file and try to load it. */ save_file = argv[++i]; } break; case 's': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-save"))) { usage(argv[0]); } do_save = 1; break; case 'i': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-image"))) { usage(argv[0]); } do_image = 1; if ((argc > i + 1) && argv[i + 1][0] != '-') { /* There is another argument, and it's not a switch, so * * we'll treat it as a save file and try to load it. */ pgm_file = argv[++i]; } break; case 'n': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-nummon")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%hu", &d.max_monsters)) { usage(argv[0]); } break; default: usage(argv[0]); } } else { /* No dash */ usage(argv[0]); } } } if (do_seed) { /* Allows me to generate more than one dungeon * * per second, as opposed to time(). */ gettimeofday(&tv, NULL); seed = (tv.tv_usec ^ (tv.tv_sec << 20)) & 0xffffffff; } printf("Seed is %ld.\n", seed); srand(seed); io_init_terminal(); init_dungeon(&d); if (do_load) { read_dungeon(&d, save_file); } else if (do_image) { read_pgm(&d, pgm_file); } else { gen_dungeon(&d); } config_pc(&d); gen_monsters(&d, d.max_monsters, 0); io_display(&d); while (pc_is_alive(&d) && dungeon_has_npcs(&d) && !d.save_and_exit) { do_moves(&d); if (!pc_is_alive(&d)) { break; } } io_display(&d); if (!d.save_and_exit) { sleep(2); } io_reset_terminal(); if (do_save) { write_dungeon(&d); } printf(pc_is_alive(&d) ? victory : tombstone); /* PC can't be deleted with the dungeon, else * * it disappears when we use the stairs. */ if (pc_is_alive(&d)) { /* If the PC is dead, it's in the move heap and will get automatically * * deleted when the heap destructs. In that case, we can't call * * delete_pc(), because it will lead to a double delete. */ delete_pc(d.pc); } delete_dungeon(&d); return 0; }
int main(int argc, char *argv[]) { dungeon_t d; time_t seed; uint32_t nummon; struct timeval tv; uint32_t i; uint32_t do_seed; uint32_t long_arg; uint32_t do_huge; memset(&d, 0, sizeof (d)); /* Default behavior: Seed with the time, generate a new dungeon, * * and don't write to disk. */ do_seed = 1; do_huge = 0; nummon = 10; /* The project spec requires '--load' and '--store'. It's common * * to have short and long forms of most switches (assuming you * * don't run out of letters). For now, we've got plenty. Long * * forms use whole words and take two dashes. Short forms use an * * abbreviation after a single dash. We'll add '--rand' (to * * specify a random seed), which will take an argument of its * * own, and we'll add short forms for all three commands, '-l', * * '-s', and '-r', respectively. We're also going to allow an * * optional argument to load to allow us to load non-default save * * files. No means to store to non-default locations, however. */ if (argc > 1) { for (i = 1, long_arg = 0; i < argc; i++, long_arg = 0) { if (argv[i][0] == '-') { /* All switches start with a dash */ if (argv[i][1] == '-') { argv[i]++; /* Make the argument have a single dash so we can */ long_arg = 1; /* handle long and short args at the same place. */ } switch (argv[i][1]) { case 'r': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-rand")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%lu", &seed) /* Argument is not an integer */) { usage(argv[0]); } do_seed = 0; break; case 'n': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-nummon")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%u", &nummon) /* Argument is not an int */) { usage(argv[0]); } break; case 'h': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-huge"))) { usage(argv[0]); } do_huge = 1; break; default: usage(argv[0]); } } else { /* No dash */ usage(argv[0]); } } } if (do_seed) { /* Allows me to generate more than one dungeon * * per second, as opposed to time(). */ gettimeofday(&tv, NULL); seed = (tv.tv_usec ^ (tv.tv_sec << 20)) & 0xffffffff; } if (do_huge) { d.render_whole_dungeon = 1; } else { d.render_whole_dungeon = 0; } printf("Seed is %ld.\n", seed); srand(seed); parse_descriptions(&d); io_init_terminal(); init_dungeon(&d); if (read_dungeon(&d)) { gen_dungeon(&d); config_pc(&d); gen_monsters(&d, nummon, 0); gen_objects(&d, 10); } io_display(&d); while (pc_is_alive(&d) && dungeon_has_npcs(&d) && !(d.save_and_exit || d.quit_no_save)) { do_moves(&d); io_display(&d); if (!pc_is_alive(&d)) { break; } io_handle_input(&d); } io_display(&d); io_reset_terminal(); if (!(d.save_and_exit || d.quit_no_save)) { sleep(2); if (pc_is_alive(&d)) { printf("%s says, \"%s\"\n", d.pc.pc->name, d.pc.pc->catch_phrase); } else { printf("The monster hordes growl menacingly.\n"); } unlink_dungeon(); } else if (d.save_and_exit) { write_dungeon(&d); } else /* d.quit_no_save */ { unlink_dungeon(); } pc_delete(d.pc.pc); destroy_descriptions(&d); delete_dungeon(&d); return 0; }
int main(int argc, char *argv[]) { dungeon_t d; time_t seed; struct timeval tv; int32_t i; uint32_t do_load, do_save, do_seed, do_image, do_save_seed, do_save_image, do_place_pc; uint32_t long_arg; char *save_file; char *load_file; char *pgm_file; memset(&d, 0, sizeof (d)); /* Default behavior: Seed with the time, generate a new dungeon, * * and don't write to disk. */ do_load = do_save = do_image = do_save_seed = do_save_image = do_place_pc = 0; do_seed = 1; save_file = load_file = NULL; d.max_monsters = MAX_MONSTERS; d.max_objects = MAX_OBJECTS; /* The project spec requires '--load' and '--save'. It's common * * to have short and long forms of most switches (assuming you * * don't run out of letters). For now, we've got plenty. Long * * forms use whole words and take two dashes. Short forms use an * * abbreviation after a single dash. We'll add '--rand' (to * * specify a random seed), which will take an argument of it's * * own, and we'll add short forms for all three commands, '-l', * * '-s', and '-r', respectively. We're also going to allow an * * optional argument to load to allow us to load non-default save * * files. No means to save to non-default locations, however. * * And the final switch, '--image', allows me to create a dungeon * * from a PGM image, so that I was able to create those more * * interesting test dungeons for you. */ if (argc > 1) { for (i = 1, long_arg = 0; i < argc; i++, long_arg = 0) { if (argv[i][0] == '-') { /* All switches start with a dash */ if (argv[i][1] == '-') { argv[i]++; /* Make the argument have a single dash so we can */ long_arg = 1; /* handle long and short args at the same place. */ } switch (argv[i][1]) { case 'r': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-rand")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%lu", &seed) /* Argument is not an integer */) { usage(argv[0]); } do_seed = 0; break; case 'l': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-load"))) { usage(argv[0]); } do_load = 1; if ((argc > i + 1) && argv[i + 1][0] != '-') { /* There is another argument, and it's not a switch, so * * we'll treat it as a save file and try to load it. */ load_file = argv[++i]; } break; case 's': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-save"))) { usage(argv[0]); } do_save = 1; if ((argc > i + 1) && argv[i + 1][0] != '-') { /* There is another argument, and it's not a switch, so * * we'll save to it. If it is "seed", we'll save to * * <the current seed>.rlg327. If it is "image", we'll * * save to <the current image>.rlg327. */ if (!strcmp(argv[++i], "seed")) { do_save_seed = 1; do_save_image = 0; } else if (!strcmp(argv[i], "image")) { do_save_image = 1; do_save_seed = 0; } else { save_file = argv[i]; } } break; case 'i': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-image"))) { usage(argv[0]); } do_image = 1; if ((argc > i + 1) && argv[i + 1][0] != '-') { /* There is another argument, and it's not a switch, so * * we'll treat it as a save file and try to load it. */ pgm_file = argv[++i]; } break; case 'n': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-nummon")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%hu", &d.max_monsters)) { usage(argv[0]); } break; case 'p': /* PC placement makes no effort to avoid placing * * the PC inside solid rock. */ if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-pc"))) { usage(argv[0]); } if ((d.PC->position[dim_y] = atoi(argv[++i])) < 1 || d.PC->position[dim_y] > DUNGEON_Y - 2 || (d.PC->position[dim_x] = atoi(argv[++i])) < 1 || d.PC->position[dim_x] > DUNGEON_X - 2) { fprintf(stderr, "Invalid PC position.\n"); usage(argv[0]); } do_place_pc = 1; break; case 'o': if ((!long_arg && argv[i][2]) || (long_arg && strcmp(argv[i], "-objcount")) || argc < ++i + 1 /* No more arguments */ || !sscanf(argv[i], "%hu", &d.max_objects)) { usage(argv[0]); } break; default: usage(argv[0]); } } else { /* No dash */ usage(argv[0]); } } } if (do_seed) { /* Allows me to generate more than one dungeon * * per second, as opposed to time(). */ gettimeofday(&tv, NULL); seed = (tv.tv_usec ^ (tv.tv_sec << 20)) & 0xffffffff; } srand(seed); parse_descriptions(&d); io_init_terminal(); init_dungeon(&d); if (do_load) { read_dungeon(&d, load_file); } else if (do_image) { read_pgm(&d, pgm_file); } else { gen_dungeon(&d); } config_pc(&d); gen_monsters(&d); gen_objects(&d); pc_observe_terrain(d.PC, &d); io_display(&d); io_queue_message("Seed is %u.", seed); while (pc_is_alive(&d) && dungeon_has_npcs(&d) && !d.quit) { do_moves(&d); } io_display(&d); io_reset_terminal(); if (do_save) { if (do_save_seed) { /* 10 bytes for number, dot, extention and null terminator. */ save_file = (char *) malloc(18); sprintf(save_file, "%ld.rlg327", seed); } if (do_save_image) { if (!pgm_file) { fprintf(stderr, "No image file was loaded. Using default.\n"); do_save_image = 0; } else { /* Extension of 3 characters longer than image extension + null. */ save_file = (char *) malloc(strlen(pgm_file) + 4); strcpy(save_file, pgm_file); strcpy(strchr(save_file, '.') + 1, "rlg327"); } } write_dungeon(&d, save_file); if (do_save_seed || do_save_image) { free(save_file); } } printf("%s", pc_is_alive(&d) ? victory : tombstone); printf("You defended your life in the face of %u deadly beasts.\n" "You avenged the cruel and untimely murders of %u " "peaceful dungeon residents.\n", d.PC->kills[kill_direct], d.PC->kills[kill_avenged]); if (pc_is_alive(&d)) { /* If the PC is dead, it's in the move heap and will get automatically * * deleted when the heap destructs. In that case, we can't call * * delete_pc(), because it will lead to a double delete. */ character_delete(d.PC); } delete_dungeon(&d); destroy_descriptions(&d); return 0; }