diff options
Diffstat (limited to 'include/action_list.c')
| -rw-r--r-- | include/action_list.c | 123 |
1 files changed, 61 insertions, 62 deletions
diff --git a/include/action_list.c b/include/action_list.c index 9afb199..50eb266 100644 --- a/include/action_list.c +++ b/include/action_list.c @@ -6,12 +6,9 @@ static inline action_list_t * action_list_prepend(action_list_t *list, const enum A_TYPE type, - const uint8_t loc, const uint8_t data0, + const int8_t loc, const uint8_t data0, const uint8_t data1); -static inline void inline_previous_ply(void); -static inline void inline_next_ply(void); - // =================================================================== // Exported method implementations // =================================================================== @@ -28,8 +25,7 @@ void action_list_free(action_list_t *list) { // Keep track of move offsets static int8_t deltas[4]; -void action_list_init(const uint8_t new_board_size) { - board_size = new_board_size; +void action_list_init(void) { deltas[0] = +board_size; deltas[1] = -board_size; deltas[2] = -1; @@ -37,24 +33,23 @@ void action_list_init(const uint8_t new_board_size) { } action_list_t *action_list_generate(void) { - action_list_t *result = NULL; - const uint8_t black = (ply & 1), + const uint8_t black = (ply < 2) ? (ply==1) : (ply & 1), material = (black) ? black_count : white_count, flat = material & 127, - cap = (ply > 2 && (material & 128)), - standing = (ply > 2 && (material & 127)); + cap = (ply >= 2 && (material & 128)), + standing = (ply >= 2 && (material & 127)); // Step across the board for (uint8_t row = 0; row < board_size; row++) { for (uint8_t col = 0; col < board_size; col++) { - // We'll need these at various points, the location of this + // We'll need these at various points: the location of this // square and the maximum number of stones we could pick up - const uint8_t loc = THE_COORDS(col, row); + const int8_t loc = THE_COORDS(col, row); const uint8_t count = (COUNT_AT(loc) > board_size) ? board_size : COUNT_AT(loc); // Only try moves after CPS - if (count && ((colours[loc] & 1) == current_colour) && ply>2) { + if (ply >= 2 && count && ((colours[loc] & 1) == current_colour)) { // There are stones, let's try moving them // Pre-compute end-stops @@ -68,12 +63,13 @@ action_list_t *action_list_generate(void) { // Now we check for caps and walls const uint8_t cap_top = STONE_AT(loc) == STONE_CAPSTONE; - for (uint8_t d = 0; d < board_size-1; d++){ + for (uint8_t d = 0; d < 4; d++){ + const int8_t delta = deltas[d]; end_stops[d][1] = 1; const uint8_t stop = end_stops[d][0]; end_stops[d][0] = 0; for (uint8_t k = 1; k <= stop; k++) { - const uint8_t stone = STONE_AT(loc+k*deltas[d]); + const uint8_t stone = STONE_AT(loc+k*delta); if (stone == STONE_STANDING) { if (cap_top) { end_stops[d][1] = 0; @@ -93,13 +89,12 @@ action_list_t *action_list_generate(void) { * summands as steps */ for (enum MOVE_DIRECTION dir = M_UP; dir <= M_RIGHT; dir++) { - uint8_t gaps, t; for (uint8_t num = 1; num <= count; num++) { for (uint8_t steps = 1; steps <= end_stops[dir][0] && steps <= num; steps++) { // TODO: Generalise to board_size! - gaps = 0x07 >> (board_size-steps-1); + uint8_t gaps = 0x07 >> (board_size-steps-1); // 0b0000[0111] because 4-1=3 and 5-1=4 do { /* @@ -109,28 +104,40 @@ action_list_t *action_list_generate(void) { const uint8_t last_drop_check = (num > 1) ? (gaps & 1<<(num - 2)) : 1; if (end_stops[dir][1] || last_drop_check) - result = action_list_prepend(result, A_MOVE, loc, (dir<<4) | num, gaps); + result = action_list_prepend(result, A_MOVE, loc, gaps, (dir<<4) | num); /* * With thanks to * https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation * we have the following magic to generate the next * permutation of steps-many set bits */ - t = (gaps | (gaps - 1)); + uint8_t t = (gaps | (gaps - 1)); gaps = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(gaps) + 1)); } while (gaps && (gaps + 1 <= (1<<(num-1)))); } } } - } else if (material && count == 0) { + } else if (count == 0 && material) { // Empty square, generate placements if (flat) { - result = action_list_prepend(result, A_PLACE, loc, STONE_FLAT, 0); + result = action_list_prepend(result, + A_PLACE, + loc, + STONE_FLAT, + 0); if (standing) - result = action_list_prepend(result, A_PLACE, loc, STONE_STANDING, 0); + result = action_list_prepend(result, + A_PLACE, + loc, + STONE_STANDING, + 0); } if (cap) - result = action_list_prepend(result, A_PLACE, loc, STONE_CAPSTONE, 0); + result = action_list_prepend(result, + A_PLACE, + loc, + STONE_CAPSTONE, + 0); } } } @@ -138,9 +145,9 @@ action_list_t *action_list_generate(void) { } void action_take(action_list_t *action) { - const uint8_t loc = action->loc; + const int8_t loc = action->loc; if (action->type == A_PLACE) { - const uint8_t black = (ply&1); + const uint8_t black = (current_colour == C_BLACK); switch (action->data0) { case STONE_FLAT: { if (black) black_count--; @@ -167,8 +174,8 @@ void action_take(action_list_t *action) { } else { const uint8_t gaps = action->data0, num = action->data1 & 0x0F, // unpack - dir = action->data1 & 0xF0, - delta = deltas[dir]; + dir = action->data1 >> 4; + int8_t delta = deltas[dir]; // Unfortunately num == 1 is a special case if (num > 1) { @@ -176,7 +183,7 @@ void action_take(action_list_t *action) { // Use the Kernighan method to count the set bits for (steps = 1; gaps_prime; steps++) gaps_prime &= gaps_prime - 1; // then from the destination to the source - for (uint8_t d = 0; d + 1 < num; d++) { + for (uint8_t d = 0; d + 1 <= num; d++) { // transfer the top colour colours[loc+steps*delta] <<= 1; colours[loc+steps*delta] |= colours[loc] & 1; @@ -209,14 +216,29 @@ void action_take(action_list_t *action) { celldat[loc] -= NUM_INC; } } - // Always - inline_next_ply(); + // Next ply + ply++; + if (ply == 2) { + current_colour = C_WHITE; + } else { + if (current_colour == C_BLACK) current_colour = C_WHITE; + else current_colour = C_BLACK; + } } void action_undo(action_list_t *action) { - const uint8_t loc = action->loc; + // Previous ply + if (ply>0) ply--; + if (ply == 1) { + current_colour = C_WHITE; + } else { + if (current_colour == C_BLACK) current_colour = C_WHITE; + else current_colour = C_BLACK; + } + + const int8_t loc = action->loc; if (action->type == A_PLACE) { - const uint8_t black = (ply&1); + const uint8_t black = (current_colour == C_BLACK); celldat[loc] = 0; if (action->data0 == STONE_CAPSTONE) { if (black) black_count |= 128; @@ -229,18 +251,18 @@ void action_undo(action_list_t *action) { // See action_take for comments, this is the time reversal const uint8_t gaps = action->data0, num = action->data1 & 0x0F, // unpack - dir = action->data1 & 0xF0, - delta = deltas[dir]; + dir = action->data1 >> 4; + const int8_t delta = deltas[dir]; uint8_t steps = 1, mask = 1; if (num > 1) { - for (uint8_t d = 0; d + 1 < num; d++) { + for (uint8_t d = 0; d + 1 <= num; d++) { colours[loc] <<= 1; colours[loc] |= colours[loc+steps*delta] & 1; colours[loc+steps*delta] >>= 1; celldat[loc] += NUM_INC; - if (d + 2 == num) { + if (d + 1 == num) { celldat[loc] &= NUM_MASK; celldat[loc] |= STONE_AT(loc+steps*delta); celldat[loc+steps*delta] &= NUM_MASK; @@ -264,17 +286,16 @@ void action_undo(action_list_t *action) { celldat[loc+delta] -= NUM_INC; } } - inline_previous_ply(); } void action_to_ptn(action_list_t* action, char* out_ptn) { - const uint8_t loc = action->loc; + const int8_t loc = action->loc; if (action->type == A_PLACE) { generate_place(loc, action->data0, out_ptn); } else { const uint8_t gaps = action->data0, num = action->data1 & 0x0F, // unpack - dir = action->data1 & 0xF0; + dir = action->data1 >> 4; uint8_t drops[board_size]; // we only ever need board_size-1 in // drops actually, the last spot is to @@ -301,7 +322,7 @@ void action_to_ptn(action_list_t* action, char* out_ptn) { static inline action_list_t * action_list_prepend(action_list_t *list, const enum A_TYPE type, - const uint8_t loc, const uint8_t data0, + const int8_t loc, const uint8_t data0, const uint8_t data1) { action_list_t *new = malloc(sizeof(action_list_t)); // TODO: trap errno @@ -312,25 +333,3 @@ action_list_prepend(action_list_t *list, const enum A_TYPE type, new->data1 = data1; return new; } - -static inline void -inline_next_ply(void) { - ply++; - if (ply == 2) { - current_colour = C_WHITE; - } else { - if (current_colour == C_BLACK) current_colour = C_WHITE; - else current_colour = C_BLACK; - } -} - -static inline void -inline_previous_ply(void) { - if (ply>0) ply--; - if (ply == 1) { - current_colour = C_WHITE; - } else { - if (current_colour == C_BLACK) current_colour = C_WHITE; - else current_colour = C_BLACK; - } -} |
