Thread: Lost, need help again~

  1. #1
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73

    Lost, need help again~

    This might get a little troublesome, please help if u can.



    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;
    Question: What am I doing wrong? Why wouldn't the first room description print itself?

    Code:
    #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 main.c
    Code:
    #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");
            }
        }
    }
    This is commands.c

    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;
    }
    PLS help!
    Last edited by NoobieGecko; 02-16-2008 at 11:09 PM.

  2. #2
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    Because i always liked this games i 'll try.
    I'll start working on it, and fill you up with details later in 30 minutes at least.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  3. #3
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    So far i have done this:
    Code:
        // allocate an array for all of the room structs to be stored
        // store the pointer in the global room_array variable
    
        room_array = malloc(num_rooms * sizeof(*room_array));
        // Initialize room_array   <- To what? Clear memory?
    
        memset(room_array, 0, num_rooms * sizeof(*room_array));
    Code:
    
        // Before the while you need a counter.
        cur_room = 0;	// The room being read in.
    
        while(fgets(buf, 256, levelfile), buf[0] != '\n') {
    		/*** YOUR CODE HERE ***/
    
    	// I recall you had a pointer that was pointing at the description, named rest
    	if(rest[strlen(rest)-1] == '\n')
    		rest[strlen(rest)-1] = 0;
    	room_array[cur_room]->description = malloc(strlen(rest)+1);
    	strcpy(room_array[cur_room]->description, rest);
    	cur_room++;
        }
    WAIT A MINUTE!
    Is room_array an array of POINTERS to room_t structures???
    This is very important, as the allocation needs to be done differently.
    Please respond for further assistance.
    Last edited by xuftugulus; 02-17-2008 at 12:17 AM.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  4. #4
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    well i tested it, and i got an error with -> operators
    Code:
    level.c: In function `load_level':
    level.c:59: error: incompatible types in assignment
    level.c:69: error: invalid type argument of `->'
    level.c:70: error: invalid type argument of `->'
    level.c:72: error: invalid type argument of `->'
    level.c:73: error: invalid type argument of `->'
    level.c:75: error: invalid type argument of `->'
    level.c:76: error: invalid type argument of `->'
    level.c:157: error: invalid type argument of `->'
    level.c:159: error: invalid type argument of `->'
    level.c:161: error: invalid type argument of `->'
    level.c:163: error: invalid type argument of `->'
    and it's because:

    room_t *room_array;

    should be **room_array?

    what i have is actually this:

    struct room** rooms = (room_t **) malloc(num_rooms * sizeof(room_t *));

    which kind of works~

    (i sent u a pm)

  5. #5
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    wait wait wait!!

    room_array points to the first element of a data structure where that structure is an array of structures of (room_t)!

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,794
    No need of pointer to pointer
    just instead of
    room_array[cur_room]->description
    use
    room_array[cur_room].description

    because [] already dereferences the pointer and gives you the struct
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    David J. Wheeler

  7. #7
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    exactly but this is what i found out later
    Code:
    int look(int argc, char **argv) {
        room_t *r = the_player.current_room;
        printf("&#37;s\n", r->description);
    which calls r->description (r is primarily room_array, the first element of the array of room structs) is this right?

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,794
    r is pointer to the first element
    so r->description is equivalent to
    r[0].description

    as well as r[i].description
    you can substitute with
    (r+i)->description

    but the "array" notaition is more readable, I think
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    David J. Wheeler

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by NoobieGecko View Post
    exactly but this is what i found out later
    Code:
    int look(int argc, char **argv) {
        room_t *r = the_player.current_room;
        printf("%s\n", r->description);
    which calls r->description (r is primarily room_array, the first element of the array of room structs) is this right?
    r is a pointer to a room_t: the declaration's right there in the function. So here you need the -> to get the description in the object pointed to by r. (And you need it that way 'cuz that's what the_player holds: not the room itself, but a pointer to the room that the player is in.)

    I think the problem xuf was pointing out was this:
    // Initialize room_array
    /*** YOUR CODE HERE ***/
    At no point, that I can see anyway, do you actually read data from the file and put it into this room_array of yours. (Maybe I just missed it.)

  10. #10
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    Quote Originally Posted by NoobieGecko View Post
    exactly but this is what i found out later
    Code:
    int look(int argc, char **argv) {
        room_t *r = the_player.current_room;
        printf("&#37;s\n", r->description);
    which calls r->description (r is primarily room_array, the first element of the array of room structs) is this right?
    Code:
     // the struct representing a player
    typedef struct {
         room_t *current_room;    // In the player is stored a pointer to a room_t
         unsigned experience;
         unsigned level;
         int hp;
         int max_hp;
    } player_t;
    Therefore, when accessing through the player_t, you need to use -> , also:
    In function calls that need a room_t it is usual to pass a pointer to a room_t because otherwise a copy of the entire struct would be passed which usually is not wanted.

    I managed to compile this, with the original data file of the game.
    Code:
        // allocate an array for all of the room structs to be stored
    	// store the pointer in the global room_array variable
    	/*** YOUR CODE HERE ***/
    	room_array = malloc(num_rooms * sizeof(*room_array));
        // Initialize room_array
    	/*** YOUR CODE HERE ***/
    	int room_idx = 0;  /* MOVE THESE 2 TO THE DECLARATIONS AT THE START*/
    	char *c;
        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 ***/
    		room_array[room_idx].room_id = atoi(buf);
    		c = buf;
    		assert(strchr(whitespace,*c)==NULL);
    		while(*c!=' ' && *c!='\n' && *c!='\t') c++;	// Skip the digits of the room id. This covers you even if more than 1...
    		if(c[strlen(c)-1] == '\n')
    			c[strlen(c)-1] = 0;						// Kill the newline
    		room_array[room_idx].description = malloc(strlen(c)+1);   // Make room for copying the description
    		strcpy(room_array[room_idx].description, c);   //Read the reference for strcpy. It copies 0 terminated strings. Memory handled by user.
    // Another way to copy: room_array[room_idx].description = strdup(c);
    //printf("Got id: %d, descr: %s\n", room_array[room_idx].room_id, room_array[room_idx].description);
    		room_idx++;
        }
    Last edited by xuftugulus; 02-17-2008 at 01:32 AM.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  11. #11
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    sorry, i'm am trying to be less confusing as i can, this is so far what i have written
    Code:
    #include "level.h"
    #include "common.h"
    #include "util.h"
    #include "string.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 &#37;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
    
        struct room** rooms = (room_t **) malloc(num_rooms * sizeof(room_t *));
        room_array = &rooms;
        
        for (int j = 0; j < num_rooms; j++)
    	{
    	    rooms[j] = malloc(sizeof(room_t*));
    	}
    
        
        for (int i = 0; i < num_rooms-1; i++)
    
    	{
    	   
    	    rooms[i]->room_id = NULL;	    
    	    rooms[i]->description = NULL;
    	    for (int j = 0; j < 6; j++){
    		rooms[i]->exits[j].dest = NULL;
    		rooms[i]->exits[j].locked = 0;
    	    }
    	    rooms[i]->puzzle.description_fxn = NULL;
    	    rooms[i]->puzzle.interact_fxn = NULL;    
    	}
        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
    
     
        
        int t = 0; 
        
        while(fgets(buf, 256, levelfile), buf[0] != '\n') {
         	char *numptr = NULL;
    	char *newline = strchr(buf, '\n');
    	if (newline)
    	    {
    		*newline = '\0';
    	    }
    	
    	numptr = strtok(buf, whitespace);
          
    	if (numptr != NULL) {
    	    rooms[t]->room_id = atoi(&buf[0]);
    	    //	    char temp[] = malloc(sizeof(&buf[2]));
    	    //strcpy(NULL, &buf[2]);
    	    // printf("%s\n", &temp);
    	    rooms[t]->description = "I dont know how to do this";
    	    //printf("%s", rooms[t]->description);
    	    t++;
    	}
    	
    	    
        }
       
        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);
    	}
           
    	int FROM_ROOM;
    	int TO_ROOM;
    	FROM_ROOM = atoi(&words[2][0]);
    	TO_ROOM = atoi(&words[3][0]);
    	rooms[FROM_ROOM]->exits[TO_ROOM].dest = &rooms[TO_ROOM];
    	if (strcmp("cant-go", words[0])) {
    	    rooms[FROM_ROOM]->exits[TO_ROOM].locked = 1;
    	}
           	rooms[TO_ROOM]->exits[FROM_ROOM].dest = &rooms[FROM_ROOM];
    	if (strcmp("can-go", words[0])) {
    	    rooms[FROM_ROOM]->exits[TO_ROOM].locked = 0;
    	
    	}	
        }
        //    printf("%s", rooms[0]->description);
        return room_array; // equivalent to a pointer to the first element of the array
    }
    the problem i'm having is right hereeeeeee
    Code:
        while(fgets(buf, 256, levelfile), buf[0] != '\n') {
         	char *numptr = NULL;
    	char *newline = strchr(buf, '\n');
    	if (newline)
    	    {
    		*newline = '\0';
    	    }
    	
    	numptr = strtok(buf, whitespace);
          
    	if (numptr != NULL) {
    	    rooms[t]->room_id = atoi(&buf[0]);
    	    //	    char temp[] = malloc(sizeof(&buf[2]));
    	    //strcpy(NULL, &buf[2]);
    	    // printf("%s\n", &temp);
    	    rooms[t]->description = "I dont know how to do this";
    	    //printf("%s", rooms[t]->description);
    	    t++;
    	}
    	
    	    
        }
    how do u store the description inside rooms[t]->description?

  12. #12
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    oh so u don't necessarily need "**"?

    brb: as i try to compile this, there's the last part of the main code that gives me segmentation faults, fixin it atm...
    Last edited by NoobieGecko; 02-17-2008 at 01:19 AM.

  13. #13
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    You have confused the nested structures.
    Pleases look at the types.
    A room_t object has an exit_t object, which contains a pointer to a room_t and a boolean flag.
    You wake up.
    You are in a cold, concrete-floored room. There are no windows and almost no light. The only thing you can make out is the faint outline of a door to the south.
    There is an exit to the south.
    >
    That's on my machine.
    And here's the code i used.
    Code:
    		bool locked = strcmp("can-go",words[0]);   // Returns 0 when equal same as false for 'C'
    		int from,to;
    		from = atoi(words[2]);   // No need for & it's a nice string words[2] :)
    		to = atoi(words[3]);
    /* Not the check to avoid indexing out of bounds in our array */
    		if( from<0 || from>num_rooms || to<0 || to>num_rooms)
    		{
    			printf("Invalid number detected. Skipping line: From: &#37;d - To: %d\n",from,to);
    			continue;
    		}
    /* The trick is that the only place you need to use & is to store the pointer in the exit structure */
    		room_array[from].exits[dir].dest = &room_array[to];
    		room_array[from].exits[dir].locked = locked;
    I think i read the file just fine. The advice, have the header files always open at the definition of
    the types. When you see room_t *x, then x->description is the string. When you see room_t then x.description is the string. When you see room_array[i] this is a full struct, not a pointer to it.
    how do u store the description inside rooms[t]->description?
    Check my post it's modified.
    I had made a typo! It must be strlen(c)+1, i had written strlen(c)-1 which means two less bytes of memory. I didn't get any segmentation fault and missed it. My bad there. Sorry.
    Last edited by xuftugulus; 02-17-2008 at 01:34 AM.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  14. #14
    Stressed Student :(
    Join Date
    Feb 2008
    Location
    Berkeley, CA
    Posts
    73
    thats the right output, thanks xuft, but the problem i'm having now is a segfault, and when i run gdb and i backtrace, i pick up this

    Code:
           room_array[room_idx].description = malloc(strlen(c)-1);

  15. #15
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,794
    you should check the room_idx value - it should be in range 0,num_rooms -1

    If it is not - you access memory out of bound which can lead to crash
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. (Date dt)??? I'm lost...
    By patricio2626 in forum C++ Programming
    Replies: 3
    Last Post: 06-24-2006, 11:49 AM
  2. I lost my laptop, DVD and money
    By Sang-drax in forum A Brief History of Cprogramming.com
    Replies: 21
    Last Post: 10-01-2004, 07:13 PM
  3. lost disk
    By Benzakhar in forum Linux Programming
    Replies: 7
    Last Post: 01-11-2004, 06:18 PM
  4. Lost ID number
    By ripper079 in forum C++ Programming
    Replies: 13
    Last Post: 10-04-2002, 12:51 PM
  5. API, LOST... help
    By Unregistered in forum Windows Programming
    Replies: 5
    Last Post: 03-13-2002, 03:19 PM