This might get a little troublesome, please help if u can.
Question: What am I doing wrong? Why wouldn't the first room description print itself?Code://In main.c this line is triggered initial_room = load_level(default_level); //In level.c this line is called, once it is triggered from main // loads a level from a config file and returns a pointer to the starting room room_t *load_level(char *filename) { . . . . . . return room_array; //And some where along the main.c, 2-5 lines later this is called look(0, NULL); //My code is buggy when it hits this point of main.c //This is what look() does // prints out the room description, the exits, and monsters int look(int argc, char **argv) { room_t *r = the_player.current_room; printf("%s\n", r->description); // My code doesn't print out the room description and the_player is inside the globals.h init_player(initial_room); //[B] This is init_player, existing inside main.c void init_player(room_t *starting_room) { the_player.current_room = starting_room; the_player.experience = 0; the_player.level = get_level(the_player.experience); the_player.hp = 10; the_player.max_hp = 10; } //[B] The starting_room is a pointer to the first room in the room_array[\B] //This is how I initialize my room array inside level.c struct room* rooms = malloc(num_rooms * sizeof(struct room)); room_array = &rooms;
This is main.cCode:#include "level.h" #include "common.h" #include "util.h" // array of directio names. must be consistent with the order of the enum // in level.h char *direction_names[] = { "north", "south", "east", "west", "up", "down" }; // loads a level from a config file and returns a pointer to the starting room room_t *load_level(char *filename) { char buf[2048]; char *whitespace = " \t\n"; FILE *levelfile = fopen(filename,"r"); if(levelfile == NULL) { printf("Could not open %s\n", filename); exit(1); } skip_characters(levelfile, whitespace); // get the total number of rooms fgets(buf,256,levelfile); num_rooms = atoi(buf); skip_characters(levelfile, whitespace); // allocate an array for all of the room structs to be stored // store the pointer in the global room_array variable /*** YOUR CODE HERE ***/ // Initialize room_array /*** YOUR CODE HERE ***/ skip_characters(levelfile, whitespace); // one line at a time, read in room description strings and set // the appropriate field in each string's corresponding room struct while(fgets(buf, 256, levelfile), buf[0] != '\n') { /*** YOUR CODE HERE ***/ } skip_characters(levelfile, whitespace); // hook up rooms so that exits point to each other appropriately. // exits should also be set to locked or unlocked as necessary while(fgets(buf, 256, levelfile), buf[0] != '\n' && !feof(levelfile)) { char *words[32]; tokenizer(buf, words, " \t\n"); assert(!strcmp("can-go", words[0]) || !strcmp("cant-go", words[0])); direction dir; switch(words[1][0]) { case 'n': dir = NORTH; break; case 's': dir = SOUTH; break; case 'e': dir = EAST; break; case 'w': dir = WEST; break; case 'u': dir = UP; break; case 'd': dir = DOWN; break; default: printf("%s isn't a direction\n", words[1]); assert(false); } /*** YOUR CODE HERE ***/ } return room_array; // equivalent to a pointer to the first element of the array }
This is commands.cCode:#include "common.h" #include "util.h" char *default_level = "cs61c-world.lvl"; char *usage = "usage: %s [LEVEL_FILE]\n" "LEVEL_FILE will be loaded if provided, otherwise \"%s\" will be used.\n" ; void init_player(room_t *starting_room) { the_player.current_room = starting_room; the_player.experience = 0; the_player.level = get_level(the_player.experience); the_player.hp = 10; the_player.max_hp = 10; } void tick_world(int elapsed_time, bool player_vulnerable) { static int time = 0; static int last_attack_time = 0; const int attack_period = 15; time += elapsed_time; while(time - last_attack_time > attack_period) { // monsters attack every attack_period seconds if(player_vulnerable) { monster_t *attacker; mob_iterator_t *iter = make_mob_iterator(&the_player.current_room->mob); while((attacker = next_monster(iter))) { // does monster attack? 75% chance... if (rand() % 4 <= 0) { printf("The %s tries to %s you, but misses\n", attacker->name,attacker->attack); continue; } printf("The %s %ss you for %d points of damage\n", attacker->name, attacker->attack, attacker->damage); the_player.hp -= attacker->damage; if(the_player.hp <= 0) { printf("that %s was too much for you. you die.\n", attacker->attack); exit(0); } } delete_mob_iterator(iter); } last_attack_time += attack_period; } static int last_spawn_time = 0; const int spawn_period = 120; while(time - last_spawn_time > spawn_period) { if(rand() % MONSTER_RARITY == 0) { for(int i = 0; i < NUM_DIRECTIONS; i++) { exit_t *exit = (the_player.current_room->exits + i); if(exit->dest != NULL && !exit->locked) { spawn_new_monster(&exit->dest->mob); } } } last_spawn_time += spawn_period; } } void print_border(char a, char b, int length) { for(int i = 0; i < length; i++) putchar(i % 2 == 0 ? a : b); putchar('\n'); } int main(int argc, char **argv) { //load level from cmd line arg if(argc > 2) { printf(usage, argv[0], default_level); exit(1); } char *welcome_message = "Welcome to %s, the CS 61C adventure extravaganza!\n"; int border_length = strlen(welcome_message) + strlen(argv[0]) - 3; print_border('-', '=', border_length); printf(welcome_message, argv[0]); print_border('-', '=', border_length); room_t *initial_room = NULL; if(argc == 1) { initial_room = load_level(default_level); assert(initial_room != NULL); for (int i = 0; i < num_rooms; i++) { room_array[i].puzzle.description_fxn = get_puzzle_description(i); room_array[i].puzzle.interact_fxn = get_puzzle_solver(i); } } else { initial_room = load_level(argv[1]); // returns a room array or null } assert(initial_room != NULL); init_player(initial_room); printf("You wake up.\n"); look(0, NULL); // Read-eval-print loop for(;;) { char buf[256]; char *words[32]; int num_words; char delimiters[] = " \t\n"; printf("> "); fflush(stdout); fgets(buf, 256, stdin); if(feof(stdin)) { printf("\n"); break; } num_words = tokenizer(buf, words, delimiters); char *command_name = words[0]; if(command_name == NULL) continue; // try to find a command to do cmd_fxn_t cmd_to_do = lookup_command(command_name); if(cmd_to_do != NULL) { // and do it int elapsed_time = cmd_to_do(num_words, words); tick_world(elapsed_time, is_player_vulnerable(command_name)); } else { printf("Huh?\n"); } } }
PLS help!Code:#include "commands.h" #include "common.h" #include "level.h" #include "monsters.h" #include "game.h" // A name/command pair typedef struct { char *name; cmd_fxn_t fxn; bool player_vulnerable; // Whether or not monsters can attack the player during this command } cmd_entry_t; // commands[] maps command names to command functions cmd_entry_t commands[] = { {"look", look, true}, {"attack", attack, true}, {"dawdle", dawdle, true}, {"wait", dawdle, true}, {"quit", quit, true}, {"exit", quit, true}, {"status", status, true}, {"help", help, true}, {"cast", cast, true}, // TA FUNCTION FOR PUZZLES {"interact", interact, false}, // movement aliases {"go", go, false}, {"walk", go, false}, {"move", go, false}, {"north", go_north, false}, {"n", go_north, false}, {"south", go_south, false}, {"s", go_south, false}, {"east", go_east, false}, {"e", go_east, false}, {"west", go_west, false}, {"w", go_west, false}, {"up", go_up, false}, {"u", go_up, false}, {"down", go_down, false}, {"d", go_down, false}, }; const unsigned int num_commands = sizeof(commands) / sizeof(cmd_entry_t); // finds the command with the given name string in commands[] // returns NULL if the command is not found cmd_fxn_t lookup_command(char *name) { for(int i = 0; i < num_commands; i++) { if(!strcmp(name, commands[i].name)) { return commands[i].fxn; } } return NULL; } bool is_player_vulnerable(char *name) { for(int i = 0; i < num_commands; i++) { if(!strcmp(name, commands[i].name)) { return commands[i].player_vulnerable; } } // We have no out-of-bandwidth failure value, so just bail assert(false); return false; // to avoid a compiler error } // prints the player's status int status(int argc, char **argv) { printf("level: %d\n", get_level(the_player.experience)); printf("exp: %d\n", the_player.experience); printf("hp: %d/%d\n", the_player.hp, the_player.max_hp); i_love_additional_status_its_so_bad(); return STATUS_TIME; } // attacks the first monster of monster type argv[1] int attack(int argc, char **argv) { if(argc == 1) { printf("Please specify a monster to attack.\n"); return 0; } // find the monster monster_t *target = find_monster(&the_player.current_room->mob, argv[1]); // give up if we can't find it if(target == NULL) { printf("There's no %s here...\n", argv[1]); return 0; } // inflict damage int damage_amount = the_player.level; printf("You attack the %s for %d damage...\n", target->name, damage_amount); damage(target, damage_amount); return ATTACK_TIME; } // waits for the specified number of seconds (15 by default) int dawdle(int argc, char **argv) { int amount = argc == 2 ? atoi(argv[1]) : DAWDLE_DEFAULT_TIME; printf("You %s for %d seconds...\n", argv[0], amount); return amount; } // prints out the room description, the exits, and monsters int look(int argc, char **argv) { room_t *r = the_player.current_room; printf("%s\n", r->description); if(r->puzzle.description_fxn != NULL) { r->puzzle.description_fxn(argc, argv); } int num_exits = 0; for(int i = 0; i < NUM_DIRECTIONS; i++) { if(r->exits[i].dest != NULL) { num_exits++; } } switch(num_exits) { case 0: break; case 1: for(int i = 0; i < NUM_DIRECTIONS; i++) { if(r->exits[i].dest != NULL) { printf("There is an exit %s%s%s%s.\n", (i == UP || i == DOWN) ? "" : "to the ", direction_names[i], (i == UP || i == DOWN) ? "wards" : "", r->exits[i].locked ? " (locked)" : ""); break; } } break; default: printf("There are exits"); int exits_remaining = num_exits; int i = 0; while(exits_remaining) { if(r->exits[i].dest != NULL) { exits_remaining--; printf(" %s%s%s", direction_names[i], r->exits[i].locked ? " (locked)" : "", exits_remaining == 1 ? " and" : exits_remaining == 0 ? ".\n" : "," ); } if(exits_remaining == 0) break; i++; } } if(num_monsters(&r->mob) > 0) { print_monsters(&r->mob); } return LOOK_TIME; } // calls the puzzle function for the current room int interact(int argc, char **argv) { if (the_player.current_room->puzzle.interact_fxn != NULL) { return the_player.current_room->puzzle.interact_fxn(argc, argv); } else { printf("There is no puzzle in this room.\n"); return INTERACT_TIME; } } // quit the game int quit(int argc, char **argv) { printf("goodbye!\n"); exit(0); } int help(int argc, char **argv) { printf("available commands:\n"); unsigned int num_commands = sizeof(commands) / sizeof(cmd_entry_t); for (int i = 0; i < num_commands; i++) { printf("\t%s\n",commands[i].name); } return HELP_TIME; } // go moves the player from room to room by updating the_player.current_room // and returns the amount of time movement has taken // the argc and argv[] arguments are passed similarly to command-line arguments // a typical "go" command would be: // > go north // and would be passed in as: // argc = 2, argv = {"go", "north"} int go(int argc, char **argv) { /*** YOUR CODE HERE ***/ printf("What's this!? You can't move! You'll need to implement the go() function before you can get out of this place...\n"); // print the room description assert(look(0, NULL) == 0); // we're assuming that look doesn't take any time return MOVE_TIME; } // cast() handles spellcasting // uses get_spell() to check level_table[] in game.c for a spell name that matches argv[1] // and acquire the corresponding function pointer // uses get_spell_level() to check that the spell's level is <= the player's level before casting // this function should return whatver the spell itself returns. int cast(int argc, char **argv) { // for part 3, remove this line printf("Cast? There's no such thing as magic...\n"); return 0; }


