···
struct WinningBoardCollection
MakeMoveResult make_move_table_partial[2][MAKE_MOVE_TABLE_PARTIAL_SIZE];
MakeMoveResult make_move_table_full[2][MAKE_MOVE_TABLE_FULL_SIZE];
+
const uint8_t CHECK_FOR_WIN_PROCESSED_COLUMN_TABLE_SIZE = MAX_FULL_COLUMN + 1;
uint8_t check_for_win_processed_column_table[2][CHECK_FOR_WIN_PROCESSED_COLUMN_TABLE_SIZE];
+
WinningBoardCollection check_for_win_processed_winning_boards_table[NUM_ROWS][NUM_COLUMNS];
void init_board(BoardState state)
+
for (uint8_t col = 0; col < NUM_COLUMNS; ++col)
···
inline int8_t get_board_value(BoardState state, uint8_t row, uint8_t col)
+
assert(row < NUM_ROWS && col < NUM_COLUMNS);
return state[col] < (1 << (row + 1)) ? -1 : ((state[col] & (1 << row)) >> row);
int8_t make_move_column(uint8_t player, uint8_t* column_state)
+
if (*column_state >= MIN_FULL_COLUMN)
uint8_t mask = *column_state; // 0011 0000 (example)
···
+
inline binary_board bit_set(binary_board num, uint8_t row, uint8_t col)
+
return num | ((binary_board)1 << (col * 8 + (row)));
···
for (uint8_t player = 0; player < 2; ++player)
make_move_table_partial[player][0] = MakeMoveResult { -1, 0 };
+
for (uint8_t column_state = 1; column_state < MAKE_MOVE_TABLE_PARTIAL_SIZE; ++column_state)
result.column_state = column_state;
···
// Building check_for_win winning board lookup table
+
for (uint8_t table_row = 0; table_row < NUM_ROWS; ++table_row)
+
for (uint8_t table_col = 0; table_col < NUM_COLUMNS; ++table_col)
+
binary_board boards[32];
+
for (uint8_t row_start = 0; row_start <= (NUM_ROWS - NUM_TO_WIN); ++row_start)
+
binary_board winning_board_state = 0;
+
for (uint8_t row_offset = 0; row_offset < NUM_TO_WIN; ++row_offset)
winning_board_state = bit_set(winning_board_state, row_start + row_offset, table_col);
···
+
for (uint8_t col_start = 0; col_start <= (NUM_COLUMNS - NUM_TO_WIN); ++col_start)
+
binary_board winning_board_state = 0;
+
for (uint8_t col_offset = 0; col_offset < NUM_TO_WIN; ++col_offset)
winning_board_state = bit_set(winning_board_state, table_row, col_start + col_offset);
···
+
while (diag_row + NUM_TO_WIN <= NUM_ROWS && diag_col + NUM_TO_WIN <= NUM_COLUMNS)
+
binary_board winning_board_state = 0;
+
for (uint8_t i = 0; i < NUM_TO_WIN; ++i)
winning_board_state = bit_set(winning_board_state, diag_row + i, diag_col + i);
···
int8_t diag_row = table_row;
uint8_t diag_col = table_col;
+
while (diag_row + 1 < NUM_ROWS && diag_col > 0)
+
while ((diag_row + 1) - NUM_TO_WIN >= 0 && diag_col + NUM_TO_WIN <= NUM_COLUMNS)
+
binary_board winning_board_state = 0;
+
for (uint8_t i = 0; i < NUM_TO_WIN; ++i)
winning_board_state = bit_set(winning_board_state, diag_row - i, diag_col + i);
···
WinningBoardCollection board_collection;
board_collection.num_boards = num_boards;
+
board_collection.boards = (binary_board*)malloc(num_boards * sizeof(binary_board));
+
memcpy(board_collection.boards, boards, num_boards * sizeof(binary_board));
check_for_win_processed_winning_boards_table[table_row][table_col] = board_collection;
···
int8_t make_move(uint8_t player, uint8_t column, BoardState state)
+
assert(column >= 0 && column < NUM_COLUMNS);
return make_move_column(player, &state[column]);
···
bool check_for_win(BoardState state, uint8_t last_move_player, uint8_t last_move_row, uint8_t last_move_col)
assert(last_move_player <= 1);
+
assert(last_move_row < NUM_ROWS && last_move_col < NUM_COLUMNS);
+
uint8_t processed_board_state[NUM_COLUMNS_PROCESSED] = { 0 };
+
for (uint8_t col = 0; col < NUM_COLUMNS; ++col)
+
assert(state[col] < MAX_FULL_COLUMN + 1);
processed_board_state[col] = check_for_win_processed_column_table[last_move_player][state[col]];
+
binary_board* processed_board_state_binary = (binary_board*)processed_board_state;
WinningBoardCollection winning_boards = check_for_win_processed_winning_boards_table[last_move_row][last_move_col];
for (uint8_t i = 0; i < winning_boards.num_boards; ++i)
+
binary_board winning_board_state = winning_boards.boards[i];
if ((winning_board_state & *processed_board_state_binary) == winning_board_state)
···
+
void get_move_scores(int64_t final_scores[NUM_COLUMNS])
init_board(nodes[0].state);
···
++nodes[depth].curr_move_column;
// If we've checked every column...
+
while (nodes[depth].curr_move_column >= NUM_COLUMNS)
min_depth = depth < min_depth ? depth : min_depth;
···
void sprint_board(BoardState state, char* buffer)
+
for (uint8_t i = 0; i < NUM_COLUMNS; ++i)
+
snprintf(buffer, 256, "_%d", i + 1);
+
snprintf(buffer, 256, "_\n");
+
for (int8_t row = NUM_ROWS - 1; row >= 0; --row)
snprintf(buffer, 256, "|");
+
for (uint8_t col = 0; col < NUM_COLUMNS; ++col)
switch (get_board_value(state, row, col))
···
snprintf(buffer, 256, "\n");
+
for (uint8_t i = 0; i < NUM_COLUMNS; ++i)
+
snprintf(buffer, 256, "--");
+
snprintf(buffer, 256, "‾\n");
void print_board(BoardState state)