/* we change some priorities of the values before starting our backtrack */
void board_optimize(Board *board)
{
    for (int row = 1; row < board->height - 1; row++)
    {
        for (int col = 1; col < board->width - 1; col++)
        {
            Cell *cell = board_get_cell(board, row, col);
            // Initial values of the corners
            if ((row == 1 && col == 1) || (row == 1 && col == board->width - 2) || (row == board->height - 2 && col == 1) || (row == board->height - 2 && col == board->width - 2))
            {
                if (cell->degree == 1)
                {
                    board_set_priority(board, cell, 1);
                }
            } //values of the edges - corners
            else if (row == 1 || col == 1 || row == board->height - 2 || col == board->width - 2)
            {
                if (cell->degree == 4)
                {
                    board_set_priority(board, cell, 1);
                    for (int i = 0; i < 4; i++)
                    {
                        Cell *neighbour = board_iter_neighbours(board, cell, i);
                        if (neighbour)
                        {
                            board_set_priority(board, neighbour, 1);
                        }
                    }
                }
            }
        }
    }
}
/* We get the next cell for assignation, TODO: implement heuristics ordering */
Cell *board_next_assignation(Board *board)
{
    for (int row = 1; row < board->height - 1; row++)
    {
        for (int col = 1; col < board->width - 1; col++)
        {
            Cell * cell = board_get_cell(board, row, col);
            if (cell -> status == 0)
            {
                return cell;
            }
        }
    }
    return NULL;
    if (board->stack_a->count)
    {
        return stack_pop(board->stack_a);
    }
    else if (board->stack_b->count)
    {
        return stack_pop(board->stack_b);
    }
    else
    {
        return NULL; // in case we don't have any assignations left
    }
}
/* Set the status of a given cell
 * with each assignation, we update the grafical interface and
 * update the count of the neighbours used in the neighbours branch prune
 * TODO: remove grafical interface update for performance? check this
 */
void board_set_status(Board *board, int row, int col, int status)
{
    Cell *cell = board_get_cell(board, row, col);
    int old_status = cell->status;
    // we first update all of our neighbours with the appropiate info about the change in status
    board_update_neighbours(board, cell, old_status, status);
    cell->status = status;
    // we re-prioritize the neighbours and the cell, depending if it's empty or not
    // board_update_heuristics(board, cell);
    if (status)
    {
        if (old_status == 0)
        {
            board->count_empty -= 1;
        }
        watcher_set_cell_status(row, col, status - 1);
    }
    else
    {
        // TODO change this to work with two stacks
        if (cell->priority == 1)
        {
            stack_push(board->stack_a, cell);
        }
        else
        {
            stack_push(board->stack_b, cell);
        }
        board->count_empty += 1;
        watcher_clear_cell(row, col);
    }
}
Esempio n. 4
0
/*
 * Displays the current board in a curses window
 *
 * Parameters: const World_t* world, Lens_t* lens, WINDOW* display_area
 * Return: void
 */
void display_curses(const World_t* world, Lens_t* lens, WINDOW* window)
{
    int x, y;
    int display_x, display_y;
    int display_width, display_height;
    int value;
    char display_value;

    // determine terminal's rows and columns. Display cell if in bounds
    getmaxyx(window, display_height, display_width);
    lens_set(lens, world->board, display_width, display_height);
    // clear the display of the old frame
    clear();
    for(y = lens->min_y; y < lens->max_y; y++) {
        for(x = lens->min_x; x < lens->max_x; x++) {
            value = board_get_cell(world->board, x, y);
            // Adjust display coordinates by the BOARD_BORDER_SIZE offset
            display_x = x - lens->x_display_offset;
            display_y = y - lens->y_display_offset;
            move(display_y, display_x);
            // display o for each living cell within the terminal
            if (display_y < display_height && display_x < display_width) {
                display_value = world->rule->state_chars[value];
                if (display_value != ' ') {
                    insch(display_value);
                }
            }
        }
    }
    refresh();
}
/* Create our board and return a pointer to our object */
Board *board_init(int height, int width)
{
    Board *board = malloc(sizeof(Board));
    board->height = height;
    board->width = width;
    board->count_empty = 0;
    board->count_loyalist = 0;
    board->count_rebel = 0;
    board->count_empty = height * width;
    /* We allocate enough memory for the cells in our board
     * we store a simple array of pointers and use basic arithmetic two get the correct cell
     */
    board->cells = (Cell *)malloc(board->height * board->width * sizeof(Cell));
    board->stack_a = stack_init();
    board->stack_b = stack_init();
    /* We set the initial values of the cells in our board
     * on the first pass we just create an empty board
     */
    for (int row = 0; row < board->height; row++)
    {
        for (int col = 0; col < board->width; col++)
        {
            Cell *cell = board_get_cell(board, row, col);
            cell->row = row;
            cell->col = col;
            cell->loyals = 0;
            cell->rebels = 0;
            cell->color = 0;
            cell->degree = 0;
            cell->empty = 4;
            cell->status = 0;
            // Initial values of the corners
            if ((!row && !col) || (!row && col + 1 == board->width) || (row + 1 == board->height && !col) || (row + 1 == board->height && col + 1 == board->width))
            {
                cell->empty = 2;
            } //values of the edges - corners
            else if (!row || !col || row + 1 == board->height || col + 1 == board->width)
            {
                cell->empty = 3;
            }
            else
            {
                stack_push(board->stack_b, cell);
            }
        }
    }
    for (int row = 0; row < board->height; row++)
    {
        for (int col = 0; col < board->width; col++)
        {
            if (!row || !col || row + 1 == board->height || col + 1 == board->width)
            {
                board_set_status(board, row, col, 1);
            }
        }
    }
    return board;
}
/* Helper function to return upper neighbour, returns NULL if it doesn't have one */
Cell *board_upper_neighbour(Board *board, Cell *cell)
{
    Cell *neighbour = NULL;
    if (cell->row >= 1)
    {
        neighbour = board_get_cell(board, cell->row - 1, cell->col);
    }
    return neighbour;
}
/* Used when creating out board, we set the apropiate info */
void board_set_degree(Board *board, int row, int col, int degree)
{
    Cell *cell = board_get_cell(board, row, col);
    cell->degree = degree;
    if (cell->degree > 0)
    {
        watcher_set_cell_degree(row, col, cell->degree);
    }
}
/* Helper function to return bottom neighbour, returns NULL if it doesn't have one */
Cell *board_bottom_neighbour(Board *board, Cell *cell)
{
    Cell *neighbour = NULL;
    if (cell->row < board->height - 1)
    {
        neighbour = board_get_cell(board, cell->row + 1, cell->col);
    }
    return neighbour;
}
/* Helper function to return right neighbour, returns NULL if it doesn't have one */
Cell *board_right_neighbour(Board *board, Cell *cell)
{
    Cell *neighbour = NULL;
    if (cell->col < board->width - 1)
    {
        neighbour = board_get_cell(board, cell->row, cell->col + 1);
    }
    return neighbour;
}
/* Helper function to return left neighbour, returns NULL if it doesn't have one */
Cell *board_left_neighbour(Board *board, Cell *cell)
{
    Cell *neighbour = NULL;
    if (cell->col >= 1)
    {
        neighbour = board_get_cell(board, cell->row, cell->col - 1);
    }
    return neighbour;
}
/* Debuging function */
void board_print_empty_count(Board *board)
{
    for (int row = 0; row < board->height; row++)
    {
        for (int col = 0; col < board->width; col++)
        {
            printf("%d ", board_get_cell(board, row, col)->empty);
        }
        printf("\n");
    }
    printf("\n");
}
Esempio n. 12
0
/*
 * Determines the next state of a cell at x, y in the board of the given
 * `world` and applies it to next_board according to the world's rule.
 */
void handle_transition_rule(World_t* world, int x, int y)
{
    int num_neighbors;
    Transition_t* transition;
    int index;
    unsigned char current_cell;
    int i, j;
    bool changed = false;

    index = y * world->board->width + x;
    current_cell = board_get_cell(world->board, x, y);
    // Go through each transition rule
    for (i = 0; i < world->rule->transition_length; i++) {
        transition = world->rule->transitions[i];
        if (current_cell == transition->begin) {
            // If the rule involves neighbor counting
            if (transition->size > 0) {
                num_neighbors = world->rule->neighbor_func(
                    world->board, x, y, transition->neighbor_state
                );
                for (j = 0; j < transition->size; j++) {
                    // Apply transition if count of neighbors matches
                    // any in the list
                    if (!transition->negator) {
                        if (num_neighbors == transition->transitions[j]) {
                            world->next_board->cells[index] = transition->end;
                            changed = true;
                            break;
                        }
                    } else {
                        // Make the transition *unless* the right
                        // number of neighbors are present
                        changed = true;
                        world->next_board->cells[index] = transition->end;
                        if (num_neighbors == transition->transitions[j]) {
                            world->next_board->cells[index] = current_cell;
                            break;
                        }
                    }
                }
            } else {
                // Rule should occur regardless of neighbors
                world->next_board->cells[index] = transition->end;
                changed = true;
            }
        }
    }
    // The cell is unchanged so far, just copy the old value
    if (!changed) {
        world->next_board->cells[index] = current_cell;
    }
}
Esempio n. 13
0
static int proc_board_read (char *page, char **start, off_t off,
			    int count, int *eof, void *data)
{
	struct klife_board *board = data;
	int x, y;
	int val;
	char *p = page;

	*start = p;

	/* calculate starting point to dump board */
	x = off % (board->side + 1);
	y = off / (board->side + 1);

	if (y >= board->side) {
		*eof = 1;
		return 0;
	}

	while (y < board->side) {
		while (x < board->side) {
			val = board_get_cell (board, x, y);
			*p = val ? '#' : '.';
			p++;
			x++;
			count--;
			if (count <= 0)
				goto finish;
		}

		*p = '\n';
		p++;
		count--;
		x = 0;
		y++;
		if (count <= 0)
			goto finish;
	}

	*eof = 1;

finish:
	return p - page;
}
/* Neighbour prunning, we iter through the cell and its neighbours calling cell_degree_check */
bool board_degree_prune(Board *board, int row, int col)
{
    Cell *cell = board_get_cell(board, row, col);
    // first we check the cell its self
    if (!cell_degree_check(cell))
    {
        return false;
    }
    for (int i = 0; i < 4; i++)
    {
        Cell *neighbour = board_iter_neighbours(board, cell, i);
        if (neighbour)
        {
            //printf("checking neighbour:\n");
            //board_print_cell(neighbour);
            if (!cell_degree_check(neighbour))
            {
                return false;
            }
        }
    }
    return true;
}
/* Get the current status of a given cell */
int board_get_status(Board *board, int row, int col)
{
    Cell *cell = board_get_cell(board, row, col);
    return cell->status;
}
Esempio n. 16
0
//! handles mouse clicks as well as key presses
gint board_signal_handler (GtkWidget *widget, GdkEventButton *event, 
		gpointer data)
/* FIXME: clean up this function */
{
	int row, col, pixel_x, pixel_y, type;
	int status = 0;
	byte *move = NULL;
	int *rmove = NULL;
	GtkboardEvent our_event;
	MoveInfo minfo = {NULL, NULL, NULL, NULL, NULL};
	if (!opt_game) return FALSE;
	if (ui_gameover) return FALSE;
	if (event->type == GDK_KEY_PRESS && 
			!(((GdkEventKey *)event)->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
	{
		if (!game_getmove_kb && !game_event_handler) return FALSE;
		if (game_event_handler) 
		{
			our_event.type = GTKBOARD_KEY_PRESS;
			our_event.key = ((GdkEventKey *)event)->keyval;
			status = game_event_handler (&cur_pos, &our_event, &minfo);
			move = minfo.move;
			rmove = minfo.rmove;
		}
		else //(if game_getmove_kb)
			status = game_getmove_kb (&cur_pos, 
				((GdkEventKey *)event)->keyval, &move, &rmove);
	}
	else
	{
		if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE)
		{
			if (player_to_play != HUMAN)
			{
				sb_message ("Machine's turn", FALSE);
				return FALSE;
			}
			if (!impl_check()) { sb_error ("Not yet implemented", TRUE); 
				return FALSE; }
		}
		if (!game_getmove && !game_event_handler) {return FALSE;}
		board_get_cell (event, &row, &col, &pixel_x, &pixel_y);
		if (!(row >= 0 && row < board_wid)) return FALSE;
		if (!(col >= 0 && col < board_heit)) return FALSE;
		switch (event->type)
		{
			case GDK_BUTTON_PRESS:
				type = GTKBOARD_BUTTON_PRESS; break;
			case GDK_BUTTON_RELEASE:
				type = GTKBOARD_BUTTON_RELEASE; break;
			case GDK_MOTION_NOTIFY:
				type = GTKBOARD_MOTION_NOTIFY; break;
			case GDK_LEAVE_NOTIFY:
				type = GTKBOARD_LEAVE_NOTIFY; break;
			default:
				return FALSE;
		}
		if (game_event_handler)
		{
			our_event.type = type;
			our_event.x = row;
			our_event.y = col;
			our_event.pixel_x = pixel_x;
			our_event.pixel_y = pixel_y;
			status = game_event_handler (&cur_pos, &our_event, &minfo);
			move = minfo.move;
			rmove = minfo.rmove;
		}
		else
			status = game_getmove (&cur_pos, row, col, 
					type, cur_pos.player, &move, &rmove);
		if (status < 0)
		{
			gchar *tmpstr = minfo.help_message ? 
				g_strdup_printf ("Illegal move: %s", minfo.help_message) 
				: g_strdup_printf ("Illegal move");
			sb_error (tmpstr, FALSE);
			g_free (tmpstr);
			sound_play (SOUND_ILLEGAL_MOVE);
		}
	}
	if (status <= 0)
	{
		ui_make_human_move (NULL, rmove);
		if (rmove)
			menu_start_stop_game (NULL, MENU_START_GAME); 
		return FALSE;
	}
	sound_play (SOUND_USER_MOVE);
	menu_start_stop_game (NULL, MENU_START_GAME); 
	ui_make_human_move (move, rmove);
	return FALSE;
}
/* Get the degree of a given cell */
int board_get_degree(Board *board, int row, int col)
{
    Cell *cell = board_get_cell(board, row, col);
    return cell->degree;
}
/* DFS prunning to check if we have more than one group per status, we return true if it is, false in another case */
bool board_check_groups(Board *board)
{
    /* color 0: unvisited node (white)
     * color 1: visited   node (grey)
     * color 2: closed    node (black)
     */
    // Starting params
    board_reset_color(board);
    board->count_loyalist = 0;
    board->count_rebel = 0;

    /* Pointer to the first cell that we find that is rebel */
    Cell *rebel = NULL;

    /* We add the top right corner to the stack, which is garanteed to be a loyalist cell */
    Stack *stack = stack_init();
    stack_push(stack, board_get_cell(board, 0, 0));

    /* We count the loyalist cells first */
    Cell *current_cell = stack_pop(stack);
    current_cell->color = 1;
    board->count_loyalist += 1;

    while (current_cell)
    {
        current_cell->color = 2;
        dfs_search_neighbours(board, current_cell, stack, &rebel, 1);
        current_cell = stack_pop(stack);
    }
    board_reset_color(board);
    /* Now we count the rebel cells starting from the pointer to rebel 
     * empty cells are being counted twice, we also check if any rebel cells 
     * have been assigned
     */
    if (rebel != NULL)
    {
        current_cell = rebel;
        current_cell->color = 1;
        board->count_rebel += 1;
        while (current_cell)
        {
            current_cell->color = 2;
            dfs_search_neighbours(board, current_cell, stack, &rebel, 2);
            current_cell = stack_pop(stack);
        }
    }

    // free the memmory from our stack
    stack_destroy(stack);

    // return our value
    //printf("count empty: %d\n", board->count_empty);
    //printf("count rebels: %d\n", board->count_rebel);
    //printf("count loyals: %d\n", board->count_loyalist);
    if (board->count_empty + board->count_rebel + board->count_loyalist == board->width * board->height)
    {
        return true;
    }
    else
    {
        return false;
    }
}
/* Set the color of a given cell */
void board_set_color(Board *board, int row, int col, int color)
{
    Cell *cell = board_get_cell(board, row, col);
    cell->color = color;
}
/* Get the color of a given cell */
int board_get_color(Board *board, int row, int col)
{
    Cell *cell = board_get_cell(board, row, col);
    return cell->color;
}