samedi 26 septembre 2015

Rand() generating different values when used in valgrind

I'm trying to randomly generate rooms in a two-dimensional array of size 100x100. If the room being generated collides with an already existing room, it generates new points for the room. The generation code makes sense conceptually, but when I try to run, the program loops endlessly, and checking the log reveals why.

Room created successfully with dimensions x=0, y=0, width=976761120, height=809120052

For some reason, at lines 65-68, inside create_room(), the width and height for the room are being randomly assigned huge numbers, when they should be between 1 and 11. Just for fun, I ran the program through Valgrind using the options --track-origins=yes -v, and I what I found surprised me. Suddenly, the program would run!

Room created successfully with dimensions x=0, y=0, width=0, height=0

While still not exactly what I wanted, this at least prevents an infinite loop of collisions being detected with an impossibly huge room.

So, my question is, why is the code generating such large numbers when executed normally, but generate smaller numbers when in Valgrind?

Here's the code for the program.

#include <time.h>
#include <stdlib.h>
#include "global.h"
#include "draw.h"
#include "log.h"
#include "generate.h"
#define NUM_ROOMS 10
#define ROOM_SIZE 10
#define MAP_HEIGHT 100
#define MAP_WIDTH 100

static struct ROOM* create_room (unsigned int);

struct ROOM {
    int x, y, width, height; 
    int feature;
};

struct ROOM* rooms[NUM_ROOMS] = {NULL};

static FILE* gen_log;

static WINDOW* gen_window;

int** generate_dungeon(unsigned int seed){
    char* log_entry = malloc (80);
    int i = 0, j, k;
    gen_window = create_window (0, 0, LINES, COLS);

    gen_log = log_open (GEN_LOG);
    if (seed == 0){
        time_t t;
        seed = time (&t);
    }
    srand (seed); 
    for (int i = 0; i < NUM_ROOMS; i++){
        rooms[i] = create_room (seed);
        sprintf (log_entry,"Room created successfully with dimensions x=%d, y=%d, width=%d, height=%d\n", rooms[i]->x, rooms[i]->y, rooms[i]->width, rooms[i]->height);
        LOG_DEBUG (gen_log,log_entry);
    }
    LOG_DEBUG(gen_log, "Beginning to draw rooms\n");
    for (i=0;i < NUM_ROOMS;i++){
        sprintf (log_entry, "Drawing room %d\n", i);
        LOG_DEBUG (gen_log, log_entry);
        for (j = rooms[i]->y; j < rooms[i]->y + rooms[i]->height; j++){
            for (k = rooms[i]->x; k < rooms[i]->x + rooms[i]->width; k++){
                sprintf (log_entry, "Clearing %d,%d]\n", j,k);
                LOG_DEBUG (gen_log, log_entry);
                map_array[j][k] = 1;
            }
        }
    }
    destroy_window (gen_window);
}

static struct ROOM* create_room (unsigned int seed){
    int i = 0, flag; 
    srand (seed);
    if (rooms[0] == NULL)
        flag = 0;
    else
        flag = 1;
    char* log_entry = malloc (80);
    struct ROOM* new_room = malloc (sizeof(struct ROOM));
    while (flag){
        draw_notify (gen_window, "Creating room\n");
        new_room->x = (rand() % MAP_WIDTH);
        new_room->y = (rand() % MAP_HEIGHT);
        new_room->width =  (rand() % ROOM_SIZE + 1);
        new_room->height = (rand() % ROOM_SIZE + 1);

        sprintf (log_entry, "New room created with points x=%d, y=%d,width=%d, height=%d\n", new_room->x, new_room->y, new_room->width, new_room->height);
        LOG_DEBUG (gen_log, log_entry);
        draw_notify (gen_window, "Log entry made\n");

        if (new_room->x + new_room->width >= MAP_WIDTH || new_room->y + new_room->height >= MAP_HEIGHT){
            LOG_DEBUG (gen_log, "Room out of bounds\n");
            continue;
        }
        i=0;
        draw_notify(gen_window, "Entering loop\n");
        while (rooms[i] != NULL && i < NUM_ROOMS){
            sprintf (log_entry, "Testing room %d\n", i);
            draw_notify (gen_window, log_entry);
            LOG_DEBUG(gen_log, log_entry);
            if (new_room->x < rooms[i]->x + rooms[i]->width && 
                new_room->x + new_room->width > rooms[i]->x && 
                new_room->y < rooms[i]->y + rooms[i]->height &&
                new_room->y + new_room->height > rooms[i]->y){
                    sprintf (log_entry, "Collision detected with room %d\n", i);
                    draw_notify (gen_window, log_entry);
                    LOG_DEBUG (gen_log, log_entry);
                    flag = 1;
                    break;
            }
            else{
                sprintf (log_entry, "Room %d passed.\n", i);
                flag = 0;
                i++;
            }
        }
        draw_notify(gen_window, "Exited loop\n");
    }
    return new_room;
}




Aucun commentaire:

Enregistrer un commentaire