From 0223a9bec5535fced1a7698b55fd42155d9b0446 Mon Sep 17 00:00:00 2001 From: tslil clingman Date: Sun, 15 Jan 2023 21:31:00 +0100 Subject: switch to explicit game state & important bug fix & clang format Previously the code base assumed that there was a single, global game state which was the implicit target of all actions taken. Looking ahead at architectural improvements, this has now been (almost entirely) made explicit and functions take tak_state_p where necessary (and also where unnecessary). Two important fixes to actions.c were made: - Previously when generating the possible stack moves, stack height overflows (> 15) were not taken into account and this resulted in the tree search corrupting the board state. Now action search does not list all legal actions, rather the subset of these encodeable by the implementation. - The check for crushing on a stack move was incorrect (too strict), and this resulted in many legitimate moves being igonored. Finally, in other changes, weights have also been improved by training all games instead of some subset for chosen players, and clang-format was run on the codebase. --- include/actions.c | 508 ++++++++++++++++++++------------------ include/actions.h | 29 ++- include/lcdlib.c | 53 ++-- include/lcdlib.h | 7 +- include/negamax.c | 208 ++++++++-------- include/negamax.h | 10 +- include/nn1986.c | 26 +- include/nn1986.h | 2 +- include/tak.c | 670 +++++++++++++++++++++++++++++---------------------- include/tak.h | 53 ++-- include/tps.c | 351 +++++++++++++++------------ include/tps.h | 8 +- include/tt_llcht.c | 27 +-- include/tt_llcht.h | 9 +- include/weights.c | 10 +- include/weights.h | 3 +- include/xorshift64.h | 11 +- include/zobrist.c | 23 +- include/zobrist.h | 8 +- 19 files changed, 1096 insertions(+), 920 deletions(-) (limited to 'include') diff --git a/include/actions.c b/include/actions.c index 795c135..6303822 100644 --- a/include/actions.c +++ b/include/actions.c @@ -16,37 +16,42 @@ */ #include "actions.h" +#include "tak.h" + +#include + +static uint8_t al_board_size; // =================================================================== // Helper method declarations // =================================================================== -#define DANGER_MIN(a,b) (((a)<(b))?(a):(b)) +#define DANGER_MIN(a, b) (((a) < (b)) ? (a) : (b)) #define CLR_STONE NUM_MASK -static inline void -list_append(action_list_t *list, const enum A_TYPE type, - const int8_t loc, const uint8_t data0, - const uint8_t data1); +static inline void list_append(action_list_t *list, const enum A_TYPE type, + const int8_t loc, const uint8_t data0, + const uint8_t data1); + +static inline void list_prepend(action_list_t *list, const enum A_TYPE type, + const int8_t loc, const uint8_t data0, + const uint8_t data1); -static inline void -list_prepend(action_list_t *list, const enum A_TYPE type, - const int8_t loc, const uint8_t data0, - const uint8_t data1); +static inline void inline_next_ply(tak_state_p state); -static inline void -inline_next_ply(void); +static inline void inline_prev_ply(tak_state_p state); -static inline void -inline_prev_ply(void); +static inline uint8_t check_no_overflow(tak_state_p state, const uint8_t loc, + const int8_t delta, const uint8_t num, + const uint8_t steps, + const uint8_t gaps); // =================================================================== // Exported method implementations // =================================================================== -int action_move_to_front(const action_t action, - action_list_t *list) { +int action_move_to_front(const action_t action, action_list_t *list) { action_node_t *n = list->head; // TODO: what if it's not in the list? @@ -64,7 +69,6 @@ int action_move_to_front(const action_t action, return EXIT_FAILURE; } - void action_list_free(action_list_t *list) { if (list) { action_node_t *n = list->head, *nn; @@ -80,7 +84,8 @@ void action_list_free(action_list_t *list) { // Keep track of move offsets int8_t move_deltas[4]; -void action_list_init(void) { +void action_list_init(const uint8_t board_size) { + al_board_size = board_size; move_deltas[0] = +board_size; move_deltas[1] = -board_size; move_deltas[2] = -1; @@ -89,7 +94,7 @@ void action_list_init(void) { // We bias place over move by prepending place actions and appending // move actions to the generated list -action_list_t *action_list_generate(void) { +action_list_t *action_list_generate(tak_state_p state) { action_list_t *list = malloc(sizeof(struct action_list_s)); // TODO: trap errno @@ -103,278 +108,297 @@ action_list_t *action_list_generate(void) { * well save on the conditional. */ - const uint8_t material = (ply & 1) ? black_count : white_count, - flat = material & 0x7F, - cap = ((ply >= 2) && (material & 0x80)), - standing = ((ply >= 2) && flat); + const uint8_t material = + (state->ply & 1) ? state->black_count : state->white_count, + flat = material & 0x7F, + cap = ((state->ply >= 2) && (material & 0x80)), + standing = ((state->ply >= 2) && flat); // Step across the board - for (int row = 0; row < board_size; row++) { - for (int col = 0; col < board_size; col++) { + for (int row = 0; row < state->board_size; row++) { + for (int col = 0; col < state->board_size; col++) { // We'll need these at various points: the location of this // square and the maximum number of stones we could pick up - const int loc = THE_COORDS(col, row); - const uint8_t count = DANGER_MIN(COUNT_AT(loc), board_size); + const int loc = THE_COORDS(al_board_size, col, row); + const uint8_t count = DANGER_MIN(COUNT_AT(state, loc), al_board_size); // Only try moves after CPS and if the colour is correct if (count) { - if (ply >= 2 && ((colours[loc] & 1) == current_colour)) { - - // Pre-compute end-stops and crushes - uint8_t end_stops[4], crushes[4] = {0, 0, 0, 0}; - - // These are upper bounds, not counting walls and such. - // UP DOWN LEFT RIGHT - end_stops[0] = DANGER_MIN(board_size - row - 1, count); - end_stops[1] = DANGER_MIN(row, count); - end_stops[2] = DANGER_MIN(col, count); - end_stops[3] = DANGER_MIN(board_size - col - 1, count); - - // Now we check for caps and walls - const uint8_t cap_top = STONE_AT(loc) == STONE_CAPSTONE; - for (int d = 0; d < 4; d++){ - const int delta = move_deltas[d]; - const int stop = end_stops[d]; - end_stops[d] = 0; - for (int k = 1; k <= stop; k++) { - const enum STONE_VARIANT stone = STONE_AT(loc+k*delta); - if (stone == STONE_STANDING) { - if (cap_top) { - crushes[d] = 0xFF; - end_stops[d]++; - } - break; - } else if (stone == STONE_CAPSTONE) { - break; - } - end_stops[d]++; - } - } - /* - * For each direction, generate all possible ordered integer - * partitions of 1 ≤ num ≤ count whose number of summands is - * exactly 1 ≤ summands ≤ min(end_stops[dir], num) -- we - * write summands as steps. - * - * We exploit the `gaps' bijection here and elsewhere - * between ordered {integer partitions of n with s summands} - * and {binary strings of length n-1 with s-1 set bits}. - */ - for (enum MOVE_DIRECTION dir=M_UP; dir<=M_RIGHT; dir++) { - for (uint8_t num = 1; num <= count; num++) { - for (uint8_t steps = 1; - steps <= end_stops[dir] && steps <= num; - steps++) { - uint8_t gaps = - ((1<<(board_size - 2)) - 1) >> (board_size-steps-1); - // For 5x5 this givess 0b0000[0XXX] where steps-1 of - // those X's are 1s (starting with LSB) because 4-1=3 - // and 5-1=4 - do { - /* - * We skip the partition if it calls for multiple - * stones at the end with a crush. - */ - const uint8_t last_drop_check = - (num > 1) ? (gaps & (1 << (num - 2))) : 1; - if (crushes[dir] == 0 || last_drop_check) { - // We have to record a crush! - const uint8_t crush = - (steps == end_stops[dir]) && crushes[dir]; - // Store the move - - list_append(list, A_MOVE, loc, - (crush << 7) | 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 - */ - uint8_t t = (gaps | (gaps - 1)); - gaps = (t + 1) - | (((~t & -~t) - 1) >> (__builtin_ctz(gaps) + 1)); - } while (gaps && (gaps + 1 <= (1 << (num - 1)))); - } - } - } - } + if (state->ply >= 2 && + ((state->colours[loc] & 1) == state->current_colour)) { + + // Pre-compute end-stops and crushes + uint8_t end_stops[4], crushes[4] = {0, 0, 0, 0}; + + // These are upper bounds, not counting walls and such. + // UP DOWN LEFT RIGHT + end_stops[0] = DANGER_MIN(al_board_size - row - 1, count); + end_stops[1] = DANGER_MIN(row, count); + end_stops[2] = DANGER_MIN(col, count); + end_stops[3] = DANGER_MIN(al_board_size - col - 1, count); + + // Now we check for caps and walls + const uint8_t cap_top = STONE_AT(state, loc) == STONE_CAPSTONE; + for (int d = 0; d < 4; d++) { + const int delta = move_deltas[d]; + const int stop = end_stops[d]; + end_stops[d] = 0; + for (int k = 1; k <= stop; k++) { + const enum STONE_VARIANT stone = STONE_AT(state, loc + k * delta); + if (stone == STONE_STANDING) { + if (cap_top) { + crushes[d] = k; + end_stops[d]++; + } + break; + } else if (stone == STONE_CAPSTONE) { + break; + } + end_stops[d]++; + } + } + /* + * For each direction, generate all possible ordered integer + * partitions of 1 ≤ num ≤ count whose number of summands is in the + * range 1 ≤ # summands ≤ min(end_stops[dir], num) -- we write + * summands as steps. + * + * We exploit the `gaps' bijection here and elsewhere between ordered + * {integer partitions of n with s summands} and {binary strings of + * length n-1 with s-1 set bits}. + */ + for (enum MOVE_DIRECTION dir = M_UP; dir <= M_RIGHT; dir++) { + const int8_t delta = move_deltas[dir]; + for (uint8_t num = 1; num <= count; num++) { + for (uint8_t steps = 1; steps <= end_stops[dir] && steps <= num; + steps++) { + uint8_t gaps = ((1 << (al_board_size - 2)) - 1) >> + (al_board_size - steps - 1); + // For 5x5 this gives 0b0000[0XXX] where steps-1 of those X's + // are 1s (starting with LSB) because 4-1=3 and 5-1=4 + do { + /* + * We skip the partition if it calls for multiple stones at + * the end with a crush, or if it would cause any stack to + * grow beyond height 15. + */ + const uint8_t no_overflow = + check_no_overflow(state, loc, delta, num, steps, gaps); + const uint8_t last_drop_check = + (num > 1) ? (gaps & (1 << (num - 2))) : 1; + const uint8_t can_and_must_crush = + crushes[dir] == steps && last_drop_check; + const uint8_t crush_check = + can_and_must_crush || crushes[dir] != steps; + if (no_overflow && crush_check) { + // Store the move + list_append(list, A_MOVE, loc, + (can_and_must_crush << 7) | 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 + */ + uint8_t t = (gaps | (gaps - 1)); + gaps = + (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(gaps) + 1)); + } while (gaps && (gaps + 1 <= (1 << (num - 1)))); + } + } + } + } } // end of if (count) { ... } else if (material) { - // Empty square, generate placements - if (flat) { - list_prepend(list, A_PLACE, loc, STONE_FLAT, 0); - if (standing) - list_prepend(list, A_PLACE, loc, STONE_STANDING,0); - } - if (cap) - list_prepend(list, A_PLACE, loc, STONE_CAPSTONE, 0); + // Empty square, generate placements + if (flat) { + list_prepend(list, A_PLACE, loc, STONE_FLAT, 0); + if (standing) + list_prepend(list, A_PLACE, loc, STONE_STANDING, 0); + } + if (cap) + list_prepend(list, A_PLACE, loc, STONE_CAPSTONE, 0); } } } return list; } -void action_take(const action_t action) { +void action_take(tak_state_p state, const action_t action) { const int8_t loc = A_GET_LOC(action); if (A_GET_TYPE(action) == A_PLACE) { - const uint8_t black = (current_colour == C_BLACK); + const uint8_t black = (state->current_colour == C_BLACK); switch (A_GET_DATA0(action)) { - case STONE_FLAT: { - if (black) black_count--; - else white_count--; - colours[loc] = current_colour; - celldat[loc] = NUM_INC | STONE_FLAT; - break; - } - case STONE_STANDING: { - if (black) black_count--; - else white_count--; - colours[loc] = current_colour; - celldat[loc] = NUM_INC | STONE_STANDING; - break; - } - default: { - if (black) black_count &= 0x7F; - else white_count &= 0x7F; - colours[loc] = current_colour; - celldat[loc] = NUM_INC | STONE_CAPSTONE; - break; - } + case STONE_FLAT: { + if (black) + state->black_count--; + else + state->white_count--; + state->colours[loc] = state->current_colour; + state->celldat[loc] = NUM_INC | STONE_FLAT; + break; + } + case STONE_STANDING: { + if (black) + state->black_count--; + else + state->white_count--; + state->colours[loc] = state->current_colour; + state->celldat[loc] = NUM_INC | STONE_STANDING; + break; + } + default: { + if (black) + state->black_count &= 0x7F; + else + state->white_count &= 0x7F; + state->colours[loc] = state->current_colour; + state->celldat[loc] = NUM_INC | STONE_CAPSTONE; + break; + } } } else { /* - * See the discussion around line 135 for an explanation of the - * encoding. Here we are not interested in whether we crushed, it - * will work out by anyway because we overwrite the top stone - * type. See (*) later for when we do need to know. + * See the discussion around line 160 for an explanation of the encoding. + * Here we are not interested in whether we crushed, it will work out by + * anyway because we overwrite the top stone type. See (*) later for when we + * do need to know. */ const uint8_t gaps = A_GET_DATA0(action) & 0x7F, - num = A_GET_DATA1(action) & 0x0F, // unpack - dir = A_GET_DATA1(action) >> 4; + num = A_GET_DATA1(action) & 0x0F, // unpack + dir = A_GET_DATA1(action) >> 4; int8_t delta = move_deltas[dir]; // Use the Kernighan method to count the set bits int8_t steps = 1; - for (uint8_t _gaps = gaps; _gaps; steps++) _gaps &= _gaps - 1; + for (uint8_t _gaps = gaps; _gaps; steps++) + _gaps &= _gaps - 1; // Move top stone type to destination - celldat[loc+steps*delta] &= CLR_STONE; // necessary for crushing - celldat[loc+steps*delta] |= STONE_AT(loc); - celldat[loc] &= CLR_STONE; - celldat[loc] |= STONE_FLAT; // should be optimised out - - uint8_t total = 1, gap_bit = 1 << (num - 2); // it's not important - // what negative - // shifts do here, we - // don't use gap_bit - // if num < 2 + state->celldat[loc + steps * delta] &= CLR_STONE; // necessary for crushing + state->celldat[loc + steps * delta] |= STONE_AT(state, loc); + state->celldat[loc] &= CLR_STONE; + state->celldat[loc] |= STONE_FLAT; // should be optimised out + + uint8_t total = 1, gap_bit = 1 << (num - 2); // it's not important what + // negative shifts do here, we + // don't use gap_bit if num < 2 + // move stuff starting at destination for (uint8_t d = 1; d < num; d++, total++, gap_bit >>= 1) { // We took a step, move everything over so far if (gaps & gap_bit) { - colours[loc+steps*delta] <<= total; - colours[loc+steps*delta] |= colours[loc] & ((1 << total) - 1); - colours[loc] >>= total; - celldat[loc+steps*delta] += total*NUM_INC; - celldat[loc] -= total*NUM_INC; - // Reset for next step - total = 0; - steps--; + state->colours[loc + steps * delta] <<= total; + state->colours[loc + steps * delta] |= + state->colours[loc] & ((1 << total) - 1); + state->colours[loc] >>= total; + state->celldat[loc + steps * delta] += total * NUM_INC; + state->celldat[loc] -= total * NUM_INC; + // Reset for next step + total = 0; + steps--; } } // Move what remains (steps == 1 here always, so we simplify) - colours[loc+delta] <<= total; - colours[loc+delta] |= colours[loc] & ((1 << total) - 1); - colours[loc] >>= total; - celldat[loc+delta] += total*NUM_INC; - celldat[loc] -= total*NUM_INC; + state->colours[loc + delta] <<= total; + state->colours[loc + delta] |= state->colours[loc] & ((1 << total) - 1); + state->colours[loc] >>= total; + state->celldat[loc + delta] += total * NUM_INC; + state->celldat[loc] -= total * NUM_INC; } // Next ply - inline_next_ply(); + inline_next_ply(state); } -void action_undo(const action_t action) { +void action_undo(tak_state_p state, const action_t action) { // Previous ply - inline_prev_ply(); + inline_prev_ply(state); const int8_t loc = A_GET_LOC(action); if (A_GET_TYPE(action) == A_PLACE) { - const uint8_t black = (current_colour == C_BLACK); - celldat[loc] = 0; + const uint8_t black = (state->current_colour == C_BLACK); + state->celldat[loc] = 0; if (A_GET_DATA0(action) == STONE_CAPSTONE) { - if (black) black_count |= 0x80; - else white_count |= 0x80; + if (black) + state->black_count |= 0x80; + else + state->white_count |= 0x80; } else { - if (black) black_count++; - else white_count++; + if (black) + state->black_count++; + else + state->white_count++; } } else { // See action_take for comments, this is the time reversal, but // there is one caveat -- undoing a crush! (*) const uint8_t gaps = A_GET_DATA0(action) & 0x7F, - crush = A_GET_DATA0(action) & 0x80, - num = A_GET_DATA1(action) & 0x0F, - dir = A_GET_DATA1(action) >> 4; + crush = A_GET_DATA0(action) & 0x80, + num = A_GET_DATA1(action) & 0x0F, + dir = A_GET_DATA1(action) >> 4; const int8_t delta = move_deltas[dir]; int8_t steps = 1; uint8_t gap_bit = 1, total = 1; for (int8_t d = 1; d < num; d++, total++, gap_bit <<= 1) { if (gaps & gap_bit) { - colours[loc] <<= total; - colours[loc] |= colours[loc+steps*delta] & ((1 << total) - 1); - colours[loc+steps*delta] >>= total; - celldat[loc] += total*NUM_INC; - celldat[loc+steps*delta] -= total*NUM_INC; - total = 0; - steps++; + state->colours[loc] <<= total; + state->colours[loc] |= + state->colours[loc + steps * delta] & ((1 << total) - 1); + state->colours[loc + steps * delta] >>= total; + state->celldat[loc] += total * NUM_INC; + state->celldat[loc + steps * delta] -= total * NUM_INC; + total = 0; + steps++; } } - colours[loc] <<= total; - colours[loc] |= colours[loc+steps*delta] & ((1 << total) - 1); - colours[loc+steps*delta] >>= total; + state->colours[loc] <<= total; + state->colours[loc] |= + state->colours[loc + steps * delta] & ((1 << total) - 1); + state->colours[loc + steps * delta] >>= total; - celldat[loc] += total*NUM_INC; + state->celldat[loc] += total * NUM_INC; // celldat[loc] &= CLR_STONE; is not necessary, as STONE_FLAT == 0 - celldat[loc] |= STONE_AT(loc+steps*delta); - celldat[loc+steps*delta] -= total*NUM_INC; - celldat[loc+steps*delta] &= CLR_STONE; + state->celldat[loc] |= STONE_AT(state, loc + steps * delta); + state->celldat[loc + steps * delta] -= total * NUM_INC; + state->celldat[loc + steps * delta] &= CLR_STONE; if (crush) { - celldat[loc+steps*delta] |= STONE_STANDING; + state->celldat[loc + steps * delta] |= STONE_STANDING; } else { - celldat[loc+steps*delta] |= STONE_FLAT; // should be optimised out + state->celldat[loc + steps * delta] |= + STONE_FLAT; // should be optimised out } } } -void action_to_ptn(const action_t action, char* out_ptn) { +void action_to_ptn(const action_t action, char *out_ptn) { const int8_t loc = A_GET_LOC(action); if (A_GET_TYPE(action) == A_PLACE) { - generate_place(loc, A_GET_DATA0(action), out_ptn); + generate_place(al_board_size, loc, A_GET_DATA0(action), out_ptn); } else { const uint8_t gaps = A_GET_DATA0(action) & 0x7F, - num = A_GET_DATA1(action) & 0x0F, // unpack - dir = A_GET_DATA1(action) >> 4; + num = A_GET_DATA1(action) & 0x0F, // unpack + dir = A_GET_DATA1(action) >> 4; - uint8_t drops[board_size]; // we only ever need board_size-1 in - // drops actually, the last spot is to - // skip a bounds check at (**) + uint8_t drops[al_board_size]; // we only ever need al_board_size-1 in drops + // actually, the last spot is to skip a bounds + // check at (**) uint8_t mask = 1, steps = 0; // Translate to a drop sequence - drops[0] = 1; mask = 1; + drops[0] = 1; + mask = 1; for (uint8_t d = 1; d < num; d++) { if (gaps & mask) { - steps++; - drops[steps] = 1; // (**) no bounds check + steps++; + drops[steps] = 1; // (**) no bounds check } else { - drops[steps] += 1; + drops[steps] += 1; } mask <<= 1; } - generate_move(loc, dir, steps+1, drops, out_ptn); + generate_move(al_board_size, loc, dir, steps + 1, drops, out_ptn); } } @@ -382,10 +406,9 @@ void action_to_ptn(const action_t action, char* out_ptn) { // Helper method implementations // =================================================================== -static inline void -list_append(action_list_t *list, const enum A_TYPE type, - const int8_t loc, const uint8_t data0, - const uint8_t data1) { +static inline void list_append(action_list_t *list, const enum A_TYPE type, + const int8_t loc, const uint8_t data0, + const uint8_t data1) { action_node_t *new = malloc(sizeof(action_node_t)); // TODO: trap errno @@ -403,10 +426,9 @@ list_append(action_list_t *list, const enum A_TYPE type, list->length++; } -static inline void -list_prepend(action_list_t *list, const enum A_TYPE type, - const int8_t loc, const uint8_t data0, - const uint8_t data1) { +static inline void list_prepend(action_list_t *list, const enum A_TYPE type, + const int8_t loc, const uint8_t data0, + const uint8_t data1) { action_node_t *new = malloc(sizeof(action_list_t)); // TODO: trap errno @@ -421,24 +443,46 @@ list_prepend(action_list_t *list, const enum A_TYPE type, list->length++; } -static inline void -inline_next_ply(void) { - ply++; - if (ply == 2) { - current_colour = C_WHITE; +static inline void inline_next_ply(tak_state_p state) { + state->ply++; + if (state->ply == 2) { + state->current_colour = C_WHITE; } else { - if (current_colour == C_BLACK) current_colour = C_WHITE; - else current_colour = C_BLACK; + if (state->current_colour == C_BLACK) + state->current_colour = C_WHITE; + else + state->current_colour = C_BLACK; } } -static inline void -inline_prev_ply(void) { - if (ply>0) ply--; - if (ply == 1) { - current_colour = C_WHITE; +static inline void inline_prev_ply(tak_state_p state) { + if (state->ply > 0) + state->ply--; + if (state->ply == 1) { + state->current_colour = C_WHITE; } else { - if (current_colour == C_BLACK) current_colour = C_WHITE; - else current_colour = C_BLACK; + if (state->current_colour == C_BLACK) + state->current_colour = C_WHITE; + else + state->current_colour = C_BLACK; + } +} + +static inline uint8_t check_no_overflow(tak_state_p state, const uint8_t loc, + const int8_t delta, const uint8_t num, + const uint8_t steps, + const uint8_t gaps) { + uint8_t total = 1, gap_bit = 1 << (num - 2), step = steps; + for (uint8_t d = 1; d < num; d++, total++, gap_bit >>= 1) { + if (gaps & gap_bit) { + if (COUNT_AT(state, loc + step * delta) + total > 15) + return 0; + step--; + total = 0; + } } + if (COUNT_AT(state, loc + delta) + total > 15) + return 0; + + return 1; } diff --git a/include/actions.h b/include/actions.h index 8df9392..1550cce 100644 --- a/include/actions.h +++ b/include/actions.h @@ -18,8 +18,8 @@ #ifndef ACTIONS_H #define ACTIONS_H -#include #include +#include #include @@ -33,16 +33,15 @@ typedef uint32_t action_t; #define A_DATA1_SHIFT 24 #define A_DATA0_SHIFT 16 -#define A_LOC_SHIFT 8 +#define A_LOC_SHIFT 8 -#define A_GET_DATA1(a) (enum A_TYPE)((a)>>A_DATA1_SHIFT) -#define A_GET_DATA0(a) (int8_t)(((a)>>A_DATA0_SHIFT) & 0xFF) -#define A_GET_LOC(a) (uint8_t)(((a)>>A_LOC_SHIFT) & 0xFF) -#define A_GET_TYPE(a) (uint8_t)((a) & 0xFF) -#define A_BUILD(type,loc,data0,data1) ((type) \ - | (loc) << A_LOC_SHIFT \ - | (data0) << A_DATA0_SHIFT \ - | (data1) << A_DATA1_SHIFT) +#define A_GET_DATA1(a) (enum A_TYPE)((a) >> A_DATA1_SHIFT) +#define A_GET_DATA0(a) (int8_t)(((a) >> A_DATA0_SHIFT) & 0xFF) +#define A_GET_LOC(a) (uint8_t)(((a) >> A_LOC_SHIFT) & 0xFF) +#define A_GET_TYPE(a) (uint8_t)((a)&0xFF) +#define A_BUILD(type, loc, data0, data1) \ + ((type) | (loc) << A_LOC_SHIFT | (data0) << A_DATA0_SHIFT | \ + (data1) << A_DATA1_SHIFT) typedef struct action_node_s { struct action_node_s *next; @@ -64,15 +63,15 @@ extern int8_t move_deltas[4]; // Methods // =================================================================== -void action_list_init(void); +void action_list_init(const uint8_t board_size); void action_list_free(action_list_t *list); -action_list_t *action_list_generate(void); +action_list_t *action_list_generate(tak_state_p state); int action_move_to_front(const action_t action, action_list_t *list); -void action_take(const action_t action); -void action_undo(const action_t action); +void action_take(tak_state_p state, const action_t action); +void action_undo(tak_state_p state, const action_t action); -void action_to_ptn(const action_t action, char* out_ptn); +void action_to_ptn(const action_t action, char *out_ptn); #endif diff --git a/include/lcdlib.c b/include/lcdlib.c index 69d6df0..beced28 100644 --- a/include/lcdlib.c +++ b/include/lcdlib.c @@ -17,38 +17,32 @@ #include "lcdlib.h" -static char previous_lines[LCD_HEIGHT][LCD_WIDTH+1]; -static const char* esc = "\x1B[L"; +static char previous_lines[LCD_HEIGHT][LCD_WIDTH + 1]; +static const char *esc = "\x1B[L"; static FILE *lcd = NULL; static int line_idx; -int -lcd_begin(void) { +int lcd_begin(void) { lcd = fopen("/dev/lcd", "w"); - if (lcd == NULL) return EXIT_FAILURE; + if (lcd == NULL) + return EXIT_FAILURE; lcd_clear(); return EXIT_SUCCESS; } -void -lcd_end(void) { - fclose(lcd); -} +void lcd_end(void) { fclose(lcd); } -void -lcd_set_blink(void) { +void lcd_set_blink(void) { fprintf(lcd, "%sB", esc); fflush(lcd); } -void -lcd_stop_blink(void) { +void lcd_stop_blink(void) { fprintf(lcd, "%sb", esc); fflush(lcd); } -void -lcd_clear(void) { +void lcd_clear(void) { line_idx = 0; for (int y = 0; y + 1 < LCD_HEIGHT; y++) { fprintf(lcd, "%sy%dx0;%sk", esc, y, esc); @@ -57,18 +51,17 @@ lcd_clear(void) { fflush(lcd); } -void -lcd_put_line(const enum LCD_WRITE_MODE mode, const char *line) { +void lcd_put_line(const enum LCD_WRITE_MODE mode, const char *line) { char last_line = 0; if (line_idx == LCD_HEIGHT) { if (mode == L_SCROLL) { // If we're at the bottom, ``shift'' everything up for (int y = 1; y < LCD_HEIGHT; y++) { - // Go to the start of row y, clear the line, and print the - // previous string there - fprintf(lcd, "%sy%dx0;%sk%s", esc, y-1, esc, previous_lines[y]); - // Overwrite the stored previous line with the next - strncpy(previous_lines[y-1], previous_lines[y], LCD_WIDTH+1); + // Go to the start of row y, clear the line, and print the + // previous string there + fprintf(lcd, "%sy%dx0;%sk%s", esc, y - 1, esc, previous_lines[y]); + // Overwrite the stored previous line with the next + strncpy(previous_lines[y - 1], previous_lines[y], LCD_WIDTH + 1); } } last_line = 1; @@ -77,20 +70,20 @@ lcd_put_line(const enum LCD_WRITE_MODE mode, const char *line) { fprintf(lcd, "%sy%dx0;%sk%s", esc, line_idx, esc, line); fflush(lcd); // Store this line, null-terminate! - if (last_line) line_idx--; - strncpy(previous_lines[line_idx], line, LCD_WIDTH+1); + if (last_line) + line_idx--; + strncpy(previous_lines[line_idx], line, LCD_WIDTH + 1); previous_lines[line_idx][LCD_WIDTH] = 0; - if (mode == L_SCROLL && line_idx < LCD_HEIGHT) line_idx++; + if (mode == L_SCROLL && line_idx < LCD_HEIGHT) + line_idx++; } -void -lcd_printf_line(const enum LCD_WRITE_MODE mode, - const char *format, ...) { - char buf[LCD_WIDTH+1]; +void lcd_printf_line(const enum LCD_WRITE_MODE mode, const char *format, ...) { + char buf[LCD_WIDTH + 1]; va_list(args); va_start(args, format); - vsnprintf(buf, LCD_WIDTH+1, format, args); + vsnprintf(buf, LCD_WIDTH + 1, format, args); va_end(args); lcd_put_line(mode, buf); diff --git a/include/lcdlib.h b/include/lcdlib.h index c514ba0..d8225c2 100644 --- a/include/lcdlib.h +++ b/include/lcdlib.h @@ -15,16 +15,16 @@ along with ct. If not, see . */ -#include #include #include +#include #include // =================================================================== // Types // =================================================================== -#define LCD_WIDTH 16 +#define LCD_WIDTH 16 #define LCD_HEIGHT 2 enum LCD_WRITE_MODE { L_OVERWRITE, L_SCROLL }; @@ -42,5 +42,4 @@ void lcd_stop_blink(void); void lcd_put_line(const enum LCD_WRITE_MODE mode, const char *line); -void lcd_printf_line(const enum LCD_WRITE_MODE mode, - const char *format, ...); +void lcd_printf_line(const enum LCD_WRITE_MODE mode, const char *format, ...); diff --git a/include/negamax.c b/include/negamax.c index e85aba9..0f2c450 100644 --- a/include/negamax.c +++ b/include/negamax.c @@ -16,6 +16,7 @@ */ #include "negamax.h" +#include "actions.h" // =================================================================== // Variables @@ -30,43 +31,40 @@ static uint64_t negamax_best_action; // Helper declarations // =================================================================== -static float negamax(const uint8_t cur_depth, const uint8_t init_depth, - float alpha, float beta, - const float colour, const uint64_t hash); +static float negamax(tak_state_p state, const uint8_t cur_depth, + const uint8_t init_depth, float alpha, float beta, + const float colour, const uint64_t hash); // =================================================================== // Exported functions // =================================================================== void negamax_init(const uint8_t new_board_size) { - board_size = new_board_size; - action_list_init(); - zobrist_init(); - tt_init(); + action_list_init(new_board_size); + zobrist_init(new_board_size); + tt_init(); } -void negamax_free(void) { - zobrist_free(); -} +void negamax_free(void) { zobrist_free(); } -float negamax_generate(void) { - // We need to start with something outside of [-∞,∞] because those - // values are wins - const float safe_infty = infty + 1; - float result = -infty; +float negamax_generate(tak_state_p state) { + // We need to start with something outside of [-∞,∞] because those + // values are wins + const float safe_infty = infty + 1; + float result = -infty; - negamax_best_action = -1; + negamax_best_action = -1; - tt_init(); - for (int d = 1; d <= negamax_search_depth; d++) { - result = negamax(d, d, -safe_infty, safe_infty, - (ply & 1) ? +1.0 : -1.0, zobrist_compute()); - } - tt_free(); + tt_init(); + for (int d = 1; d <= negamax_search_depth; d++) { + result = negamax(state, d, d, -safe_infty, safe_infty, + (state->ply & 1) ? +1.0 : -1.0, zobrist_compute(state)); + } + tt_free(); - action_to_ptn(negamax_best_action, negamax_ptn); + action_to_ptn(negamax_best_action, negamax_ptn); - return result; + return result; } // =================================================================== @@ -78,89 +76,95 @@ float negamax_generate(void) { static enum TT_FLAG flag; static enum WIN_TYPE w; -static float negamax(const uint8_t cur_depth, const uint8_t init_depth, - float alpha, float beta, - const float colour, const uint64_t hash) { - - tt_entry_t *entry = tt_seek(hash); - - // CAUTION: ≥ breaks search stability (vs =) on shallow depths - if (entry != NULL && entry->depth >= cur_depth) { - if (entry->flag == TT_EXACT) { - return entry->value; - } else if (entry->flag == TT_LOWERBOUND && entry->value > alpha) { - alpha = entry->value; - } else if (entry->flag == TT_UPPERBOUND && entry->value < beta) { - beta = entry->value; - } - if (alpha >= beta) return entry->value; - } +static float negamax(tak_state_p state, const uint8_t cur_depth, + const uint8_t init_depth, float alpha, float beta, + const float colour, const uint64_t hash) { - action_list_t *list; - if ((list = action_list_generate()) == NULL) - return alpha; // should never happen! - - if (entry != NULL) { - action_move_to_front(entry->action, list); - } + tt_entry_t *entry = tt_seek(hash); - if (init_depth > 1 && cur_depth == init_depth) { - action_move_to_front(negamax_best_action, list); + // CAUTION: ≥ breaks search stability (vs =) on shallow depths + if (entry != NULL && entry->depth >= cur_depth) { + if (entry->flag == TT_EXACT) { + return entry->value; + } else if (entry->flag == TT_LOWERBOUND && entry->value > alpha) { + alpha = entry->value; + } else if (entry->flag == TT_UPPERBOUND && entry->value < beta) { + beta = entry->value; } - - // TODO: what to do if this is never written to? - action_t best_action = list->head->action; - float best_value = -infty; - - for (action_node_t *node=list->head; node!=NULL; node=node->next) { - negamax_display_progress(cur_depth, init_depth, list->length); - - action_take(node->action); - - // Compute the value of the node - float node_value; - if (ply >= 2*board_size - 2 && (w = check_win()) < 0xFF) { - node_value = -colour*infty; - // Check win if far enough into the game - if (w == WIN_ROAD_BLACK || w == WIN_FLAT_BLACK) { - node_value = colour*infty; - } else if (w == WIN_DRAW) { - node_value = 0; - } - } else if (cur_depth > 1) { - // If nobody won, or too early and not leaf, recurse - node_value = -negamax(cur_depth - 1, init_depth, - -beta, -alpha, - -colour, zobrist_compute()); - } else { - node_value = colour * nn1986_evaluate_black_win(); - } - action_undo(node->action); - - if (node_value > best_value) { - best_value = node_value; - best_action = node->action; - } - - if (best_value > alpha) alpha = best_value; - if (alpha >= beta) break; + if (alpha >= beta) + return entry->value; + } + + action_list_t *list; + if ((list = action_list_generate(state)) == NULL) + return alpha; // should never happen! + + if (entry != NULL) { + action_move_to_front(entry->action, list); + } + + if (init_depth > 1 && cur_depth == init_depth) { + action_move_to_front(negamax_best_action, list); + } + + // TODO: what to do if this is never written to? + action_t best_action = list->head->action; + float best_value = -infty; + + for (action_node_t *node = list->head; node != NULL; node = node->next) { + negamax_display_progress(cur_depth, init_depth, list->length); + + action_take(state, node->action); + + // Compute the value of the node + float node_value; + if (state->ply >= 2 * state->board_size - 2 && + (w = check_win(state)) < 0xFF) { + node_value = -colour * infty; + // Check win if far enough into the game + if (w == WIN_ROAD_BLACK || w == WIN_FLAT_BLACK) { + node_value = colour * infty; + } else if (w == WIN_DRAW) { + node_value = 0; + } + } else if (cur_depth > 1) { + // If nobody won, or too early and not leaf, recurse + node_value = -negamax(state, cur_depth - 1, init_depth, -beta, -alpha, + -colour, zobrist_compute(state)); + } else { + node_value = colour * nn1986_evaluate_black_win(state); } + action_undo(state, node->action); - action_list_free(list); - if (cur_depth == init_depth) negamax_best_action = best_action; - - flag = TT_EXACT; - if (best_value >= beta) flag = TT_LOWERBOUND; - else if (best_value <= alpha) flag = TT_UPPERBOUND; - - if (entry == NULL) { - tt_insert(hash, flag, cur_depth, best_value, best_action); - } else { - entry->flag = flag; - entry->value = best_value; - entry->depth = cur_depth; - entry->action = best_action; + if (node_value > best_value) { + best_value = node_value; + best_action = node->action; } - return best_value; + if (best_value > alpha) + alpha = best_value; + if (alpha >= beta) + break; + } + + action_list_free(list); + if (cur_depth == init_depth) + negamax_best_action = best_action; + + flag = TT_EXACT; + if (best_value >= beta) + flag = TT_LOWERBOUND; + else if (best_value <= alpha) + flag = TT_UPPERBOUND; + + if (entry == NULL) { + tt_insert(hash, flag, cur_depth, best_value, best_action); + } else { + entry->flag = flag; + entry->value = best_value; + entry->depth = cur_depth; + entry->action = best_action; + } + + return best_value; } diff --git a/include/negamax.h b/include/negamax.h index e491baa..eedb7dd 100644 --- a/include/negamax.h +++ b/include/negamax.h @@ -15,12 +15,12 @@ along with ct. If not, see . */ -#include #include +#include -#include #include #include +#include #include #include @@ -33,8 +33,8 @@ extern char negamax_ptn[9]; extern uint8_t negamax_search_depth; extern void negamax_display_progress(const uint8_t cur_depth, - const uint8_t init_depth, - const uint32_t length); + const uint8_t init_depth, + const uint32_t length); // =================================================================== // Methods @@ -50,4 +50,4 @@ void negamax_free(void); * `negamax_ptn', and return its value. The `negamax_display_progress' * function is called on every new square at the top level. */ -float negamax_generate(void); +float negamax_generate(tak_state_p state); diff --git a/include/nn1986.c b/include/nn1986.c index b9c551c..117a034 100644 --- a/include/nn1986.c +++ b/include/nn1986.c @@ -28,22 +28,22 @@ static float dense1[DENSE_NUM]; static float output[2]; #define RELU(x) ((x) = ((x) < 0) ? 0 : (x)) -float nn1986_evaluate_black_win(void) { +float nn1986_evaluate_black_win(tak_state_p state) { /* --------------- * * Populate input * * --------------- */ - for (unsigned int y = 0; y < board_size; y++) { - for (unsigned int x = 0; x < board_size; x++) { - const unsigned int loc = x + y * board_size; - const unsigned int count = COUNT_AT(loc); + for (unsigned int y = 0; y < state->board_size; y++) { + for (unsigned int x = 0; x < state->board_size; x++) { + const unsigned int loc = x + y * state->board_size; + const unsigned int count = COUNT_AT(state, loc); float lookup = 0; if (count > 0) { - if (STONE_AT(loc) == STONE_STANDING) { - lookup = (colours[loc] & 1) ? +0.25 : -0.25; - } else if (STONE_AT(loc) == STONE_CAPSTONE) { - lookup = (colours[loc] & 1) ? +1.00 : -1.00; + if (STONE_AT(state, loc) == STONE_STANDING) { + lookup = (state->colours[loc] & 1) ? +0.25 : -0.25; + } else if (STONE_AT(state, loc) == STONE_CAPSTONE) { + lookup = (state->colours[loc] & 1) ? +1.00 : -1.00; } else { - lookup = (colours[loc] & 1) ? +0.50 : -0.50; + lookup = (state->colours[loc] & 1) ? +0.50 : -0.50; } } cur_board[3 + loc] = lookup; @@ -53,9 +53,9 @@ float nn1986_evaluate_black_win(void) { * Convolution layer * * ------------------ */ // Add input of flat counts and ply parity - cur_board[0] = (ply & 1) ? 1 : -1; - cur_board[1] = (float)(white_count & 127) / 21.0; - cur_board[2] = (float)(black_count & 127) / 21.0; + cur_board[0] = (state->ply & 1) ? 1 : -1; + cur_board[1] = (float)(state->white_count & 127) / 21.0; + cur_board[2] = (float)(state->black_count & 127) / 21.0; /* ------------------ * * First dense layer * * ------------------ */ diff --git a/include/nn1986.h b/include/nn1986.h index 4e99ac2..02dca0e 100644 --- a/include/nn1986.h +++ b/include/nn1986.h @@ -17,4 +17,4 @@ #include -float nn1986_evaluate_black_win(void); +float nn1986_evaluate_black_win(tak_state_p state); diff --git a/include/tak.c b/include/tak.c index 5fd8e9a..a5f2f44 100644 --- a/include/tak.c +++ b/include/tak.c @@ -16,57 +16,55 @@ */ #include "tak.h" +#include // =================================================================== -// Globals +// Helpers // =================================================================== -enum WIN_TYPE won; -uint8_t board_size; -data_t celldat[36]; -colour_stack_t colours[36]; -enum COLOUR current_colour; -uint8_t white_count, black_count, ply; +#define NUM_SQUARES(board_size) (board_size * board_size) -// =================================================================== -// Helpers -// =================================================================== +tak_state_p new_tak_state(const uint8_t board_size) { + tak_state_p state = malloc(sizeof(struct tak_state_s)); + reset_state(state, board_size); + return state; +} -#define NUM_SQUARES (board_size * board_size) +void free_tak_state(tak_state_p state) { free(state); } // =================================================================== // General state stuff // =================================================================== -void -reset_state(const uint8_t new_board_size) { +void reset_state(tak_state_p state, const uint8_t new_board_size) { if (new_board_size == 6) { - board_size = 6; - white_count = 128 | 30; - black_count = 128 | 30; + state->board_size = 6; + state->white_count = 128 | 30; + state->black_count = 128 | 30; } else { - board_size = 5; - white_count = 128 | 21; - black_count = 128 | 21; + state->board_size = 5; + state->white_count = 128 | 21; + state->black_count = 128 | 21; } - ply = 0; - won = 0xFF; // i may live to regret this hack - current_colour = C_BLACK; + state->ply = 0; + state->won = 0xFF; // i may live to regret this hack + state->current_colour = C_BLACK; - for (uint8_t k = 0; k < NUM_SQUARES; k++ ) { - celldat[k] = 0; + for (uint8_t k = 0; k < NUM_SQUARES(new_board_size); k++) { + state->celldat[k] = 0; } } -void -next_ply(void) { - ply++; - if (ply == 2) { - current_colour = C_WHITE; +void next_ply(tak_state_p state) { + state->ply++; + if (state->ply == 2) { + state->current_colour = C_WHITE; } else { - if (current_colour == C_BLACK) current_colour = C_WHITE; - else current_colour = C_BLACK; + if (state->current_colour == C_BLACK) + state->current_colour = C_WHITE; + else + state->current_colour = C_BLACK; } } @@ -74,47 +72,57 @@ next_ply(void) { // Placing stones // =================================================================== -enum ACT_RESULT -try_place(const int8_t location, const enum COLOUR colour, - const enum STONE_VARIANT stone) -{ +enum ACT_RESULT try_place(tak_state_p state, const int8_t location, + const enum COLOUR colour, + const enum STONE_VARIANT stone) { // Game is over? - if (won < 0xFF) return GAME_END; + if (state->won < 0xFF) + return GAME_END; // Can't place on an occupied square - if (COUNT_AT(location)) { + if (COUNT_AT(state, location)) { return ACT_ILLEGAL; } else { switch (stone) { - case STONE_STANDING: - if (ply < 2) return ACT_ILLEGAL; - // behold the magic GCC comment which defeates - // -Wimplicit-fallthrough: - // fall through - case STONE_FLAT: { - if (colour == C_BLACK) { - if (black_count & 127) black_count--; - else return ACT_ILLEGAL; - } else { - if (white_count & 127) white_count--; - else return ACT_ILLEGAL; - } - break; + case STONE_STANDING: + if (state->ply < 2) + return ACT_ILLEGAL; + // behold the magic GCC comment which defeates + // -Wimplicit-fallthrough: + // fall through + case STONE_FLAT: { + if (colour == C_BLACK) { + if (state->black_count & 127) + state->black_count--; + else + return ACT_ILLEGAL; + } else { + if (state->white_count & 127) + state->white_count--; + else + return ACT_ILLEGAL; } - case STONE_CAPSTONE: { - if (ply < 2) return ACT_ILLEGAL; - if (colour == C_BLACK) { - if (black_count & 128) black_count &= 127; - else return ACT_ILLEGAL; - } else { - if (white_count & 128) white_count &= 127; - else return ACT_ILLEGAL; - } - break; + break; + } + case STONE_CAPSTONE: { + if (state->ply < 2) + return ACT_ILLEGAL; + if (colour == C_BLACK) { + if (state->black_count & 128) + state->black_count &= 127; + else + return ACT_ILLEGAL; + } else { + if (state->white_count & 128) + state->white_count &= 127; + else + return ACT_ILLEGAL; } + break; + } } - colours[location] = colour; - celldat[location] = NUM_INC | stone; + state->colours[location] = colour; + state->celldat[location] = NUM_INC | stone; return ACT_OK; } } @@ -123,59 +131,63 @@ try_place(const int8_t location, const enum COLOUR colour, // Moving stacks // =================================================================== -static inline void -push_stones(const int8_t location, const uint8_t count, - const uint8_t new_colours, - const enum STONE_VARIANT top_stone) { - colours[location] = (colours[location] << count) | new_colours; - celldat[location] = top_stone - | ((celldat[location] + ((count << NUM_SHIFT))) & NUM_MASK); +static inline void push_stones(tak_state_p state, const int8_t location, + const uint8_t count, const uint8_t new_colours, + const enum STONE_VARIANT top_stone) { + state->colours[location] = (state->colours[location] << count) | new_colours; + state->celldat[location] = + top_stone | + ((state->celldat[location] + ((count << NUM_SHIFT))) & NUM_MASK); } -enum ACT_RESULT -try_move(const int8_t location, const enum MOVE_DIRECTION direction, - const uint8_t steps, const uint8_t drops[5]) { +enum ACT_RESULT try_move(tak_state_p state, const int8_t location, + const enum MOVE_DIRECTION direction, + const uint8_t steps, const uint8_t drops[5]) { // Game is over? - if (won < 0xFF) return GAME_END; + if (state->won < 0xFF) + return GAME_END; // Can't do this - if (steps == 0 || steps > board_size) return ACT_ILLEGAL; + if (steps == 0 || steps > state->board_size) + return ACT_ILLEGAL; // Check for stones at all - const uint8_t avail = COUNT_AT(location); - if (avail == 0) return ACT_ILLEGAL; + const uint8_t avail = COUNT_AT(state, location); + if (avail == 0) + return ACT_ILLEGAL; // Does the current player own the pile? - if ((colours[location] & 1) != current_colour) return ACT_ILLEGAL; + if ((state->colours[location] & 1) != state->current_colour) + return ACT_ILLEGAL; // Is the desired direction and count on the board? int8_t delta = 0; switch (direction) { - case M_UP: { - delta = +board_size; - if (location + delta * steps > NUM_SQUARES) - return ACT_ILLEGAL; - break; - }; - case M_DOWN: { - delta = -board_size; - if (location + delta * steps < 0) - return ACT_ILLEGAL; - break; - }; - case M_RIGHT: { - delta = +1; - if ((location + steps * delta) / board_size - > location / board_size) - return ACT_ILLEGAL; - break; - }; - case M_LEFT: { - delta = -1; - // We need the extra check for zero here because, irritatingly, - // -1 / board_size == 1 / board_size - if ((location + steps * delta < 0) || - ((location + steps * delta) / board_size - < location / board_size)) - return ACT_ILLEGAL; - break; - }; + case M_UP: { + delta = +state->board_size; + if (location + delta * steps > NUM_SQUARES(state->board_size)) + return ACT_ILLEGAL; + break; + }; + case M_DOWN: { + delta = -state->board_size; + if (location + delta * steps < 0) + return ACT_ILLEGAL; + break; + }; + case M_RIGHT: { + delta = +1; + if ((location + steps * delta) / state->board_size > + location / state->board_size) + return ACT_ILLEGAL; + break; + }; + case M_LEFT: { + delta = -1; + // We need the extra check for zero here because, irritatingly, + // -1 / board_size == 1 / board_size + if ((location + steps * delta < 0) || + ((location + steps * delta) / state->board_size < + location / state->board_size)) + return ACT_ILLEGAL; + break; + }; }; // For every square in the direction @@ -185,27 +197,25 @@ try_move(const int8_t location, const enum MOVE_DIRECTION direction, if (drops[k] == 0) return ACT_ILLEGAL; // Can't drop more than BOARD_SIZE stones in a square - if (drops[k] > board_size) + if (drops[k] > state->board_size) return ACT_ILLEGAL; // Check for overflows - if (COUNT_AT(location+(k+1)*delta) + drops[k] > 0x0F) + if (COUNT_AT(state, location + (k + 1) * delta) + drops[k] > 0x0F) return ACT_OVERFLOW; // Check for capstone - if (STONE_AT(location+(k+1)*delta) == STONE_CAPSTONE) + if (STONE_AT(state, location + (k + 1) * delta) == STONE_CAPSTONE) return ACT_ILLEGAL; // Check for wall - if ( (STONE_AT(location+(k+1)*delta) == STONE_STANDING) - // If not last drop, or not dropping just one, or not a cap - && ( (k+1 < steps) - || (drops[k] != 1) - || (STONE_AT(location) != STONE_CAPSTONE) ) - ) + if ((STONE_AT(state, location + (k + 1) * delta) == STONE_STANDING) + // If not last drop, or not dropping just one, or not a cap + && ((k + 1 < steps) || (drops[k] != 1) || + (STONE_AT(state, location) != STONE_CAPSTONE))) return ACT_ILLEGAL; total += drops[k]; } // Can't ask to move 0, more than board_size, or stones available - if ( (total == 0) || (total > board_size) || (total > avail) ) + if ((total == 0) || (total > state->board_size) || (total > avail)) return ACT_ILLEGAL; // Nothing illegal, do it. First we add the stones to the @@ -213,15 +223,14 @@ try_move(const int8_t location, const enum MOVE_DIRECTION direction, uint8_t j = total; for (uint8_t k = 0; k < steps; k++) { j -= drops[k]; - push_stones(location+(k+1)*delta, - drops[k], - (colours[location] >> j) & (0xFFFF >> (0x10 - drops[k])), - (k == steps - 1) ? STONE_AT(location) : STONE_FLAT); + push_stones(state, location + (k + 1) * delta, drops[k], + (state->colours[location] >> j) & (0xFFFF >> (0x10 - drops[k])), + (k == steps - 1) ? STONE_AT(state, location) : STONE_FLAT); } // Then we drop them from the source - colours[location] >>= total; - const uint8_t dec_count = celldat[location] - (total << NUM_SHIFT); - celldat[location] = dec_count & NUM_MASK; + state->colours[location] >>= total; + const uint8_t dec_count = state->celldat[location] - (total << NUM_SHIFT); + state->celldat[location] = dec_count & NUM_MASK; return ACT_OK; } @@ -231,9 +240,10 @@ try_move(const int8_t location, const enum MOVE_DIRECTION direction, // =================================================================== // Check for the presence of a road connecting opposite sides -static enum WIN_TYPE -check_road_colour(const enum COLOUR colour) { - int component[NUM_SQUARES], touching[NUM_SQUARES]; +static enum WIN_TYPE check_road_colour(tak_state_p state, + const enum COLOUR colour) { + int component[NUM_SQUARES(state->board_size)], + touching[NUM_SQUARES(state->board_size)]; /* We're doing a poor version of a disjoint set data structure to @@ -249,10 +259,10 @@ check_road_colour(const enum COLOUR colour) { the same reason we also don't do path flattening/halving or anything. */ - for (int k=0; kboard_size); k++) { component[k] = k; // every square is in its own connected // component initially - touching[k] = 0; // and not connected to any sides + touching[k] = 0; // and not connected to any sides } // touching is the bit mask for connectivity, @@ -260,90 +270,95 @@ check_road_colour(const enum COLOUR colour) { // 1 2 4 8 int touch = 5; - for (int row = 0; row < board_size; row++) { - for (int col = 0; col < board_size; col++) { - const int cur = THE_COORDS(col, row); - if (COUNT_AT(cur) - && (colours[cur] & 1) == colour - && STONE_AT(cur) != STONE_STANDING) { - - // do we have any neighbours to the left and below? - const int left_neighbour = ((cur % board_size > 0) - && (COUNT_AT(cur - 1)) // wont ever be out of bounds - && ((colours[cur - 1] & 1) == colour) - && (STONE_AT(cur - 1) != STONE_STANDING)); - - const int lowr_neighbour = ((cur >= board_size) - && (COUNT_AT(cur - board_size)) - && ((colours[cur - board_size] & 1) == colour) - && (STONE_AT(cur - board_size) != STONE_STANDING)); - - // always take the component of the lower neighbour if - // possible, failing that take the left neighbour, otherwise - // we're not yet connected, so update our own component. - if (lowr_neighbour) { - // look up the root of the lower neighbour - int root = cur - board_size; - while (root != component[root]) - root = component[root]; - // join the set - component[cur] = root; - if (touch) { - // something new - touching[root] |= touch; - // are we done? - if ( (touching[root] & 0x3) == 0x3 || (touching[root] & 0xC) == 0xC) - return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; - } - // if we also have a left neighbour then we should `merge' - // sets, and here we assume that the left neighbour set is - // always smaller (may not be) for the direction of merge - if (left_neighbour) { - int left_root = cur - 1; - while (left_root != component[left_root]) - left_root = component[left_root]; - // merge - const int left_touch = touching[left_root]; - if (left_touch) { - touching[root] |= left_touch; - if ( (touching[root] & 0x3) == 0x3 || (touching[root] & 0xC) == 0xC) - return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; - } - component[left_root] = root; - } - } else if (left_neighbour) { - int root = cur - 1; - while (root != component[root]) - root = component[root]; - component[cur] = root; - if (touch) { - touching[root] |= touch; - if ( (touching[root] & 0x3) == 0x3 || (touching[root] & 0xC) == 0xC) - return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; - } - } else if (touch) { - // we had no left or lower neighbour, so we're on our own - touching[cur] = touch; - } + for (int row = 0; row < state->board_size; row++) { + for (int col = 0; col < state->board_size; col++) { + const int cur = THE_COORDS(state->board_size, col, row); + if (COUNT_AT(state, cur) && (state->colours[cur] & 1) == colour && + STONE_AT(state, cur) != STONE_STANDING) { + + // do we have any neighbours to the left and below? + const int left_neighbour = + ((cur % state->board_size > 0) && + (COUNT_AT(state, cur - 1)) // wont ever be out of bounds + && ((state->colours[cur - 1] & 1) == colour) && + (STONE_AT(state, cur - 1) != STONE_STANDING)); + + const int lowr_neighbour = + ((cur >= state->board_size) && + (COUNT_AT(state, cur - state->board_size)) && + ((state->colours[cur - state->board_size] & 1) == colour) && + (STONE_AT(state, cur - state->board_size) != STONE_STANDING)); + + // always take the component of the lower neighbour if + // possible, failing that take the left neighbour, otherwise + // we're not yet connected, so update our own component. + if (lowr_neighbour) { + // look up the root of the lower neighbour + int root = cur - state->board_size; + while (root != component[root]) + root = component[root]; + // join the set + component[cur] = root; + if (touch) { + // something new + touching[root] |= touch; + // are we done? + if ((touching[root] & 0x3) == 0x3 || (touching[root] & 0xC) == 0xC) + return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; + } + // if we also have a left neighbour then we should `merge' + // sets, and here we assume that the left neighbour set is + // always smaller (may not be) for the direction of merge + if (left_neighbour) { + int left_root = cur - 1; + while (left_root != component[left_root]) + left_root = component[left_root]; + // merge + const int left_touch = touching[left_root]; + if (left_touch) { + touching[root] |= left_touch; + if ((touching[root] & 0x3) == 0x3 || + (touching[root] & 0xC) == 0xC) + return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; + } + component[left_root] = root; + } + } else if (left_neighbour) { + int root = cur - 1; + while (root != component[root]) + root = component[root]; + component[cur] = root; + if (touch) { + touching[root] |= touch; + if ((touching[root] & 0x3) == 0x3 || (touching[root] & 0xC) == 0xC) + return (colour == C_BLACK) ? WIN_ROAD_BLACK : WIN_ROAD_WHITE; + } + } else if (touch) { + // we had no left or lower neighbour, so we're on our own + touching[cur] = touch; + } } - if (col + 2 == board_size) touch |= 8; - else touch &= 0x3; + if (col + 2 == state->board_size) + touch |= 8; + else + touch &= 0x3; } - if (row + 2 == board_size) touch = 6; - else touch = 4; + if (row + 2 == state->board_size) + touch = 6; + else + touch = 4; } return 0xFF; } -enum WIN_TYPE -check_win(void) { +enum WIN_TYPE check_win(tak_state_p state) { // Road? enum WIN_TYPE rb, rw; - rb = check_road_colour(C_BLACK); - rw = check_road_colour(C_WHITE); + rb = check_road_colour(state, C_BLACK); + rw = check_road_colour(state, C_WHITE); if (rb == WIN_ROAD_BLACK && rw == WIN_ROAD_WHITE) { - return (ply & 1) ? rb : rw; // Dragons + return (state->ply & 1) ? rb : rw; // Dragons } else if (rw == WIN_ROAD_WHITE) { return rw; } else if (rb == WIN_ROAD_BLACK) { @@ -352,18 +367,21 @@ check_win(void) { // Do we do a flat count? int8_t total = 0, board_full = 1; - for (uint8_t k = 0; k < NUM_SQUARES; k++) { - if (COUNT_AT(k) == 0) { + for (uint8_t k = 0; k < NUM_SQUARES(state->board_size); k++) { + if (COUNT_AT(state, k) == 0) { board_full = 0; - } else if (STONE_AT(k) == STONE_FLAT) { - total += ((colours[k] & 1) == C_BLACK) ? +1 : -1 ; + } else if (STONE_AT(state, k) == STONE_FLAT) { + total += ((state->colours[k] & 1) == C_BLACK) ? +1 : -1; } } - if (black_count == 0 || white_count == 0 || board_full) { + if (state->black_count == 0 || state->white_count == 0 || board_full) { // Decide based on count - if (total > 0) return WIN_FLAT_BLACK; - else if (total < 0) return WIN_FLAT_WHITE; - else return WIN_DRAW; + if (total > 0) + return WIN_FLAT_BLACK; + else if (total < 0) + return WIN_FLAT_WHITE; + else + return WIN_DRAW; } return 0xFF; @@ -372,38 +390,57 @@ check_win(void) { // PTN place parser // =================================================================== -#define NULL 0 - -#define ASSERT_NONEMPTY { \ - if (ptn == NULL || *ptn == 0) return PTN_INVALID; \ +#define ASSERT_NONEMPTY \ + { \ + if (ptn == NULL || *ptn == 0) \ + return PTN_INVALID; \ } -#define ASSERT_MORE { if (*ptn == 0) return PTN_INVALID; } +#define ASSERT_MORE \ + { \ + if (*ptn == 0) \ + return PTN_INVALID; \ + } -enum PTN_RESULT -parse_place(char *ptn, uint8_t *out_location, - enum STONE_VARIANT *out_stone) { +enum PTN_RESULT parse_place(const uint8_t board_size, char *ptn, + uint8_t *out_location, + enum STONE_VARIANT *out_stone) { ASSERT_NONEMPTY; *out_stone = STONE_FLAT; switch (*ptn) { - case 'C' : { ptn++; *out_stone = STONE_CAPSTONE; break; }; - case 'S' : { ptn++; *out_stone = STONE_STANDING; break; }; - case 'F' : { ptn++; break; }; + case 'C': { + ptn++; + *out_stone = STONE_CAPSTONE; + break; + }; + case 'S': { + ptn++; + *out_stone = STONE_STANDING; + break; + }; + case 'F': { + ptn++; + break; + }; } ASSERT_MORE; - if ( (*ptn < 'a') || (*ptn > '`' + board_size) ) return PTN_INVALID; + if ((*ptn < 'a') || (*ptn > '`' + board_size)) + return PTN_INVALID; *out_location = *ptn - 'a'; - ptn++; ASSERT_MORE; + ptn++; + ASSERT_MORE; - if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; + if ((*ptn < '1') || (*ptn > board_size + '0')) + return PTN_INVALID; *out_location += board_size * (*ptn - '1'); - if (*(++ptn) > 0) return PTN_INVALID; + if (*(++ptn) > 0) + return PTN_INVALID; return PTN_OK; } @@ -412,40 +449,58 @@ parse_place(char *ptn, uint8_t *out_location, // PTN move parser // =================================================================== -enum PTN_RESULT -parse_move(char *ptn, uint8_t *out_location, - enum MOVE_DIRECTION *out_direction, - uint8_t *out_steps, uint8_t out_drops[5]) { +enum PTN_RESULT parse_move(const uint8_t board_size, char *ptn, + uint8_t *out_location, + enum MOVE_DIRECTION *out_direction, + uint8_t *out_steps, uint8_t out_drops[5]) { ASSERT_NONEMPTY; uint8_t picked_up = 1; // Optionally indicate how many stones picked up - if ( (*ptn >= '1') && (*ptn <= '0' + board_size)) { + if ((*ptn >= '1') && (*ptn <= '0' + board_size)) { picked_up = *ptn - '0'; - ptn++; ASSERT_MORE; + ptn++; + ASSERT_MORE; } // column must be on the board - if ( (*ptn < 'a') || (*ptn > '`' + board_size) ) return PTN_INVALID; + if ((*ptn < 'a') || (*ptn > '`' + board_size)) + return PTN_INVALID; *out_location = *ptn - 'a'; - ptn++; ASSERT_MORE; + ptn++; + ASSERT_MORE; // row must be on the board - if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; + if ((*ptn < '1') || (*ptn > board_size + '0')) + return PTN_INVALID; *out_location += board_size * (*ptn - '1'); - ptn++; ASSERT_MORE; + ptn++; + ASSERT_MORE; // valid direction switch (*ptn) { - case '+': { *out_direction = M_UP; break; } - case '-': { *out_direction = M_DOWN; break; } - case '<': { *out_direction = M_LEFT; break; } - case '>': { *out_direction = M_RIGHT; break; } - default: return PTN_INVALID; + case '+': { + *out_direction = M_UP; + break; + } + case '-': { + *out_direction = M_DOWN; + break; + } + case '<': { + *out_direction = M_LEFT; + break; + } + case '>': { + *out_direction = M_RIGHT; + break; + } + default: + return PTN_INVALID; } // Handle the case 'n' as @@ -463,11 +518,11 @@ parse_move(char *ptn, uint8_t *out_location, uint8_t total = 0; while (*ptn) { // can't drop more than the carry limit, or less than 1 - if ( (*ptn < '1') || (*ptn > '0' + board_size) ) + if ((*ptn < '1') || (*ptn > '0' + board_size)) return PTN_INVALID; // can't move more than the size of the board in any direction - if ( (*out_steps + 1 >= board_size) && *ptn) + if ((*out_steps + 1 >= board_size) && *ptn) return PTN_INVALID; out_drops[*out_steps] = *ptn - '0'; @@ -477,7 +532,8 @@ parse_move(char *ptn, uint8_t *out_location, } // Mismatch between number of stones picked up and total dropped - if ( total != picked_up ) return PTN_INVALID; + if (total != picked_up) + return PTN_INVALID; return PTN_OK; } @@ -486,16 +542,27 @@ parse_move(char *ptn, uint8_t *out_location, // Generate PTN for place // =================================================================== -void -generate_place(const uint8_t in_location, - const enum STONE_VARIANT in_stone, char out_ptn[4]) { +void generate_place(const uint8_t board_size, const uint8_t in_location, + const enum STONE_VARIANT in_stone, char out_ptn[4]) { switch (in_stone) { - case STONE_FLAT: { break; } - case STONE_STANDING: { *out_ptn = 'S'; out_ptn++; break; } - case STONE_CAPSTONE: { *out_ptn = 'C'; out_ptn++; break; } + case STONE_FLAT: { + break; + } + case STONE_STANDING: { + *out_ptn = 'S'; + out_ptn++; + break; + } + case STONE_CAPSTONE: { + *out_ptn = 'C'; + out_ptn++; + break; } - *out_ptn = 'a' + (in_location % board_size); out_ptn++; - *out_ptn = '1' + (in_location / board_size); out_ptn++; + } + *out_ptn = 'a' + (in_location % board_size); + out_ptn++; + *out_ptn = '1' + (in_location / board_size); + out_ptn++; *out_ptn = 0; } @@ -503,29 +570,46 @@ generate_place(const uint8_t in_location, // Generate PTN for move // =================================================================== -void -generate_move(const uint8_t in_location, - const enum MOVE_DIRECTION in_direction, - const uint8_t in_steps, const uint8_t in_drops[5], - char out_ptn[10]) { +void generate_move(const uint8_t board_size, const uint8_t in_location, + const enum MOVE_DIRECTION in_direction, + const uint8_t in_steps, const uint8_t in_drops[5], + char out_ptn[10]) { uint8_t total = 0; - for (uint8_t k = 0; k 1) { - *out_ptn = '0' + total; out_ptn++; + *out_ptn = '0' + total; + out_ptn++; } - *out_ptn = 'a' + (in_location % board_size); out_ptn++; - *out_ptn = '1' + (in_location / board_size); out_ptn++; + *out_ptn = 'a' + (in_location % board_size); + out_ptn++; + *out_ptn = '1' + (in_location / board_size); + out_ptn++; switch (in_direction) { - case M_UP: { *out_ptn = '+'; break; } - case M_DOWN: { *out_ptn = '-'; break; } - case M_LEFT: { *out_ptn = '<'; break; } - case M_RIGHT: { *out_ptn = '>'; break; } - }; out_ptn++; + case M_UP: { + *out_ptn = '+'; + break; + } + case M_DOWN: { + *out_ptn = '-'; + break; + } + case M_LEFT: { + *out_ptn = '<'; + break; + } + case M_RIGHT: { + *out_ptn = '>'; + break; + } + }; + out_ptn++; for (uint8_t k = 0; (total > 1) && (k < in_steps); k++) { - *out_ptn = '0' + in_drops[k]; out_ptn++; + *out_ptn = '0' + in_drops[k]; + out_ptn++; } *out_ptn = 0; @@ -535,24 +619,26 @@ generate_move(const uint8_t in_location, // Driver // =================================================================== -static uint8_t -is_not_placement(char *ptn) { - if (ptn == 0) return 0; - for (;;ptn++) { +static uint8_t is_not_placement(char *ptn) { + if (ptn == 0) + return 0; + for (;; ptn++) { switch (*ptn) { - case '+': - case '-': - case '>': - case '<': return 1; - case 0: return 0; + case '+': + case '-': + case '>': + case '<': + return 1; + case 0: + return 0; } } } -enum ACT_RESULT -do_ptn(char *ptn) { +enum ACT_RESULT do_ptn(tak_state_p state, char *ptn) { // Game over? - if (won < 0xFF) return GAME_END; + if (state->won < 0xFF) + return GAME_END; enum PTN_RESULT ptn_res; enum ACT_RESULT act_res; @@ -563,11 +649,13 @@ do_ptn(char *ptn) { uint8_t steps, drops[5]; enum MOVE_DIRECTION direction; // Parse it as a move - ptn_res = parse_move(ptn, &location, &direction, &steps, drops); + ptn_res = parse_move(state->board_size, ptn, &location, &direction, &steps, + drops); // If valid PTN, try to do it if (ptn_res == PTN_OK) { - if (ply < 2) return ACT_ILLEGAL; - act_res = try_move(location, direction, steps, drops); + if (state->ply < 2) + return ACT_ILLEGAL; + act_res = try_move(state, location, direction, steps, drops); } else { return ACT_INVALID_PTN; } @@ -575,10 +663,10 @@ do_ptn(char *ptn) { // It was not a move enum STONE_VARIANT stone; // Was it a valid placement? - ptn_res = parse_place(ptn, &location, &stone); + ptn_res = parse_place(state->board_size, ptn, &location, &stone); // If so, try it if (ptn_res == PTN_OK) - act_res = try_place(location, current_colour, stone); + act_res = try_place(state, location, state->current_colour, stone); else return ACT_INVALID_PTN; } @@ -586,16 +674,16 @@ do_ptn(char *ptn) { if (act_res == ACT_OK) { // Don't bother checking that the game was won early on, could be // more conservative here :) - if (ply >= board_size) { - won = check_win(); - if (won < 0xFF) { - // Winning move, but no need to update current colour - ply++; - return GAME_END; + if (state->ply >= state->board_size) { + state->won = check_win(state); + if (state->won < 0xFF) { + // Winning move, but no need to update current colour + state->ply++; + return GAME_END; } } // Only step if the game isn't over yet - next_ply(); + next_ply(state); } return act_res; } diff --git a/include/tak.h b/include/tak.h index 26f4ae6..9f458f6 100644 --- a/include/tak.h +++ b/include/tak.h @@ -49,60 +49,61 @@ enum WIN_TYPE { typedef uint8_t data_t; typedef uint16_t colour_stack_t; +typedef struct tak_state_s { + data_t celldat[36]; + colour_stack_t colours[36]; + enum WIN_TYPE won; + enum COLOUR current_colour; + uint8_t white_count, black_count, ply, board_size; +} * tak_state_p; + #define NUM_SHIFT 4 #define NUM_MASK (0xF << NUM_SHIFT) // 0b11110000 #define NUM_INC (0x1 << NUM_SHIFT) // 0b00010000 #define STONE_MASK 3 // 0b00000011 -#define STONE_AT(l) (celldat[(l)] & STONE_MASK) -#define COUNT_AT(l) (celldat[(l)] >> NUM_SHIFT) -#define THE_COORDS(col, row) ((col) + (row)*board_size) - -// =================================================================== -// Variables -// =================================================================== - -// NOTE: We only support one capstone per player and 5s or 6s games. - -extern enum WIN_TYPE won; -extern uint8_t board_size; -extern data_t celldat[36]; -extern colour_stack_t colours[36]; -extern enum COLOUR current_colour; -extern uint8_t white_count, black_count, ply; +#define STONE_AT(state, l) (state->celldat[(l)] & STONE_MASK) +#define COUNT_AT(state, l) (state->celldat[(l)] >> NUM_SHIFT) +#define THE_COORDS(board_size, col, row) ((col) + (row)*board_size) // =================================================================== // Methods // =================================================================== +tak_state_p new_tak_state(const uint8_t board_size); +void free_tak_state(tak_state_p state); + // ------------------------------------------------------------------- // Game state -void reset_state(const uint8_t new_board_size); -void next_ply(void); +void reset_state(tak_state_p state, const uint8_t new_board_size); +void next_ply(tak_state_p state); -enum ACT_RESULT try_place(const int8_t location, const enum COLOUR colour, +enum ACT_RESULT try_place(tak_state_p state, const int8_t location, + const enum COLOUR colour, const enum STONE_VARIANT stone); -enum ACT_RESULT try_move(const int8_t location, +enum ACT_RESULT try_move(tak_state_p state, const int8_t location, const enum MOVE_DIRECTION direction, const uint8_t steps, const uint8_t drops[5]); -enum WIN_TYPE check_win(void); +enum WIN_TYPE check_win(tak_state_p state); // ------------------------------------------------------------------- // PTN related -enum PTN_RESULT parse_place(char *in_ptn, uint8_t *out_location, +enum PTN_RESULT parse_place(const uint8_t board_size, char *in_ptn, + uint8_t *out_location, enum STONE_VARIANT *out_stone); -enum PTN_RESULT parse_move(char *in_ptn, uint8_t *out_location, +enum PTN_RESULT parse_move(const uint8_t board_size, char *in_ptn, + uint8_t *out_location, enum MOVE_DIRECTION *out_direction, uint8_t *out_steps, uint8_t out_drops[5]); -void generate_place(const uint8_t in_location, +void generate_place(const uint8_t board_size, const uint8_t in_location, const enum STONE_VARIANT in_stone, char out_ptn[4]); -void generate_move(const uint8_t in_location, +void generate_move(const uint8_t board_size, const uint8_t in_location, const enum MOVE_DIRECTION in_direction, const uint8_t in_steps, const uint8_t in_drops[5], char out_ptn[10]); @@ -110,5 +111,5 @@ void generate_move(const uint8_t in_location, // ------------------------------------------------------------------- // Game driver -enum ACT_RESULT do_ptn(char *ptn); +enum ACT_RESULT do_ptn(tak_state_p state, char *ptn); #endif diff --git a/include/tps.c b/include/tps.c index 7be0e8d..ad0fe21 100644 --- a/include/tps.c +++ b/include/tps.c @@ -4,134 +4,166 @@ // Load TPS string // =================================================================== -#define TPS_ASSERT_MORE { if (*tps == 0) return TPS_INVALID; } +#define TPS_ASSERT_MORE \ + { \ + if (*tps == 0) \ + return TPS_INVALID; \ + } -enum TPS_RESULT -load_tps(char* tps) { +enum TPS_RESULT load_tps(tak_state_p state, char *tps) { // TODO: Ensure NULL termination? - if (tps == NULL) return TPS_INVALID; + if (tps == NULL) + return TPS_INVALID; uint8_t prefix = 0; // Check if we're likely of the form [TPS "blah"] if (!strncmp(tps, "[TPS \"", 6)) { - prefix=1; + prefix = 1; // Now we can worry about just the TPS part tps += 6; } // Reset everything - reset_state(board_size); + reset_state(state, state->board_size); // Parse squares, NOTE: We assume that board_size matches TPS size. - int col = 0, row = board_size-1, skip, parsing = 1; + int col = 0, row = state->board_size - 1, skip, parsing = 1; while (parsing) { switch (*tps) { - case ' ': { - // we're done - parsing = 0; - tps++; TPS_ASSERT_MORE; - break; - } - case 'x': { - // empty squares - tps++; TPS_ASSERT_MORE; - skip = 0; - if (*tps >= '2' && *tps <= '0'+board_size) { - skip = *tps - '1'; - tps++; TPS_ASSERT_MORE; - } else if (*tps != ',' && *tps != '/' && *tps != ' ') { - return TPS_INVALID; - } - col += skip; - if (col >= board_size + 1) return TPS_INVALID; - break; - } - case '/': { - // next row - if (col + 1 != board_size) return TPS_INVALID; - row--; col = 0; - if (row < 0) return TPS_INVALID; - tps++; TPS_ASSERT_MORE; - break; - } - case ',': { - // next column - col++; - if (col >= board_size) return TPS_INVALID; - tps++; TPS_ASSERT_MORE; - break; + case ' ': { + // we're done + parsing = 0; + tps++; + TPS_ASSERT_MORE; + break; + } + case 'x': { + // empty squares + tps++; + TPS_ASSERT_MORE; + skip = 0; + if (*tps >= '2' && *tps <= '0' + state->board_size) { + skip = *tps - '1'; + tps++; + TPS_ASSERT_MORE; + } else if (*tps != ',' && *tps != '/' && *tps != ' ') { + return TPS_INVALID; } - default: { - const int l = THE_COORDS(col, row); - uint8_t num_read = 0, reading = 1; - // Read in a stack of colours, optionally terminated by an S - // or C to change the top stone type - while (reading) { - switch (*tps) { - // Reading a stone colour - case '2': { - // check next letter to make sure we have the material - tps++; TPS_ASSERT_MORE; - if (*tps == 'C') { - if (black_count & 128) black_count &= 127; - else return TPS_INVALID; - } else if (black_count & 127) { - black_count--; - } else return TPS_INVALID; - colours[l] <<= 1; - celldat[l] += NUM_INC; - colours[l] |= 1; - num_read++; - break; - } - case '1': { - tps++; TPS_ASSERT_MORE; - if (*tps == 'C') { - if (white_count & 128) white_count &= 127; - else return TPS_INVALID; - } else if (white_count & 127) { - white_count--; - } else return TPS_INVALID; - colours[l] <<= 1; - celldat[l] += NUM_INC; - num_read++; - break; - } - case 'S': { - // Have we already read a stone type? - if (STONE_AT(l) != STONE_FLAT) return TPS_INVALID; - celldat[l] |= STONE_STANDING; - tps++; TPS_ASSERT_MORE; - break; - } - case 'C': { - if (STONE_AT(l) != STONE_FLAT) return TPS_INVALID; - celldat[l] |= STONE_CAPSTONE; - tps++; TPS_ASSERT_MORE; - break; - } - case ',': // fall-through - case '/': { - // done here - reading=0; - break; - } - default: return TPS_INVALID; - } - if (num_read > 0xF) return TPS_INVALID; - } + col += skip; + if (col >= state->board_size + 1) + return TPS_INVALID; + break; + } + case '/': { + // next row + if (col + 1 != state->board_size) + return TPS_INVALID; + row--; + col = 0; + if (row < 0) + return TPS_INVALID; + tps++; + TPS_ASSERT_MORE; + break; + } + case ',': { + // next column + col++; + if (col >= state->board_size) + return TPS_INVALID; + tps++; + TPS_ASSERT_MORE; + break; + } + default: { + const int l = THE_COORDS(state->board_size, col, row); + uint8_t num_read = 0, reading = 1; + // Read in a stack of colours, optionally terminated by an S + // or C to change the top stone type + while (reading) { + switch (*tps) { + // Reading a stone colour + case '2': { + // check next letter to make sure we have the material + tps++; + TPS_ASSERT_MORE; + if (*tps == 'C') { + if (state->black_count & 128) + state->black_count &= 127; + else + return TPS_INVALID; + } else if (state->black_count & 127) { + state->black_count--; + } else + return TPS_INVALID; + state->colours[l] <<= 1; + state->celldat[l] += NUM_INC; + state->colours[l] |= 1; + num_read++; + break; + } + case '1': { + tps++; + TPS_ASSERT_MORE; + if (*tps == 'C') { + if (state->white_count & 128) + state->white_count &= 127; + else + return TPS_INVALID; + } else if (state->white_count & 127) { + state->white_count--; + } else + return TPS_INVALID; + state->colours[l] <<= 1; + state->celldat[l] += NUM_INC; + num_read++; + break; + } + case 'S': { + // Have we already read a stone type? + if (STONE_AT(state, l) != STONE_FLAT) + return TPS_INVALID; + state->celldat[l] |= STONE_STANDING; + tps++; + TPS_ASSERT_MORE; + break; + } + case 'C': { + if (STONE_AT(state, l) != STONE_FLAT) + return TPS_INVALID; + state->celldat[l] |= STONE_CAPSTONE; + tps++; + TPS_ASSERT_MORE; + break; + } + case ',': // fall-through + case '/': { + // done here + reading = 0; + break; + } + default: + return TPS_INVALID; + } + if (num_read > 0xF) + return TPS_INVALID; } } + } } // Now it's time to parse the ply number. First, the active player - if (*tps != '1' && *tps != '2') return TPS_INVALID; - ply += *tps - '1'; - tps++; TPS_ASSERT_MORE; + if (*tps != '1' && *tps != '2') + return TPS_INVALID; + state->ply += *tps - '1'; + tps++; + TPS_ASSERT_MORE; // Space - if (*tps != ' ') return TPS_INVALID; - tps++; TPS_ASSERT_MORE; + if (*tps != ' ') + return TPS_INVALID; + tps++; + TPS_ASSERT_MORE; // Turn number, atoi doesn't detect errors so let's do it ourselves uint8_t p = 0; @@ -139,21 +171,27 @@ load_tps(char* tps) { p *= 10; if (*tps >= '0' && *tps <= '9') { p += *tps - '0'; - } else return TPS_INVALID; + } else + return TPS_INVALID; tps++; - } while ( (prefix && *tps && *tps != '"') || (!prefix && *tps) ); - if (p == 0) return TPS_INVALID; - ply += 2*(p - 1); + } while ((prefix && *tps && *tps != '"') || (!prefix && *tps)); + if (p == 0) + return TPS_INVALID; + state->ply += 2 * (p - 1); - current_colour = (ply & 1) ? C_BLACK : C_WHITE; - if (ply < 2) current_colour = C_BLACK - current_colour; + state->current_colour = (state->ply & 1) ? C_BLACK : C_WHITE; + if (state->ply < 2) + state->current_colour = C_BLACK - state->current_colour; if (prefix) { - tps++; TPS_ASSERT_MORE; - if (*tps != ']' ) return TPS_INVALID; + tps++; + TPS_ASSERT_MORE; + if (*tps != ']') + return TPS_INVALID; tps++; - if (*tps != 0) return TPS_INVALID; + if (*tps != 0) + return TPS_INVALID; } return TPS_OK; @@ -163,55 +201,68 @@ load_tps(char* tps) { // Generate TPS string // =================================================================== -void -generate_tps(char *out_tps) { +void generate_tps(tak_state_p state, char *out_tps) { strcpy(out_tps, "[TPS \""); out_tps += 6; - for (int8_t row = board_size - 1; row >= 0; row--) { - for (int8_t col = 0; col < board_size; col++) { - const int8_t l = THE_COORDS(col, row); - const uint8_t count = COUNT_AT(l); + for (int8_t row = state->board_size - 1; row >= 0; row--) { + for (int8_t col = 0; col < state->board_size; col++) { + const int8_t l = THE_COORDS(state->board_size, col, row); + const uint8_t count = COUNT_AT(state, l); if (count) { - colour_stack_t c = colours[l], s = 1<<(count - 1); - for (int k=0; k>=1, out_tps++) { - if (c & s) *out_tps = '2'; - else *out_tps = '1'; - } - switch (STONE_AT(l)) { - case STONE_CAPSTONE: { - *out_tps = 'C'; out_tps++; break; - } - case STONE_STANDING: { - *out_tps = 'S'; out_tps++; break; - } - default: break; - } + colour_stack_t c = state->colours[l], s = 1 << (count - 1); + for (int k = 0; k < count; k++, s >>= 1, out_tps++) { + if (c & s) + *out_tps = '2'; + else + *out_tps = '1'; + } + switch (STONE_AT(state, l)) { + case STONE_CAPSTONE: { + *out_tps = 'C'; + out_tps++; + break; + } + case STONE_STANDING: { + *out_tps = 'S'; + out_tps++; + break; + } + default: + break; + } } else { - int8_t skip = 1; - while (col < board_size && COUNT_AT(l+skip) == 0) { - skip++; - col++; - } - *out_tps = 'x'; out_tps++; - if (skip > 1) { - *out_tps = '0'+skip; out_tps++; - } + int8_t skip = 1; + while (col < state->board_size && COUNT_AT(state, l + skip) == 0) { + skip++; + col++; + } + *out_tps = 'x'; + out_tps++; + if (skip > 1) { + *out_tps = '0' + skip; + out_tps++; + } } - if (col + 1 < board_size) { - *out_tps = ','; out_tps++; + if (col + 1 < state->board_size) { + *out_tps = ','; + out_tps++; } } if (row > 0) { - *out_tps = '/'; out_tps++; + *out_tps = '/'; + out_tps++; } } - *out_tps = ' '; out_tps++; - *out_tps = '1' + (ply & 1); out_tps++; - *out_tps = ' '; out_tps++; + *out_tps = ' '; + out_tps++; + *out_tps = '1' + (state->ply & 1); + out_tps++; + *out_tps = ' '; + out_tps++; - out_tps += sprintf(out_tps, "%d", ply/2 + 1); + out_tps += sprintf(out_tps, "%d", state->ply / 2 + 1); strcpy(out_tps, "\"]"); } diff --git a/include/tps.h b/include/tps.h index 70cf1de..075b3f8 100644 --- a/include/tps.h +++ b/include/tps.h @@ -1,11 +1,9 @@ #include -#include // for strnlen, strncmp, and strcpy #include // for sprintf (in a single place! grrr) +#include // for strnlen, strncmp, and strcpy // NOTE: We assume that board_size matches TPS size. -enum TPS_RESULT -load_tps(char* in_tps); +enum TPS_RESULT load_tps(tak_state_p state, char *in_tps); -void -generate_tps(char *out_tps); +void generate_tps(tak_state_p state, char *out_tps); diff --git a/include/tt_llcht.c b/include/tt_llcht.c index b80da39..7b2269b 100644 --- a/include/tt_llcht.c +++ b/include/tt_llcht.c @@ -21,30 +21,29 @@ // Variables // =================================================================== -static tt_entry_t *table[TT_LLCHT_SIZE+1]; +static tt_entry_t *table[TT_LLCHT_SIZE + 1]; // =================================================================== // Helper declarations // =================================================================== -tt_entry_t * new_ll_node(const uint64_t key, const enum TT_FLAG flag, - const uint8_t depth, const float value, - const action_t action); - +tt_entry_t *new_ll_node(const uint64_t key, const enum TT_FLAG flag, + const uint8_t depth, const float value, + const action_t action); // =================================================================== // Exported functions // =================================================================== int tt_init(void) { - for (uint32_t k=0; k<=TT_LLCHT_SIZE; k++) + for (uint32_t k = 0; k <= TT_LLCHT_SIZE; k++) table[k] = NULL; return EXIT_SUCCESS; } void tt_free(void) { tt_entry_t *n, *nn; - for (uint32_t k=0; k<=TT_LLCHT_SIZE; k++) { + for (uint32_t k = 0; k <= TT_LLCHT_SIZE; k++) { n = table[k]; while (n) { nn = n->next; @@ -61,15 +60,15 @@ tt_entry_t *tt_seek(const uint64_t key) { return lookup; } -int tt_insert(const uint64_t key, const enum TT_FLAG flag, - const uint8_t depth, const float value, - const action_t action) { +int tt_insert(const uint64_t key, const enum TT_FLAG flag, const uint8_t depth, + const float value, const action_t action) { tt_entry_t *new = new_ll_node(key, flag, depth, value, action), *n; // TODO: trap const uint32_t idx = key & TT_LLCHT_SIZE; if ((n = table[idx]) != NULL) { - for (; n->next != NULL; n = n->next); + for (; n->next != NULL; n = n->next) + ; n->next = new; } else { table[idx] = new; @@ -82,9 +81,9 @@ int tt_insert(const uint64_t key, const enum TT_FLAG flag, // Helper function implementations // =================================================================== -tt_entry_t * new_ll_node(const uint64_t key, const enum TT_FLAG flag, - const uint8_t depth, const float value, - const action_t action) { +tt_entry_t *new_ll_node(const uint64_t key, const enum TT_FLAG flag, + const uint8_t depth, const float value, + const action_t action) { tt_entry_t *new = malloc(sizeof(struct tt_node_s)); // TODO: trap errno new->key = key; diff --git a/include/tt_llcht.h b/include/tt_llcht.h index 40d8bdb..dc73d26 100644 --- a/include/tt_llcht.h +++ b/include/tt_llcht.h @@ -18,8 +18,8 @@ #ifndef TT_LLCHT_H #define TT_LLCHT_H -#include #include +#include #include @@ -42,7 +42,7 @@ typedef struct tt_node_s { // Variables // =================================================================== -#define TT_LLCHT_SIZE ((uint32_t)((1<<19) - 1)) +#define TT_LLCHT_SIZE ((uint32_t)((1 << 19) - 1)) // =================================================================== // Methods @@ -53,8 +53,7 @@ void tt_free(void); tt_entry_t *tt_seek(const uint64_t key); -int tt_insert(const uint64_t key, const enum TT_FLAG flag, - const uint8_t depth, const float value, - const action_t action); +int tt_insert(const uint64_t key, const enum TT_FLAG flag, const uint8_t depth, + const float value, const action_t action); #endif diff --git a/include/weights.c b/include/weights.c index 82b55f9..1fa864e 100644 --- a/include/weights.c +++ b/include/weights.c @@ -14,20 +14,20 @@ * Trainable params: 1,986 * Non-trainable params: 0 * _________________________________________________________________ - * ([0.4593624770641327, 0.8171698451042175], [0.44635653495788574, 0.819940984249115]) + * ([0.5177317261695862, 0.755382776260376], [0.5241230130195618, 0.7530876398086548]) */ #include "weights.h" const float dense1_weights[DENSE_NUM][INP_NUM] = -{{0.09708841890096664, -0.14983339607715607, 0.9531096816062927, 0.14991514384746552, -0.63932865858078, 0.09746148437261581, -0.1670435070991516, 0.25754305720329285, -0.1731426864862442, -0.1653723269701004, -0.3116675615310669, 0.4331771433353424, 0.07788953930139542, -0.3911878764629364, -0.5864945650100708, -0.5138149261474609, -0.10366032272577286, 0.09420160204172134, 0.3116736114025116, -0.8269373774528503, -0.6619208455085754, -1.0483648777008057, -0.05252189561724663, 0.12044219672679901, 0.677895724773407, 0.9947460293769836, -1.109876036643982, -0.20052704215049744}, {0.04853341355919838, -0.44796833395957947, 1.0772864818572998, 0.12211384624242783, 0.43898314237594604, 0.19653372466564178, -0.010857676155865192, -0.34688177704811096, -1.917777180671692, -1.0062774419784546, -0.772797167301178, -0.6764053106307983, -0.15675123035907745, 0.20477063953876495, 0.0170141514390707, 0.0373976044356823, -0.3958517014980316, -0.17130737006664276, 0.10296492278575897, -0.10372677445411682, -0.07705003023147583, -0.21586216986179352, -0.06457874923944473, 0.18130557239055634, -0.19682471454143524, -0.10427158325910568, -0.6213868260383606, 0.2646593451499939}, {0.05100073665380478, -1.490741491317749, 0.5347241759300232, 0.5138917565345764, 0.7368579506874084, -0.3916100859642029, 0.10224276781082153, -0.8944575190544128, 0.9391179084777832, 0.8531733155250549, -0.7068527936935425, -0.1843581348657608, 0.10034217685461044, 0.7256124019622803, -0.5566624402999878, -0.630030632019043, 0.1081201434135437, 0.06458459794521332, -0.06652732193470001, -0.7848819494247437, 0.06676337122917175, 0.19047099351882935, 0.3317343592643738, -1.125041127204895, -0.15809980034828186, 0.7293155193328857, 0.7303928732872009, 0.24778194725513458}, {-0.10748109966516495, 1.3822530508041382, 0.2629156708717346, 0.6968264579772949, 0.17485041916370392, -0.20862552523612976, -0.12484818696975708, -0.23138242959976196, 0.8940210342407227, 0.7281381487846375, 0.2892467975616455, 0.07963291555643082, -0.07487558573484421, -0.1968744993209839, 0.8000355362892151, 0.6640182733535767, 0.22926642000675201, 0.2277926504611969, -0.37833377718925476, -0.2742082476615906, 0.8170139193534851, 0.4202984571456909, 0.27552902698516846, -0.46328070759773254, -0.3581807315349579, 0.10414467751979828, 0.7333625555038452, 0.35470449924468994}, {-0.1888720840215683, 0.9495699405670166, -0.6001124978065491, 0.2289646714925766, 0.1645985096693039, 0.010710741393268108, -0.07195031642913818, -0.3604000210762024, 0.40493911504745483, 0.06439553201198578, -0.1027727797627449, -0.18764203786849976, -0.020061621442437172, 0.41247984766960144, 0.0985364243388176, 0.03292955830693245, 0.13963104784488678, -0.1577671319246292, 0.8160413503646851, 0.3458573818206787, 0.15316851437091827, 0.09699071943759918, -0.15548554062843323, 0.06560410559177399, 0.5002033710479736, 0.6853768825531006, 0.913468599319458, 1.762925148010254}, {-0.05926303192973137, 2.1326680183410645, 0.20786024630069733, 0.20509517192840576, 0.3232854902744293, 0.4138268232345581, 0.23191986978054047, 0.1483074426651001, 0.30143123865127563, 0.36913859844207764, 0.2858075201511383, 0.27123841643333435, 0.21376250684261322, 0.2404519021511078, 0.4652462899684906, 0.23301848769187927, 0.3275870382785797, 0.3245834708213806, 0.35785531997680664, 0.21870960295200348, 0.28119996190071106, 0.385022908449173, 0.2985413074493408, 0.015570216812193394, 0.2387431263923645, 0.3773896098136902, 0.3013421595096588, 0.09287303686141968}, {-0.13003307580947876, 1.7538926601409912, -0.6812999844551086, -0.4881831109523773, -0.4694475829601288, 0.75823974609375, 0.2842443883419037, 0.31535980105400085, -0.4027916193008423, 0.6403568387031555, 0.7254506945610046, 0.31957608461380005, 0.6868956089019775, 0.6129562854766846, 0.6620163917541504, -0.19040672481060028, 0.2591014504432678, 0.17981182038784027, 0.3206057548522949, 0.26464489102363586, 0.12509778141975403, -0.1723550260066986, 0.5769479274749756, 0.27363383769989014, 0.40419286489486694, 0.4196736216545105, 0.474353551864624, 0.3851746618747711}, {0.004320172592997551, -0.06554269790649414, 1.0545583963394165, 0.03816256299614906, -0.3641563057899475, -0.04311445355415344, -1.0777692794799805, 0.3634617328643799, -0.2762683629989624, 0.2931346595287323, 0.12660370767116547, -0.8033497333526611, -0.08709059655666351, 0.2099713832139969, 0.38327884674072266, 0.11443039029836655, -0.8581308722496033, -0.6271834969520569, 0.01899813674390316, -0.36976635456085205, -0.9609361290931702, -1.242712140083313, -0.20354503393173218, -0.892693042755127, -1.3654234409332275, -0.1457122266292572, 0.4198227822780609, 0.47160959243774414}, {-0.1309877187013626, 1.7283211946487427, -0.34542015194892883, 0.09756244719028473, 0.10365703701972961, 0.16427665948867798, 0.5429031848907471, 0.000730195315554738, 0.9568342566490173, 0.43416130542755127, 0.5171336531639099, -0.03411416709423065, 0.09991542249917984, 0.22394727170467377, 0.46084511280059814, 0.2941528856754303, 0.40269896388053894, 0.4282401502132416, -0.043696314096450806, 0.9397956728935242, 0.4523789584636688, 0.21760058403015137, 0.25844889879226685, -0.0975789725780487, 1.4064749479293823, -0.4462650716304779, -0.0176702868193388, -0.15949156880378723}, {-0.09322677552700043, 1.4953668117523193, -0.6572163701057434, 0.03580909222364426, 0.07035914063453674, 1.2231422662734985, 0.14995643496513367, -0.01055422704666853, -0.3619900643825531, 0.00962253101170063, 1.1480656862258911, 0.04119277000427246, -0.029596557840704918, -0.20450031757354736, -0.20949582755565643, 1.3544684648513794, -0.07676524668931961, -0.33410149812698364, 0.14368489384651184, 0.18317444622516632, 0.9521495699882507, 0.2047186642885208, -0.14690256118774414, -0.002987049985677004, 0.22252139449119568, 0.5207418203353882, 0.3862583041191101, 0.04728662222623825}, {0.12120318412780762, -0.32054218649864197, 0.2999326288700104, 0.914248526096344, -0.25369349122047424, 1.0056365728378296, 1.0900052785873413, -1.9740498065948486, -0.2208552062511444, 0.12854935228824615, 0.17538198828697205, -0.1234835833311081, -1.1125203371047974, -0.3354377746582031, -0.5196758508682251, -0.30077362060546875, -0.5856597423553467, -0.8402205109596252, -0.22239884734153748, -0.4105615019798279, -0.38801825046539307, -0.8613605499267578, -0.27762359380722046, 0.49667125940322876, 0.020931968465447426, -0.12382236868143082, -0.4301914572715759, -0.350443035364151}, {-0.07766333967447281, 0.6034705638885498, -4.554388523101807, 0.2126956582069397, 0.15929296612739563, 0.17145121097564697, 0.1601206660270691, 0.17433294653892517, 0.12817388772964478, 0.11653872579336166, 0.14781475067138672, 0.23677119612693787, 0.12034492939710617, 0.1955379694700241, 0.13016147911548615, 0.23828306794166565, 0.14038963615894318, 0.15755616128444672, 0.23868830502033234, 0.26690152287483215, 0.1843731850385666, 0.17341510951519012, 0.057188548147678375, 0.2539713680744171, 0.2696954309940338, 0.18604490160942078, 0.14197516441345215, 0.36821600794792175}, {0.15129533410072327, 0.09887662529945374, 1.2054975032806396, 0.24753500521183014, 0.4909513294696808, -1.6100319623947144, 0.07008431106805801, 0.1423417031764984, -0.09243771433830261, -0.34568139910697937, -1.0303078889846802, 0.18709783256053925, 0.6571977138519287, -0.11068439483642578, -0.14676885306835175, -0.6726709008216858, -0.6291938424110413, 0.6409110426902771, -0.4643811285495758, -0.06342993676662445, -0.3956544101238251, -0.7433932423591614, -1.4594924449920654, -0.2231053113937378, -0.31123557686805725, 0.03604980930685997, -0.01676316000521183, -0.010373279452323914}, {0.08248379826545715, -0.33374691009521484, 0.4519060552120209, -0.3651171028614044, -1.0735950469970703, 0.005808517802506685, 1.2023851871490479, 0.7546958327293396, -0.19511595368385315, -0.5970048904418945, -1.1051145792007446, -0.513593316078186, 1.0888173580169678, 0.2880654036998749, 0.14094868302345276, -0.5696795582771301, -1.0076549053192139, 0.19139567017555237, 0.336557537317276, 0.3891679644584656, 0.09406869858503342, -0.8800191283226013, -0.5774187445640564, 0.18142414093017578, 0.17849640548229218, -0.11618805676698685, -0.6260532736778259, -0.39390552043914795}, {-0.07623733580112457, 1.0555744171142578, -0.17468947172164917, 0.18221747875213623, 0.06131114810705185, -0.014457565732300282, 0.1536666601896286, 0.6676269769668579, 0.17481842637062073, -0.14446255564689636, 0.04878826066851616, 0.27363839745521545, 0.5058372020721436, 0.16395719349384308, 0.19522777199745178, 0.31879734992980957, 0.8337258696556091, 0.612602710723877, 0.18271851539611816, 0.12550194561481476, 0.7062245011329651, 0.2406325489282608, -0.5638207793235779, 0.44285738468170166, 0.49697133898735046, 0.655937135219574, -0.5988529324531555, -0.6180514693260193}, {-0.08515164256095886, 1.8156886100769043, -0.3055272698402405, -0.00542338564991951, 0.28451383113861084, 0.3305817246437073, 0.44789642095565796, 0.007520807906985283, 0.6411338448524475, 0.6627947688102722, 0.3936305642127991, 0.543207585811615, 0.31023091077804565, 0.5907645225524902, -0.5054730772972107, 0.5622344613075256, 0.46472644805908203, 0.7537768483161926, 0.5771557092666626, 0.6231046915054321, 0.5562911629676819, 0.05025006830692291, 0.4974210858345032, -0.021163247525691986, 0.428413450717926, 0.2096228450536728, 0.1297932267189026, 0.15994444489479065}, {0.059478625655174255, -1.2593594789505005, 0.8060709238052368, -0.5756357312202454, -0.5642467141151428, -1.1023842096328735, -1.0840095281600952, -1.7373161315917969, 0.051716454327106476, -0.18114325404167175, 0.03431779146194458, 0.07772735506296158, 0.30920106172561646, 0.06860094517469406, 0.053684305399656296, 0.050935737788677216, 1.5831908967811614e-05, 0.06146225333213806, 0.14663179218769073, 0.01896907575428486, -0.017615582793951035, 0.049037203192710876, 0.3536975681781769, 0.5997693538665771, 0.06265199184417725, 0.018393227830529213, -0.03553879261016846, 0.15440478920936584}, {-0.06590350717306137, 0.6541862487792969, -0.9594393968582153, 1.5689195394515991, 0.995005190372467, 0.7445554733276367, 0.92704838514328, 0.4702519476413727, -0.3339536786079407, -0.18121398985385895, 0.12824110686779022, 0.32404643297195435, 0.08692658692598343, 0.06525395065546036, -0.07403562217950821, -0.08786602318286896, 0.30545052886009216, 0.1610720455646515, 0.025930603966116905, -0.006452936679124832, 0.04217161983251572, -0.00885680504143238, 0.01933605782687664, -0.5424081683158875, 0.03653205558657646, -0.09611544758081436, 0.07054111361503601, -0.33712488412857056}, {-0.033981095999479294, 0.7148251533508301, -0.9412906169891357, -0.14343379437923431, -0.10766273736953735, -0.11414168775081635, -0.13219089806079865, 1.2587040662765503, 0.008397090248763561, -0.10059479624032974, 0.13039082288742065, 0.12154032289981842, 1.238200306892395, -0.19973790645599365, -0.05784938111901283, 0.017947781831026077, -0.04616774618625641, 1.1192306280136108, 0.07938524335622787, -0.005415983498096466, 0.09550166130065918, 0.09772814065217972, 1.2091776132583618, -0.30785369873046875, -0.05821114033460617, -0.06727229803800583, -0.04389581456780434, 1.2299752235412598}, {0.1273789405822754, -0.341524600982666, 1.151167392730713, -0.04134071618318558, -0.07647605985403061, 0.36836978793144226, -1.3937312364578247, -0.16971394419670105, -0.1672888547182083, 0.05098025128245354, 0.4777861535549164, -1.6180260181427002, -0.14700591564178467, -0.42429643869400024, -0.571417510509491, -0.3194080591201782, -1.2477779388427734, 0.7285082340240479, -0.5621447563171387, -0.067803755402565, -0.33690130710601807, -1.2182284593582153, -0.026820745319128036, 0.24996322393417358, -0.04271029680967331, -0.25508779287338257, -0.18486416339874268, -0.2532777190208435}, {0.11533160507678986, 0.3406147062778473, 1.8792569637298584, 0.018996711820364, -0.2056526243686676, -0.33621448278427124, -0.20685425400733948, -0.24743612110614777, -0.17051126062870026, -0.584708034992218, -0.40372198820114136, -0.37256744503974915, -0.34893912076950073, -0.3406921923160553, -0.5737095475196838, 0.9329007267951965, -0.5134408473968506, -0.3319478929042816, -0.1288238763809204, -0.5994487404823303, -0.5022518038749695, -0.49213001132011414, -0.13361960649490356, -0.02503959834575653, -0.33584609627723694, -0.30276021361351013, -0.16746489703655243, 0.13810385763645172}, {-0.09611523896455765, 1.238119125366211, -0.4888734817504883, 0.20628002285957336, 0.37660905718803406, 0.22086504101753235, 1.418500542640686, -0.3454299569129944, 0.2719173729419708, 0.19811256229877472, 0.3238287568092346, 1.0737624168395996, -0.12214085459709167, 0.3549494743347168, 0.2717260420322418, -0.009705607779324055, 0.853428304195404, 0.24796196818351746, 0.33442437648773193, -0.13321736454963684, 0.13895970582962036, 0.3937171995639801, 0.6743841767311096, -0.2558365762233734, 0.33873921632766724, -0.2011198103427887, -0.24151191115379333, 1.0191739797592163}, {0.028014613315463066, -0.4389137625694275, 1.2217202186584473, 0.5615558624267578, 0.05263078957796097, 0.05092257261276245, -0.0025020919274538755, -0.10499066114425659, 0.22626706957817078, -0.18914547562599182, 0.04754278063774109, 0.03034340962767601, -0.22401578724384308, -1.2998645305633545, -0.9751662015914917, -0.7423930764198303, -0.3970774710178375, -0.061214447021484375, -0.08540238440036774, 0.45488816499710083, -0.14393432438373566, -0.23829105496406555, -0.26323971152305603, 0.2596847116947174, 0.37555330991744995, 0.11025014519691467, -0.4083321690559387, 0.15121963620185852}, {-0.21241767704486847, 1.6689105033874512, -0.226408913731575, 0.03731200098991394, 0.26310592889785767, 1.2660009860992432, -0.47913163900375366, -0.4116690158843994, 0.39553773403167725, 0.0419420562684536, 1.0190608501434326, 0.3955974280834198, -0.2669771909713745, 0.22511376440525055, 0.19040349125862122, 0.3689280152320862, 0.5754274725914001, 0.791631281375885, 0.17811143398284912, 0.364437997341156, 0.13787342607975006, 0.1953200399875641, 0.35008370876312256, 0.40746477246284485, 0.021115917712450027, 0.19234441220760345, 0.34583356976509094, 0.221570685505867}, {-0.056629478931427, 1.3422456979751587, -0.48497992753982544, -0.1941925585269928, 0.165594220161438, 0.287276953458786, 0.15132613480091095, 0.38584816455841064, 0.2143339067697525, 0.13520006835460663, 0.2816779315471649, 0.36108213663101196, 0.5532099604606628, 0.2023126780986786, 0.26956668496131897, 0.06489624828100204, 0.8025456070899963, 0.01022995077073574, 0.20568951964378357, 0.3348022401332855, 0.235650435090065, 1.00911283493042, -0.1623430848121643, -0.029755957424640656, 0.16051626205444336, -0.30153003334999084, 1.820574402809143, -0.18349412083625793}, {0.08210670948028564, -0.10644663870334625, 2.0925099849700928, -0.24863389134407043, -0.2665429711341858, -0.40262511372566223, -0.45371878147125244, -0.1377442479133606, -0.39157360792160034, -0.22115609049797058, -0.4804888963699341, -0.2904321551322937, -0.18321593105793, -0.33899354934692383, -0.3302883207798004, -0.2938438951969147, -0.18833966553211212, -0.30292198061943054, -0.35079896450042725, -0.2308332324028015, -0.343620240688324, -0.29516926407814026, -0.2986883819103241, -0.16443338990211487, -0.44009503722190857, -0.27044206857681274, -0.4302333891391754, -0.036748480051755905}, {-0.020061643794178963, 1.2271647453308105, -0.7192057967185974, 0.22154885530471802, -0.2719059884548187, 0.45283734798431396, 0.23891234397888184, 0.06230388209223747, -0.3005612790584564, 0.38583460450172424, 0.09369464963674545, 0.25240558385849, 0.22129446268081665, -0.14313091337680817, -0.03104626201093197, 0.07079270482063293, 0.4938150942325592, 0.4324195086956024, 1.1018677949905396, 1.2313228845596313, 0.8778300881385803, 1.1587250232696533, 0.23411384224891663, -0.05438053980469704, -0.20136210322380066, -0.25242170691490173, 0.27750808000564575, 0.13955263793468475}, {0.21351471543312073, 0.13765887916088104, 2.0183377265930176, -0.007917194627225399, -0.3589908182621002, -0.5994181036949158, -0.11847121268510818, 0.021346328780055046, -0.4103794991970062, -0.41012945771217346, 0.18445296585559845, -0.6636074185371399, -0.24117298424243927, -0.3390832841396332, -0.40450406074523926, -0.3359193205833435, -0.39004817605018616, -0.2984693646430969, -0.22267311811447144, -0.3200683295726776, -0.17157769203186035, -0.15781398117542267, -0.20106711983680725, -0.3199653625488281, -0.28912240266799927, -0.5469598174095154, -0.598488450050354, -0.20015941560268402}, {0.13156303763389587, -0.04746222496032715, 1.4406293630599976, 0.04010009765625, -0.19504183530807495, -0.3422450125217438, -0.30269885063171387, 0.03397633880376816, -0.34146347641944885, -0.2657840847969055, -0.5875772833824158, -0.3439021110534668, -0.24916069209575653, -0.06749272346496582, -0.6978026032447815, -0.5449330806732178, -0.6765002608299255, -0.374035120010376, -0.0997399315237999, -0.7321766018867493, 0.932058572769165, -0.7302301526069641, -0.10420955717563629, 0.09721499681472778, -0.7511874437332153, -0.5356468558311462, -0.7049369215965271, 0.10399650782346725}, {-0.026832129806280136, 0.9518526792526245, 0.027437914162874222, 0.03834706172347069, 0.19063116610050201, 0.06822194904088974, 0.025699865072965622, -0.0034538416657596827, 0.5062559247016907, 0.48999106884002686, 0.839417040348053, 1.0514994859695435, -0.33073392510414124, 0.4111200273036957, -0.09617988020181656, -0.6156681776046753, 0.7947877049446106, 0.5059559345245361, 0.3703654408454895, -0.01992918737232685, 0.010815472342073917, 0.7090519666671753, 0.33787572383880615, 0.3802514672279358, 0.27450019121170044, 0.7134937047958374, 0.47950777411460876, 0.07987868040800095}, {-0.12225848436355591, 1.7318753004074097, -0.2236385941505432, 0.164175882935524, 0.6606665253639221, -0.09252867102622986, -0.09040944278240204, -0.01922728307545185, 0.2076280564069748, 0.5997986793518066, 0.8389816284179688, 1.0328935384750366, 1.4117224216461182, 0.2752927839756012, 0.3150433599948883, 0.3206954002380371, 0.3793025016784668, -0.2018655240535736, 0.1428735852241516, 0.4109397232532501, 0.2945535182952881, 0.2752903401851654, 0.1045895516872406, -0.013057844713330269, 0.33169877529144287, 0.5139592885971069, 0.06500981748104095, -0.03201531246304512}, {0.037458743900060654, -0.0013948864070698619, 1.5822151899337769, 0.2050805389881134, -0.1646299958229065, -0.19420349597930908, -0.09858932346105576, 0.03837038576602936, -0.14196360111236572, -0.5955793857574463, -0.6105048656463623, -0.19990204274654388, -0.14786484837532043, -0.4259253144264221, 1.1276053190231323, -0.5819753408432007, -0.5576790571212769, -0.37708580493927, -0.4070882201194763, -0.5314394235610962, -0.6408591866493225, -0.3505810797214508, 0.024513090029358864, 0.16252656280994415, -0.3316267132759094, -0.22024187445640564, -0.29375335574150085, -0.08565379679203033}, {-0.0819413959980011, 1.0591763257980347, -0.7337607741355896, -0.17952848970890045, 0.8200972676277161, 0.8254687190055847, 0.8399497866630554, 1.0778814554214478, 0.32117852568626404, 0.6869990229606628, 0.4733969271183014, 0.19321654736995697, -0.2765744924545288, 0.39945876598358154, 0.6774672269821167, 0.09932424128055573, -0.20062103867530823, -0.2712205648422241, 0.7035691142082214, 0.20941823720932007, -0.1504993587732315, 0.1819196194410324, 0.0758715346455574, 0.9624840021133423, -0.10010877996683121, 0.047227196395397186, 0.07651358097791672, -0.15292885899543762}, {-0.03150544688105583, -0.02839292772114277, -0.5884301662445068, 0.039681024849414825, 0.08184020221233368, 0.10623382031917572, 0.009769861586391926, -0.07766010612249374, -0.021818384528160095, 0.2412724792957306, 0.11478745937347412, 0.05257875472307205, 0.07520901411771774, 0.05953354015946388, 0.22793656587600708, 0.12766006588935852, 0.15545566380023956, 0.09512616693973541, 0.1359385848045349, 0.2246624231338501, 0.1218600645661354, 0.13645589351654053, 0.022114301100373268, -0.0938657894730568, 0.053409822285175323, 0.04353907331824303, 0.05621011555194855, 0.024152453988790512}, {-0.10731056332588196, 1.9101223945617676, -0.14491631090641022, -0.31954917311668396, -0.13067302107810974, -0.38983073830604553, 1.2752583026885986, 0.10712035745382309, -0.02182578109204769, -0.27314284443855286, 0.5775480270385742, 0.8474040031433105, 0.3230977952480316, -0.09060269594192505, 0.5151476263999939, 0.8193845152854919, 0.4053916931152344, 0.2335839718580246, 1.1781198978424072, 0.8876485228538513, 0.494328111410141, 0.10951576381921768, 0.35883137583732605, 0.031916506588459015, 0.24021664261817932, 0.4334607720375061, 0.32361146807670593, 0.12500637769699097}, {-0.048089589923620224, 0.2517174184322357, -0.6230883598327637, 0.03189172223210335, 0.028296470642089844, 0.05605744197964668, 0.08526457846164703, 0.05624855309724808, 0.04614025354385376, 0.0461905337870121, 0.07688868790864944, 0.1092841625213623, 0.06774014234542847, -0.03262807056307793, 0.08905143290758133, 0.0877608135342598, 0.06686928868293762, 0.07233935594558716, 0.057617634534835815, 0.016904741525650024, 0.04663266986608505, 0.07950703799724579, 0.00545073114335537, 0.07434149831533432, 0.03768325597047806, 0.10711461305618286, 0.06703071296215057, 0.10979264229536057}, {-0.08404885232448578, -0.7368913888931274, 0.4573487937450409, 0.13284821808338165, 0.3613227605819702, 0.14185453951358795, 0.6336719393730164, -1.4996527433395386, 0.14475664496421814, 0.29121872782707214, 0.4278671443462372, 0.1410083919763565, -0.8940686583518982, 0.2855665683746338, 0.42577508091926575, 0.32199257612228394, -0.29421567916870117, -0.47793734073638916, 0.3777045011520386, 0.19965225458145142, -0.2553655505180359, -0.7715121507644653, -0.7749602794647217, -0.9258174300193787, -0.47367092967033386, -0.7522175312042236, -0.6750305891036987, -0.22101743519306183}, {0.14481350779533386, -0.008970635011792183, 1.508664608001709, 0.15015840530395508, -0.14811588823795319, 0.588955819606781, -1.0150330066680908, -0.053266044706106186, 0.07046253234148026, -1.5722743272781372, -1.0555866956710815, -1.0166481733322144, -0.24272829294204712, -0.41724616289138794, -0.8357856273651123, -0.03276902064681053, -0.04676911234855652, -0.26494157314300537, -0.4370666444301605, -0.7593159079551697, -0.053759537637233734, 0.3186907172203064, -0.5872452855110168, 0.03758898749947548, -0.4328208863735199, -0.21179579198360443, -0.40803515911102295, 0.0951615571975708}, {0.00908249244093895, -0.07688987255096436, 0.782505452632904, 0.06486380100250244, -0.2471565157175064, 0.021011406555771828, 0.022204816341400146, 0.1792861968278885, -0.13489873707294464, -0.036091145128011703, -0.43057775497436523, -0.031296003609895706, -0.2873421311378479, 0.22351358830928802, -0.026948416605591774, -0.8745213150978088, 0.11529920995235443, 0.24653159081935883, 0.5388697981834412, 0.47889870405197144, -1.1142454147338867, 0.3187515139579773, 0.38350510597229004, 0.02950381115078926, 0.29876217246055603, -2.0111100673675537, 0.5463553071022034, 0.14435721933841705}, {0.14901532232761383, -1.5044587850570679, 0.8972142338752747, 0.2778427302837372, -0.05853148549795151, 0.1994359791278839, -0.30804818868637085, -0.2415803223848343, -0.22669333219528198, -0.09136048704385757, -0.09575177729129791, -0.5684528946876526, -0.5545351505279541, 0.11623877286911011, -0.16263911128044128, -0.040955785661935806, -0.049217116087675095, -0.8552798628807068, -0.048276450484991074, 0.10525430738925934, 0.33164283633232117, 0.24776573479175568, -0.9200206398963928, 0.14236557483673096, -0.1810273379087448, 0.08166225254535675, 0.7190329432487488, -2.1177501678466797}, {-0.19271403551101685, 1.728354811668396, -0.49745607376098633, 0.13163147866725922, 0.4125182628631592, 0.3173934519290924, 0.3347082734107971, 0.1567714363336563, 0.44411492347717285, 0.5317234992980957, -0.5201308727264404, 0.5674026012420654, 0.41059064865112305, 0.49735933542251587, 0.624692440032959, 0.854070246219635, 0.6220293045043945, 0.3193413019180298, 0.22398653626441956, 0.40847501158714294, 0.5839058756828308, 0.1582852154970169, 0.33516645431518555, 0.03460458666086197, 0.4448821544647217, 0.8498842120170593, 0.3459503650665283, 0.11562537401914597}, {-0.047379519790410995, 1.703660488128662, -0.5990813374519348, -0.5269250273704529, 1.5372254848480225, -0.2775944471359253, 0.001394903170876205, -0.19458095729351044, -0.27556341886520386, 0.9208241105079651, 0.21152672171592712, 0.06251904368400574, 0.2743033468723297, 0.06462933868169785, 0.7903530597686768, 0.39518019556999207, 0.31461477279663086, 0.7033582925796509, 1.100284457206726, 0.583648681640625, 0.5865142941474915, -0.006218436639755964, 0.31119057536125183, 0.5512746572494507, 0.037552036345005035, -0.026546820998191833, 0.3478201627731323, 0.03815087676048279}, {0.028824783861637115, -0.32616135478019714, 1.2353787422180176, -0.4744008779525757, -1.8294140100479126, -0.17039445042610168, -0.16263258457183838, -0.27589941024780273, 0.02396584302186966, -0.6765327453613281, 0.026453670114278793, -0.20710843801498413, 0.12056914716959, -0.027168219909071922, -0.472407728433609, -0.06178409606218338, -0.02956007793545723, -0.03951815888285637, -0.16745562851428986, -0.19822148978710175, -0.06916672736406326, 0.018468298017978668, -0.5161017179489136, -0.3942733108997345, -0.036136265844106674, -0.22772735357284546, -0.1378902643918991, 0.15064162015914917}, {0.03982025757431984, -2.4930081367492676, 0.8281068801879883, -0.4357646107673645, 0.10274703055620193, -0.665107786655426, 0.5115349888801575, 0.32747960090637207, -0.09119489789009094, 0.2945898175239563, -0.1673634648323059, -0.6479430794715881, 0.1562136858701706, -1.237152338027954, -0.3490593731403351, 0.027165303006768227, -0.03953339904546738, -0.7550083994865417, 0.424204021692276, -0.8311765193939209, -0.3301525413990021, -0.052060894668102264, 0.24890226125717163, 0.5295188426971436, 0.2250201553106308, -0.709912896156311, 0.1652745008468628, 0.02529488131403923}, {0.030456073582172394, -0.5592262744903564, 1.432510256767273, -1.1988471746444702, -0.5064346194267273, -0.6237148642539978, 0.40195557475090027, 0.25146642327308655, 0.5024128556251526, -0.12030938267707825, -0.7599889039993286, -1.1147559881210327, -1.3214906454086304, 0.37952062487602234, 0.0130626754835248, -0.057461678981781006, -0.4395413398742676, -0.39032915234565735, -0.04154334217309952, 0.3974667191505432, -0.22250966727733612, -0.495175838470459, 0.04570012539625168, 0.31906959414482117, -0.14886492490768433, 0.3113555312156677, -0.6547025442123413, 0.08879609405994415}, {0.11950501054525375, -0.48032498359680176, 1.2850854396820068, 0.06694980710744858, -0.16385744512081146, -0.3026943802833557, -0.25026676058769226, 0.08888517320156097, 0.06509137898683548, -0.17576169967651367, -0.06554707139730453, -0.08778101950883865, -0.30888912081718445, 0.06313688308000565, -0.03595643863081932, -0.1171422153711319, -0.13362252712249756, -0.10691016912460327, -2.0260233879089355, -0.8719305992126465, -0.5115545392036438, -0.20826612412929535, 0.0837148055434227, -0.10446202009916306, 0.4123838543891907, -0.08748969435691833, -0.28654301166534424, -0.22568418085575104}, {-0.0004980643279850483, 1.6956111192703247, -0.9341049194335938, 0.3910086750984192, 0.9375659823417664, -0.599976658821106, -0.1314917951822281, -0.2129734605550766, 0.21699850261211395, 1.0505825281143188, 0.901665449142456, -0.0852508544921875, -0.17882975935935974, 0.2928134500980377, -0.2693397104740143, 0.8399291038513184, 0.6454485654830933, 0.3374834358692169, 0.04004263877868652, 0.24971531331539154, -0.05535968020558357, 0.7141254544258118, 0.5550016760826111, -0.20664328336715698, 0.16429021954536438, 0.6384597420692444, 0.4723033607006073, -0.08882896602153778}, {-0.14170923829078674, 1.3551650047302246, -0.9581169486045837, 0.9161777496337891, 0.030683813616633415, 0.2503061294555664, 0.07654116302728653, -0.013592132367193699, 0.4500807523727417, 0.961696445941925, 0.3948116898536682, 0.7503361105918884, 0.32386764883995056, -0.4451524317264557, 1.040030598640442, -0.16870202124118805, -0.37502360343933105, 0.5298779606819153, -0.11141359061002731, 1.0228924751281738, -0.31592369079589844, -0.04017551988363266, -0.15074723958969116, 0.0482744537293911, 1.1439263820648193, 0.4571666717529297, 0.12239103764295578, 0.4535315930843353}, {-0.032109931111335754, -0.12122310698032379, 0.8914746642112732, -0.27882638573646545, -0.11921525001525879, 0.32706254720687866, 0.2490244358778, 0.3580411672592163, -0.2604867219924927, -0.21825937926769257, -0.012418774887919426, 0.19902339577674866, 0.2708764672279358, 0.2748216688632965, -0.3405546247959137, -0.8040348291397095, -0.9789102077484131, -1.7298134565353394, -0.25523945689201355, -0.07197760790586472, -0.021183472126722336, 0.24487651884555817, 0.5359469652175903, -0.04558420553803444, -0.1392718106508255, 0.26097846031188965, 0.41951051354408264, 0.2396070510149002}, {-0.1434144526720047, 1.5024970769882202, -0.26019152998924255, -0.032202448695898056, 0.32650431990623474, 0.39354056119918823, 0.19199824333190918, 0.15139684081077576, 0.2088635414838791, 0.23116657137870789, 0.34120866656303406, 0.2512649595737457, 0.04610608145594597, 0.45557311177253723, 0.46523430943489075, 0.3187943994998932, 0.25996607542037964, -0.3529891073703766, 0.18252035975456238, 0.43683773279190063, 0.8012835383415222, 1.1804018020629883, 1.7978644371032715, 0.37052586674690247, 0.6495969295501709, 0.21544672548770905, -0.24423786997795105, -0.04839114099740982}, {0.08772090822458267, 0.036836814135313034, 0.4411259591579437, -0.2324865311384201, -0.4422452747821808, 0.3720940351486206, 0.0609813816845417, 0.4158213138580322, -0.6237788200378418, -1.4070799350738525, 1.0921244621276855, 0.4683806300163269, -0.1926126927137375, 0.5655200481414795, -1.2423927783966064, -0.6283270120620728, -0.5818661451339722, 0.1723531186580658, 0.5311585068702698, -0.6664415597915649, -0.42718756198883057, -0.5389712452888489, -0.5409123301506042, -0.19837777316570282, -0.42452719807624817, -0.42125552892684937, 0.2389526516199112, 0.04127349331974983}, {0.13081054389476776, -0.11356072872877121, 1.4752963781356812, -0.07947410643100739, -0.2676275968551636, -0.3330131471157074, -0.20006857812404633, -0.04646018147468567, -0.4903687834739685, -0.45940980315208435, -0.631168782711029, -0.4270765483379364, -0.3620588183403015, -0.27580520510673523, -0.44114959239959717, -0.7304320335388184, 0.9806434512138367, -0.47282716631889343, -0.19448859989643097, -0.6225467920303345, -1.0841974020004272, -0.738459587097168, -0.8378979563713074, -0.14952285587787628, -0.2907923758029938, -0.20345616340637207, -0.3887461721897125, 0.09503486752510071}, {-0.06538720428943634, 0.7628426551818848, -0.48973286151885986, -0.38497161865234375, 0.15466463565826416, 0.11393487453460693, 0.030808981508016586, -0.3597305119037628, 0.03768155723810196, 0.024493861943483353, 0.04951104521751404, 0.14642468094825745, 0.07216943800449371, -0.12633569538593292, 0.016758088022470474, 0.13920584321022034, 0.13626915216445923, 0.07511813938617706, -0.2962007224559784, -0.1386595219373703, 0.2720275819301605, 0.21500355005264282, 0.6123909950256348, 1.9834942817687988, 0.9948948621749878, 0.9978277683258057, 0.8778850436210632, 0.6260098218917847}, {-0.16871626675128937, 1.4061483144760132, -0.5023764371871948, 0.33703121542930603, 0.8559048771858215, 0.469501256942749, 0.7470555305480957, 0.30814874172210693, 0.564860999584198, 0.40895015001296997, 0.10864124447107315, 0.1458897590637207, 0.3857732117176056, 0.7911720871925354, 0.7119686603546143, -0.250042200088501, 0.17346656322479248, 0.3537016212940216, -0.41765081882476807, 1.0786654949188232, 0.8970625996589661, 0.5761362910270691, 0.5433169603347778, -0.6643967032432556, -0.48398444056510925, 1.2207279205322266, 0.514649510383606, 0.21612684428691864}, {-0.08570192009210587, 1.214324712753296, -0.13377290964126587, 0.34323278069496155, -0.14258965849876404, -0.18832489848136902, -0.08113601058721542, -0.029942357912659645, 0.0971248522400856, 0.11952006071805954, 0.09883774071931839, 0.2491564154624939, 0.07593998312950134, 1.131385087966919, 1.2205246686935425, 1.1922342777252197, 1.2262190580368042, 0.48976269364356995, 0.22512586414813995, 0.33211636543273926, -0.5047371983528137, 0.2883317172527313, 0.23470860719680786, 0.24038122594356537, -0.04741585999727249, -0.5512517094612122, -0.08958519995212555, 0.3993839919567108}, {-0.09156186878681183, 1.447799801826477, -0.8677529096603394, -0.2403821051120758, -0.24082186818122864, 0.09531288594007492, 1.1842302083969116, 0.7055855393409729, 1.238553762435913, 0.830436646938324, 0.7400990724563599, 0.5128685832023621, -0.1964624524116516, -0.3230336308479309, -0.12294219434261322, 0.24010124802589417, 0.3363843262195587, -0.19299542903900146, -0.1038021519780159, 0.10120601207017899, 0.30215927958488464, 0.0030945949256420135, 0.162748321890831, 0.048576682806015015, 0.3265083134174347, 0.43292054533958435, 0.1647973358631134, -0.14344830811023712}, {-0.14595773816108704, 2.036177635192871, -0.15678788721561432, -0.19012169539928436, 0.042336251586675644, 0.09402280300855637, 0.7207157611846924, 0.14010852575302124, 0.013773145154118538, 0.2021285742521286, 0.8130205273628235, 0.697592556476593, 0.19569545984268188, 1.3054842948913574, 0.7752094864845276, 0.8463451862335205, -0.43331101536750793, 0.39584746956825256, -0.026438673958182335, 0.35300928354263306, 0.6822341680526733, 0.5199337005615234, 0.4171527326107025, -0.19292718172073364, 0.30702468752861023, 0.2383618950843811, 0.49791133403778076, 0.2006896585226059}, {-0.016399526968598366, -0.8661689162254333, 0.627953827381134, 0.8040047883987427, 0.2690049409866333, -0.05720654875040054, 0.20661626756191254, 0.49369704723358154, 0.1373131424188614, -0.08826663345098495, -0.16605296730995178, 0.23632067441940308, -0.04646783322095871, 0.3226010203361511, -0.21266025304794312, 0.13406658172607422, 0.3166760206222534, 0.39453834295272827, 0.22649653255939484, -0.2949632406234741, -0.30884310603141785, 0.1574787050485611, 0.8918634653091431, -0.6566658616065979, -1.055477261543274, -0.9904500842094421, -1.3658781051635742, -1.9980671405792236}, {0.12702903151512146, -4.264755725860596, 0.1351483166217804, -0.20723043382167816, -0.2467646598815918, -0.13731075823307037, -0.2164659947156906, -0.14355270564556122, -0.14075502753257751, -0.25379636883735657, -0.17323608696460724, -0.1511029303073883, -0.17861734330654144, -0.15422824025154114, -0.07887014746665955, -0.16572877764701843, -0.1545283943414688, -0.18726830184459686, -0.1911981999874115, -0.22419621050357819, -0.14734145998954773, -0.1506907343864441, -0.26516038179397583, -0.17076921463012695, -0.20366378128528595, -0.2068306803703308, -0.2465706467628479, -0.07892344892024994}, {0.08080519735813141, 0.1585157960653305, 1.8969849348068237, -0.20419242978096008, -0.2912924289703369, -0.36874666810035706, -0.40501853823661804, -0.19646884500980377, -0.142297625541687, -0.22064056992530823, -0.3288157284259796, -0.32355132699012756, -0.5395388007164001, -0.5318061709403992, -0.3192610740661621, -0.27381959557533264, -0.34684738516807556, -0.5140829086303711, -0.373310923576355, -0.413587361574173, -0.2374996393918991, -0.21946990489959717, -0.3940057158470154, -0.18182581663131714, -0.3221309185028076, -0.45614495873451233, -0.12116502225399017, -0.17031502723693848}, {0.07794322818517685, -0.10273882746696472, 1.2109743356704712, 0.018595527857542038, 0.056782107800245285, -0.1575082391500473, -0.1836964339017868, 0.13944111764431, 0.026699164882302284, -0.12828998267650604, -0.10416686534881592, -0.855417013168335, -1.1240910291671753, -0.3680402934551239, -0.5175941586494446, -0.8113775849342346, -0.48369184136390686, 0.42436426877975464, -0.24796444177627563, -0.7017632126808167, -0.33427396416664124, 0.8904720544815063, 0.13182073831558228, 0.0840996578335762, -1.3255901336669922, 0.555604100227356, 0.44455230236053467, 0.6097607612609863}, {-0.034049827605485916, 0.5697606801986694, -0.9041339755058289, 1.4350972175598145, -0.1483038365840912, -0.06558208167552948, -0.2450496107339859, -0.5598021149635315, 1.3650588989257812, 0.09695714712142944, 0.20738567411899567, -0.04335039108991623, 0.010373556055128574, 0.9249184727668762, 0.25404757261276245, 0.1163429543375969, -0.04122623801231384, 0.07139857113361359, 1.4624335765838623, 0.3055124580860138, 0.008223910816013813, -0.06609079241752625, 0.09183429181575775, 1.1958849430084229, 0.025186588987708092, 0.029254700988531113, 0.07879947870969772, -0.4418580234050751}, {0.07264219224452972, -0.8118353486061096, 0.5850833058357239, -0.04886290058493614, -0.21201711893081665, -0.2038731724023819, -0.044785141944885254, 0.33473384380340576, -0.3806909918785095, -0.3222631812095642, -0.1784955859184265, -0.07884243875741959, -0.04943345859646797, -0.7509729266166687, -0.2586313784122467, -0.11834448575973511, -0.3176766037940979, 0.029591834172606468, -0.6633329391479492, 0.31418582797050476, 0.1703609675168991, -0.1421850472688675, -0.09780556708574295, -2.4741933345794678, -0.007773654069751501, -0.2453930675983429, -0.10803715884685516, -0.10720524936914444}, {0.04180590435862541, -0.47792956233024597, 0.5036258101463318, -2.0397746562957764, 0.2890857756137848, 0.31826984882354736, 0.06372813880443573, -0.09525591135025024, -0.5323511362075806, 0.10418450832366943, 0.19146449863910675, 0.11332566291093826, -0.07695935666561127, -0.4690433442592621, -0.19135060906410217, 0.01175900548696518, -0.009661716409027576, 0.09737563133239746, -0.14801274240016937, -0.26320526003837585, -0.08077298104763031, -0.05239444971084595, -9.216830221703276e-05, -0.06783001869916916, -0.2219526469707489, -0.1100030168890953, 0.06168339401483536, -0.01574299857020378}}; +{{0.0335812121629715, -0.21365489065647125, -0.653753936290741, -0.13572198152542114, 0.18898768723011017, 0.06430475413799286, 0.1521165519952774, -0.6386323571205139, 0.5113293528556824, 0.3224753439426422, 0.3006350100040436, 0.4426257014274597, -0.4259096086025238, 0.34491172432899475, 0.26074907183647156, 0.30206671357154846, 0.2114274799823761, -0.5099963545799255, 0.38777005672454834, 0.23917558789253235, 0.32478395104408264, 0.2528369724750519, -0.5045477747917175, 0.10504062473773956, 0.34629005193710327, 0.28095799684524536, 0.31814444065093994, -0.7089307904243469}, {0.0565570704638958, -0.4527612030506134, 0.22363899648189545, -0.4776171147823334, -0.4429882764816284, 0.09122249484062195, 0.08279165625572205, 0.29376256465911865, -0.23718500137329102, -0.5789054036140442, 0.28780052065849304, 0.6442199945449829, 0.03741508722305298, -0.220468670129776, -0.644933819770813, -0.13106265664100647, 0.5042467713356018, 0.43313512206077576, 0.5279864072799683, -0.5684875249862671, -0.8156968355178833, -0.5465362668037415, -0.5424111485481262, 0.04707803204655647, 0.2047167718410492, -0.3449491560459137, -0.26257622241973877, -0.4042203426361084}, {0.002476541558280587, -0.21414169669151306, -0.11842579394578934, 0.14450429379940033, -0.01525128073990345, -0.12563736736774445, -0.27338773012161255, 0.009645791724324226, -0.25494587421417236, -0.2797246277332306, -0.2301362156867981, -0.40248778462409973, -0.2902604341506958, 0.19436009228229523, -0.11030247807502747, 0.08137191087007523, -0.1867382973432541, -0.7496097683906555, -0.008727616630494595, 0.22033251821994781, 0.19767463207244873, 0.11307194083929062, -0.8412720561027527, 0.2657962143421173, -0.07668104767799377, 0.06086883693933487, 0.3835994601249695, -1.091362476348877}, {0.05102699622511864, -0.8378904461860657, 0.4566768705844879, -0.2630152404308319, -0.23932738602161407, -0.19857573509216309, 0.30443575978279114, -0.14038261771202087, -0.14678728580474854, -0.40179580450057983, -0.35921597480773926, -0.14929337799549103, 0.12302257865667343, 0.10777170211076736, -0.12337932735681534, -0.33727583289146423, -0.28758835792541504, 0.37838035821914673, 0.3109462559223175, 0.15170936286449432, 0.17238374054431915, -0.7253879308700562, -0.23942553997039795, 0.11120962351560593, 0.2859588861465454, 0.4778689444065094, -0.679128885269165, -0.226375013589859}, {0.03254811838269234, -0.20261096954345703, -0.07562973350286484, -0.10781332850456238, -0.10312259197235107, -0.07764437049627304, -0.04054751992225647, -0.07112596929073334, -0.06557303667068481, -0.12047363817691803, -0.062015969306230545, -0.026542047038674355, -0.01934126764535904, -0.09312712401151657, -0.03113151155412197, -0.051008112728595734, -0.05768309533596039, -0.10491270571947098, -0.0717678889632225, -0.04455398768186569, -0.02723315730690956, -0.057788874953985214, -0.0033781195525079966, -0.03603564202785492, -0.006476488430052996, -0.021566126495599747, -0.04043968394398689, 0.007654271088540554}, {-0.08095347136259079, -0.26414069533348083, -0.09814666211605072, -0.04380079358816147, -0.5849603414535522, -0.7097421288490295, -0.9047000408172607, -1.3424301147460938, -0.31041404604911804, -0.25597554445266724, -0.11997552961111069, 0.20276427268981934, 0.36256903409957886, 0.019292958080768585, -0.041115161031484604, 0.12530303001403809, 0.20739392936229706, 0.3235205411911011, -0.05591806769371033, -0.05841316655278206, 0.038499265909194946, 0.18055571615695953, 0.293590784072876, 0.16785693168640137, 0.24048064649105072, 0.07176923751831055, 0.08983936905860901, 0.22106173634529114}, {-0.017707331106066704, 0.12255413830280304, -0.6240278482437134, -0.04464518278837204, -0.1846076399087906, 0.6399872899055481, 0.12881889939308167, 0.22656285762786865, -0.1679985672235489, -0.28858682513237, 0.5312493443489075, 0.049816571176052094, -0.24046465754508972, -0.1774766743183136, -0.09163064509630203, 0.7954617142677307, -0.39598366618156433, -0.4399476945400238, 0.6123018860816956, 0.45216771960258484, 0.6593272089958191, -0.07644930481910706, -0.4521935284137726, 0.012832398526370525, 0.028779083862900734, 0.6450971961021423, 0.575737714767456, 0.6349318027496338}, {-0.03650929406285286, -0.14473311603069305, -0.5584736466407776, -0.029627997428178787, -0.1539306640625, -0.12314235419034958, 0.08387640863656998, -0.0337577685713768, -0.17351587116718292, -0.19245818257331848, -0.16416308283805847, 0.016272591426968575, 0.36373433470726013, 0.04089183360338211, 0.02371835894882679, -0.22523774206638336, -0.15100933611392975, 0.45591863989830017, -0.1123512014746666, 0.061778921633958817, -0.13473178446292877, -0.40654733777046204, 0.4156742990016937, -0.03619186207652092, 0.24843069911003113, 0.29947373270988464, 0.36726078391075134, 1.2590346336364746}, {-0.1366739124059677, 0.41514185070991516, -0.2774442732334137, -0.3785100281238556, -0.43781572580337524, 0.0857686847448349, 0.548991322517395, 0.3008037805557251, -0.710213303565979, 0.02195434831082821, 0.5724306702613831, 0.5335829854011536, 0.09624887257814407, 1.017358660697937, 0.8264562487602234, 0.4335733652114868, 0.2976129651069641, -0.07695961743593216, 0.08250663429498672, 0.12967929244041443, -0.04427557811141014, 0.24989163875579834, 0.08119788765907288, 0.05688076093792915, 0.14414691925048828, -0.15780726075172424, 0.12778723239898682, 0.17664006352424622}, {0.045846302062273026, -0.4202306270599365, 0.24253332614898682, 0.058551233261823654, 0.13127459585666656, -0.08259733766317368, -0.5951005220413208, 0.010317057371139526, 0.32319802045822144, -0.2788604497909546, -0.10889868438243866, -0.6505680084228516, 0.0621410608291626, -0.22810311615467072, -0.0803237184882164, 0.4647519290447235, -0.6627072691917419, 0.20077340304851532, 0.1278313249349594, 0.021397558972239494, -0.017719708383083344, -0.65326988697052, 0.03247045353055, -0.003151470795273781, -0.089555524289608, -0.21280834078788757, -0.18042130768299103, -0.13124220073223114}, {0.08920250833034515, -0.4041590988636017, 0.11126764863729477, -0.38825124502182007, -0.37751445174217224, 0.3841644823551178, 0.13915617763996124, -0.427076131105423, -0.42071813344955444, -0.8185845017433167, -0.6395564675331116, -0.3830700218677521, -0.34343987703323364, 0.14143605530261993, 0.2065681666135788, -0.5982153415679932, -0.2753662168979645, -0.5253153443336487, 0.1136728972196579, 0.303848534822464, -0.3599269390106201, -0.48723894357681274, 0.1170220747590065, 0.1082770973443985, 0.2027408331632614, -0.6000553369522095, -0.2399190366268158, 0.21266664564609528}, {-0.044174984097480774, 0.10084715485572815, -0.7766823768615723, 0.5814716219902039, 0.2989753484725952, -0.04704820364713669, -0.23142951726913452, 0.16222569346427917, 0.026166614145040512, 0.3819707930088043, 0.0457681305706501, -0.0551467202603817, 0.09645840525627136, -0.28990161418914795, 0.11402436345815659, 0.445557564496994, 0.3328436315059662, 0.6563848853111267, -0.22550760209560394, 0.1100253015756607, -0.29362085461616516, 0.35912737250328064, 0.07314564287662506, 0.3241541087627411, -0.04152493178844452, -0.18172766268253326, 0.3779054582118988, 0.30225080251693726}, {0.0354388952255249, -0.45912227034568787, 0.07555098086595535, -0.047884486615657806, 0.12533819675445557, 0.11261603981256485, 0.5056780576705933, -0.15080063045024872, -0.14207696914672852, -0.24237896502017975, -0.4537515342235565, -0.7382211685180664, -1.396830439567566, -0.05796787142753601, -0.0972527340054512, -0.0011085039004683495, 0.15182892978191376, 0.38325998187065125, -0.013696794398128986, -0.05116301029920578, 0.24685567617416382, 0.17722700536251068, -0.011363615281879902, 0.032823070883750916, 0.23471832275390625, 0.2214534878730774, -0.12878315150737762, 0.07269603759050369}, {0.1021164283156395, -0.979482114315033, 0.10424260795116425, 0.20152615010738373, -0.4474649131298065, -0.5927112698554993, -0.4682328701019287, -0.25608980655670166, -0.03509359434247017, -0.3745705783367157, -0.5153190493583679, -0.5731074810028076, -0.558528482913971, -0.08479820191860199, -0.38562700152397156, -0.4411310851573944, -0.5317122340202332, -0.5145424604415894, -0.046643827110528946, -0.2316707819700241, -0.3664470911026001, -0.3545966148376465, -0.313737690448761, 0.09879656881093979, -0.2625102400779724, -0.306001216173172, -0.29944929480552673, 0.03161349147558212}, {-0.03801499307155609, -0.2233135849237442, -0.10620100051164627, 0.2713835537433624, 0.21967564523220062, 0.251351535320282, 0.16949021816253662, 0.15099139511585236, 0.05300286412239075, 0.08299478143453598, 0.011512423865497112, 0.01530615333467722, 0.07382016628980637, -0.18710920214653015, 0.03905392810702324, 0.16468313336372375, 0.22495073080062866, 0.3159700930118561, -0.1615748107433319, -0.16977524757385254, -0.17270493507385254, 0.1490594446659088, 0.4793047308921814, -0.0045040980912745, -0.3750409185886383, -0.5658650994300842, -0.7609032392501831, -0.9970420598983765}, {-0.06860953569412231, 0.1561063975095749, 0.41900986433029175, -0.09340472519397736, 0.05546368286013603, -0.32329270243644714, -0.3049590587615967, -0.057696402072906494, -0.17760413885116577, -0.21533682942390442, -0.06622635573148727, -0.20747050642967224, -0.13626375794410706, -0.16855809092521667, -0.06624997407197952, 0.17109455168247223, 0.265641987323761, 0.2269686758518219, -0.31261059641838074, -0.3254770040512085, -0.17686116695404053, -0.184734046459198, -0.17058107256889343, -0.13638293743133545, -0.25341087579727173, -0.06822904199361801, -0.17498566210269928, -0.15365538001060486}, {-0.09274652600288391, 0.8195863366127014, -0.6974982619285583, 0.19567207992076874, 0.3114858567714691, 0.3193179965019226, 0.3051777482032776, 0.1686609983444214, 0.28975042700767517, 0.3609328269958496, 0.34076830744743347, 0.3451266586780548, 0.2754822373390198, 0.2944789528846741, 0.3471467196941376, 0.3111295998096466, 0.36336469650268555, 0.3138508200645447, 0.3493599593639374, 0.3804861307144165, 0.3554949462413788, 0.38007041811943054, 0.304755836725235, 0.1720620095729828, 0.3196488618850708, 0.3476446270942688, 0.2819644510746002, 0.20534354448318481}, {-0.04308394342660904, 0.4313099980354309, 0.0190417543053627, -0.36723119020462036, -0.17420481145381927, 0.5145810842514038, 0.5347347855567932, 0.6282756328582764, 1.2653520107269287, 1.1850699186325073, 0.8361583352088928, 0.4141540825366974, 0.26177582144737244, 0.06430555135011673, 0.4607594609260559, -0.0807068794965744, -0.09359037131071091, 0.09638888388872147, 0.525905191898346, 0.5729591250419617, -0.02258281223475933, -0.17060524225234985, 0.12351763993501663, 0.08509236574172974, 0.4710988402366638, 0.17080940306186676, 0.250908762216568, -0.09069673717021942}, {0.07291662693023682, 0.08596876263618469, -0.08287191390991211, 0.26005038619041443, 0.46491068601608276, 0.5783225893974304, 0.15600703656673431, -0.26880383491516113, -0.17159603536128998, 0.18245145678520203, 0.6828884482383728, -0.21175506711006165, -0.057075608521699905, -0.31850534677505493, 0.12133979052305222, 0.5726630091667175, -0.07307758182287216, -0.0253745187073946, -0.05841955170035362, -0.2049519568681717, 0.542971670627594, -0.0039001810364425182, -0.027620088309049606, -0.4046057164669037, -0.07061299681663513, 0.5127297043800354, 0.17255832254886627, -0.37250733375549316}, {-0.11166863888502121, 0.055800892412662506, -0.5167198777198792, 0.2324250191450119, 0.40913817286491394, 0.6140636801719666, 0.4707394242286682, 1.522460699081421, 0.28594499826431274, 0.3309996426105499, 0.08542972803115845, -0.28014466166496277, 0.139140322804451, 0.1942225694656372, 0.1311720907688141, 0.06602678447961807, 0.13316340744495392, 0.5902721881866455, 0.03358441963791847, -0.01826644130051136, 0.2206089198589325, 0.3234162926673889, 0.29170212149620056, 0.027043171226978302, 0.2018718421459198, -0.010219907388091087, 0.35940054059028625, 0.07707080245018005}, {0.02553723379969597, 0.461318701505661, -0.4059189260005951, 0.05942573770880699, -0.010037711821496487, -0.13757778704166412, 0.22961010038852692, 0.2251977026462555, 1.0914969444274902, 0.9033216834068298, 0.83197420835495, 0.7612583637237549, 0.05771542713046074, -0.10955284535884857, -0.004019961226731539, 0.4693775475025177, 0.07826275378465652, -0.13095584511756897, -0.2168196588754654, -0.3515476584434509, 0.7580985426902771, 0.20290978252887726, -0.16279703378677368, -0.06892823427915573, -0.20307579636573792, 0.954958975315094, -0.2317219376564026, -0.1928693652153015}, {0.062168460339307785, -0.5123471617698669, -0.263359934091568, -0.7685256600379944, 0.08967547863721848, 0.24563723802566528, 0.3980844020843506, 0.3117550015449524, -0.7312137484550476, -0.06169243901968002, 0.25126340985298157, 0.2695813477039337, 0.23361706733703613, -0.969958484172821, 0.12066813558340073, 0.15110082924365997, 0.22164055705070496, 0.14506936073303223, -0.8025405406951904, 0.26169300079345703, 0.11112350225448608, 0.29015427827835083, 0.34564951062202454, -0.9369366765022278, 0.41549447178840637, 0.2582719624042511, 0.3374422788619995, 0.3025016188621521}, {-0.1270698755979538, 0.429225891828537, -0.49225398898124695, -0.11553260684013367, -0.23649732768535614, 0.8932956457138062, -0.11381787061691284, -0.300383061170578, -0.08516164869070053, -0.04815308749675751, 0.6397905349731445, 0.05467788130044937, -0.17419259250164032, 0.05954163148999214, 0.11605441570281982, 0.46235892176628113, 0.005171304568648338, -0.3957885801792145, 0.19777722656726837, 0.7243578433990479, 0.8090712428092957, 0.8684667348861694, 1.0440218448638916, 0.435382217168808, 0.20173248648643494, -0.50189208984375, -0.127868190407753, -0.049834541976451874}, {0.0026459188666194677, 0.11711517721414566, -0.7256444692611694, -0.08485592901706696, 0.9629834890365601, 0.09173507988452911, 0.244176983833313, 0.24677251279354095, 0.15705431997776031, 0.7062681913375854, -0.5933635234832764, -0.10675647109746933, 0.04850605130195618, 0.13815787434577942, 0.4868027865886688, -0.48046332597732544, 0.09973080456256866, 0.0552331916987896, 1.0236599445343018, 1.0715246200561523, 0.8364623188972473, 0.6795467138290405, 0.1431518793106079, -0.09264400601387024, -0.24593685567378998, 0.0526106022298336, 0.5356892347335815, 0.4176342785358429}, {-0.17575381696224213, 0.9493538737297058, -0.9680318832397461, 0.344186007976532, 0.37747424840927124, 0.3827437460422516, 0.3655855357646942, 0.32791411876678467, 0.3741169273853302, 0.42540842294692993, 0.4716174900531769, 0.4630044102668762, 0.4119097888469696, 0.43781936168670654, 0.4984303414821625, 0.3960149586200714, 0.4152538776397705, 0.3874683082103729, 0.37821871042251587, 0.41086938977241516, 0.436718225479126, 0.38621312379837036, 0.3685840666294098, 0.3631429970264435, 0.3682745099067688, 0.3622629940509796, 0.41871270537376404, 0.3119860589504242}, {-0.06097084656357765, 0.3522926867008209, -0.07554367929697037, 0.31942737102508545, 0.029151281341910362, 0.15592512488365173, -0.0009292215690948069, 0.18485626578330994, 0.39177006483078003, 0.2792249321937561, 0.12014344334602356, 0.09458812326192856, 0.028401147574186325, 1.115199089050293, 0.8369911313056946, 0.602891206741333, 0.28732630610466003, -0.11038826406002045, -0.5364417433738708, -0.08979910612106323, 0.6724634766578674, 0.34956303238868713, 0.27176162600517273, -0.5280332565307617, -0.5781199932098389, 0.6316017508506775, 0.41322362422943115, 0.18675293028354645}, {0.06110076978802681, 0.20676849782466888, -0.21055933833122253, 0.14543284475803375, -0.2691429555416107, 0.23192094266414642, -0.16181010007858276, -0.07387831062078476, 0.2630201280117035, -0.1249636858701706, 0.16139020025730133, 0.12681415677070618, 0.24008934199810028, 0.5166671872138977, 0.84417724609375, 0.928178071975708, 0.5734097361564636, 0.7494409680366516, 0.45103031396865845, 0.29169872403144836, -0.17037302255630493, -0.6708592176437378, 0.1958291381597519, 0.17509706318378448, 0.2388417273759842, -0.3683401942253113, -0.46702516078948975, -0.12833642959594727}, {0.00030645611695945263, -0.19412267208099365, -0.1942126452922821, 0.8911823034286499, 0.8041935563087463, 0.6952621936798096, 0.5451593399047852, 0.4937603175640106, -0.24343731999397278, -0.1464550644159317, -0.12816737592220306, 0.024196654558181763, 0.036258477717638016, -0.1814306229352951, -0.21442382037639618, -0.11105196923017502, -0.22053563594818115, -0.24859702587127686, -0.22910651564598083, -0.2101702243089676, -0.14243045449256897, -0.2865407168865204, -0.18984046578407288, -0.07871726900339127, -0.2595853805541992, -0.24533933401107788, -0.26216810941696167, -0.16304023563861847}, {0.052463531494140625, 0.1486791968345642, -0.579024612903595, 1.088742733001709, -0.13386118412017822, -0.1609494388103485, -0.09612634778022766, -0.09550110250711441, 0.9107480645179749, -0.14887897670269012, -0.017151640728116035, 0.020924121141433716, 0.04268282279372215, 0.9172422885894775, 0.04447457566857338, -0.02752840891480446, 0.022488543763756752, -0.09672117233276367, 0.8158107995986938, 0.15294760465621948, 0.04637422040104866, 0.024195043370127678, -0.08632858097553253, 0.4717424511909485, 0.18674905598163605, 0.10150022804737091, 0.025798514485359192, -0.1546076387166977}, {0.029881251975893974, 0.49499452114105225, -0.026262039318680763, 0.00900306273251772, -0.036245543509721756, -0.11946964263916016, 0.172474667429924, 0.5267413854598999, 0.07936062663793564, -0.15437465906143188, 0.16969208419322968, 0.7578750252723694, 0.4837819039821625, 0.08440805226564407, 0.20724894106388092, 0.07721617817878723, 0.7230514883995056, 0.023518960922956467, 0.3058747947216034, 0.1142619401216507, 0.08739539235830307, 0.8077057003974915, -0.38012027740478516, 0.23245155811309814, 0.10439647734165192, -0.07647071778774261, 1.3155752420425415, -0.46643584966659546}, {0.10903043299913406, -0.004875070881098509, 0.2575789988040924, 0.14737094938755035, 0.43150651454925537, -0.5420994162559509, -0.3059577941894531, -0.2527901232242584, 0.19769372045993805, 0.38301345705986023, -0.10965324938297272, -0.21152931451797485, -0.0738074779510498, 0.1658964455127716, 0.4326992332935333, 0.4845859110355377, 0.1578446626663208, -0.10062657296657562, -0.1752672642469406, -0.37322744727134705, 0.17257146537303925, 0.2496408224105835, 0.12594257295131683, -0.37234362959861755, -0.12441913038492203, -0.026296446099877357, 0.1662571132183075, -0.0028839746955782175}, {-0.014218885451555252, -0.5738092064857483, 0.23660679161548615, -0.10611919313669205, -0.12041497230529785, -0.1564393788576126, -0.2974553406238556, -0.13557544350624084, -0.03920785337686539, 0.22239501774311066, -0.6583126187324524, -0.4981720745563507, -0.34942877292633057, 0.09956511110067368, 0.07194441556930542, -0.8891360759735107, 0.09037145227193832, 0.4524118900299072, 0.1884671002626419, 0.04436931014060974, -0.9194300770759583, 0.5126015543937683, 0.5571795105934143, 0.25728949904441833, 0.03548843413591385, -1.0185256004333496, 0.30711427330970764, 0.39558374881744385}, {-0.014499297365546227, -0.6686705946922302, -0.036153871566057205, -1.3211073875427246, -0.6752616167068481, -0.7146933078765869, -0.549763023853302, -0.11895440518856049, 0.5944733619689941, 0.46897026896476746, 0.03513138368725777, -0.41634684801101685, -0.11872824281454086, 0.40422236919403076, 0.26827922463417053, 0.0015694501344114542, -0.1268347054719925, 0.18456166982650757, 0.060881517827510834, 0.1850985437631607, 0.20143119990825653, -0.07189079374074936, 0.19972868263721466, 0.16691307723522186, 0.16700705885887146, 0.14965561032295227, -0.07053949683904648, 0.2440711408853531}, {-0.30115965008735657, 0.3020112216472626, -0.6229689121246338, 0.19976438581943512, 0.25084272027015686, 0.08908466249704361, 0.12059653550386429, 0.03533867746591568, 0.2703179121017456, 0.3352479934692383, 0.3428271412849426, 0.4156206548213959, 0.3420707583427429, 0.2064814567565918, 0.35532060265541077, 0.08173895627260208, 0.07825019955635071, 0.221553236246109, 0.1776820570230484, 0.22577251493930817, 0.22278828918933868, 0.2640128433704376, 0.180125430226326, 0.11645812541246414, 0.3808441460132599, 0.1748972088098526, 0.04822747781872749, 0.20747071504592896}, {0.004458575043827295, 0.03752393275499344, 0.1197284460067749, 0.429423987865448, 0.2881259620189667, 0.6022155284881592, -0.4153423011302948, -0.5097853541374207, 0.42615923285484314, 0.44554516673088074, 0.7217490673065186, 0.8117141127586365, 0.72388756275177, 0.015255422331392765, -0.22130870819091797, 0.13519121706485748, 0.3975375294685364, 0.1678304821252823, 0.10857963562011719, -0.3138495981693268, 0.1589823067188263, 0.2486751675605774, 0.40141168236732483, 0.018049899488687515, -0.08904679864645004, -0.08511554449796677, 0.1515214890241623, 0.4401805102825165}, {-0.15634094178676605, -0.19944559037685394, -0.16159050166606903, 0.537737250328064, 0.047764409333467484, -0.14748850464820862, 0.1200181245803833, -0.07930611819028854, 0.1614770144224167, 0.7068870067596436, 0.5102498531341553, 0.8125320076942444, 0.9490340948104858, 0.2141641080379486, 0.5533105731010437, 0.23265130817890167, 0.15047943592071533, -0.514159083366394, -0.028046829625964165, 0.6813269257545471, 0.1514519900083542, -0.1020088791847229, -0.04611760750412941, 0.22561359405517578, 0.43252548575401306, -0.050761569291353226, -0.09585573524236679, -0.15603257715702057}, {-0.08421202749013901, 0.33921104669570923, -0.41581854224205017, -0.21174439787864685, 0.4582148492336273, 0.11856566369533539, 0.10920864343643188, -0.059966351836919785, 0.3425080180168152, 0.4195125102996826, 0.02871912717819214, 0.06811660528182983, 0.0683729499578476, 0.6100324988365173, 0.2850392162799835, -0.039775870740413666, -0.11169159412384033, -0.18508493900299072, 0.730349063873291, -0.10342872887849808, -0.19325177371501923, -0.12663674354553223, -0.11998621374368668, 1.3490771055221558, -0.5284110307693481, -0.12912636995315552, -0.060148727148771286, -0.1581180840730667}, {0.13426083326339722, -0.13176080584526062, 1.2296770811080933, -0.07961347699165344, -0.3992340862751007, -0.3328780233860016, -0.3540795147418976, -0.06446079909801483, -0.3728063106536865, -0.44019535183906555, -0.4748293459415436, -0.4214479923248291, -0.37979984283447266, -0.31887421011924744, -0.46707987785339355, -0.34212198853492737, -0.4332870543003082, -0.3801964819431305, -0.3589206337928772, -0.49498450756073, -0.5273376107215881, -0.4567064344882965, -0.40370914340019226, -0.004378970246762037, -0.3736163079738617, -0.3421406149864197, -0.34401506185531616, -0.011685256846249104}, {0.08239886164665222, -0.8746750354766846, 0.520552933216095, -0.2309003621339798, -0.27933767437934875, -0.20904868841171265, -0.29178568720817566, -0.056779034435749054, -0.28577834367752075, -0.25492337346076965, -0.26360198855400085, -0.2623720169067383, -0.2106320858001709, -0.11835736036300659, -0.04690302908420563, -0.06490934640169144, -0.13744433224201202, -0.21501925587654114, -0.036219630390405655, -0.11873988062143326, -0.09084317088127136, -0.2095029354095459, -0.11422516405582428, -0.016950659453868866, -0.2354726791381836, -0.17757123708724976, -0.05872594937682152, -0.23141008615493774}, {0.030258534476161003, -0.5337088108062744, -0.06049085408449173, -0.06599123775959015, -0.016824429854750633, -0.1420319825410843, -0.03433123230934143, -0.10755813121795654, -0.011755664832890034, -0.033444661647081375, -0.10537318140268326, -0.04665432870388031, -0.0709884762763977, -0.09382390230894089, -0.05977355316281319, -0.006864430848509073, -0.07894037663936615, -0.07580714672803879, -0.12620750069618225, -0.07429014146327972, -0.11756139993667603, -0.03486189246177673, -0.07912899553775787, -0.038790758699178696, -0.06529578566551208, -0.020097605884075165, -0.06760886311531067, 0.006338239647448063}, {-0.008149570785462856, -0.2281409353017807, -0.02317221276462078, 0.10482294857501984, -0.026631563901901245, -0.02272041141986847, -0.1762792021036148, -0.06379090994596481, 0.28265300393104553, 0.1829858273267746, -0.1753186285495758, -0.16000571846961975, -0.03318013623356819, 0.28647878766059875, 0.06253796070814133, -0.3300016224384308, -0.10609311610460281, -0.14531269669532776, -0.7605944275856018, -0.4989122152328491, -0.3356994390487671, -0.05982646346092224, 0.06342680007219315, -0.04135109484195709, 0.32415950298309326, 0.2208917886018753, -0.07768300175666809, -0.15703800320625305}, {0.03806011378765106, -0.6677188873291016, 0.15192484855651855, -0.16433456540107727, -0.34537896513938904, -0.020495647564530373, -0.03346096724271774, 0.223424032330513, -0.02972494252026081, -0.3487086594104767, -0.0456627681851387, -0.11218554526567459, -0.00014366689720191061, 0.4491022527217865, -0.5417236089706421, -0.6263294816017151, -0.6973318457603455, -0.9182674288749695, -0.2974551320075989, -0.7037410736083984, 0.0874515250325203, 0.14197714626789093, 0.4558337330818176, -0.5843172669410706, -0.5606727004051208, 0.45348820090293884, 0.44328850507736206, 0.4209005534648895}, {-0.08474959433078766, 0.15526627004146576, -0.7985652089118958, 0.21260187029838562, 0.3656609356403351, 0.12335719168186188, 0.060457415878772736, 0.24970696866512299, 0.4984481930732727, 0.3631579279899597, 0.26680564880371094, 0.5937404036521912, 0.2675668001174927, 0.26715323328971863, -0.2635864317417145, -0.6670373678207397, 0.5595815181732178, 0.3275291323661804, 0.3265022933483124, -0.0923314318060875, 0.2361195683479309, 0.8254050016403198, 0.5882598757743835, 0.8333842158317566, 0.4826344847679138, 0.6576237082481384, 0.013852320611476898, -0.13133659958839417}, {-0.03767941892147064, -0.16735343635082245, 0.07242633402347565, 0.09715986251831055, -0.08629732578992844, -0.12105050683021545, 0.19429436326026917, -1.189113974571228, -0.0438414141535759, -0.13045798242092133, 0.17313389480113983, 0.222298264503479, -0.6784869432449341, 0.044389013200998306, -0.04566064849495888, 0.1745270937681198, -0.18878957629203796, -0.68072509765625, -0.17901289463043213, -0.13348782062530518, -0.280407577753067, -0.5236465930938721, -0.09434037655591965, 0.3562553822994232, -0.14296357333660126, -0.17816492915153503, -0.262240469455719, 0.2708267867565155}, {-0.14643076062202454, 0.3134414553642273, -0.016158653423190117, 0.4832289218902588, 0.35327669978141785, 0.033485930413007736, 1.404250144958496, -0.4109203517436981, 0.3232615888118744, 0.03948039561510086, 0.14370359480381012, 1.0806249380111694, -0.43028610944747925, 0.19681444764137268, 0.3559668958187103, 0.24551646411418915, 0.7668668031692505, 0.26227831840515137, 0.24610893428325653, 0.03931723162531853, 0.1685093492269516, 0.42881014943122864, 0.605613648891449, 0.07715323567390442, 0.2259686291217804, 0.12414932996034622, 0.28258103132247925, 0.6711070537567139}, {-0.03460083529353142, 0.015175103209912777, -0.0020290936809033155, -0.2801230251789093, -0.049781594425439835, -0.08237257599830627, -0.24321754276752472, -0.30726316571235657, -0.1131473034620285, -0.016173556447029114, -0.0010477738687768579, -0.20699340105056763, -0.2045988142490387, -0.10566984117031097, -0.0597367063164711, -0.1446806639432907, -0.008996298536658287, -0.1636381596326828, -0.34909534454345703, -0.10394063591957092, 0.07907130569219589, 0.0491563156247139, 0.07572714239358902, 0.8712359666824341, 0.8652707934379578, 0.8136559128761292, 0.7329977750778198, 0.4842419922351837}, {0.028292212635278702, -0.6930311322212219, 0.4168195426464081, -0.722553014755249, 0.6128503084182739, 0.37802034616470337, -0.12130801379680634, -0.16137754917144775, -0.4547799825668335, 0.019849296659231186, -0.07699695229530334, 0.02751479111611843, 0.11456470936536789, -0.46225056052207947, -0.4128100574016571, -0.21820463240146637, -0.05070912092924118, -0.012455608695745468, 0.17457029223442078, -0.6548964381217957, 0.2514891028404236, 0.09665688127279282, -0.023784032091498375, 0.34345829486846924, -1.0899158716201782, 0.057933658361434937, -0.10579057782888412, -0.09446477890014648}, {0.06298044323921204, -0.5140762329101562, 0.10901061445474625, 0.25055184960365295, 0.16310572624206543, 0.1660183221101761, -0.2003139704465866, -0.25939759612083435, -0.759786069393158, -0.5441654324531555, -0.433865487575531, -0.2903525233268738, 0.20317135751247406, -0.05961161479353905, 0.1883774697780609, 0.07006954401731491, -0.348635733127594, 0.00569637306034565, -0.12705902755260468, 0.06386853754520416, 0.30274978280067444, -0.06455851346254349, -0.16498570144176483, -0.2735350728034973, -0.05759710818529129, -0.09640154242515564, -0.2553178668022156, 0.1108042374253273}, {0.16303423047065735, -0.840851902961731, 0.3045694828033447, 0.5177968144416809, 0.010460598394274712, -0.0009595230803824961, -0.164739727973938, -0.2865234613418579, -0.1834029257297516, 0.4267294108867645, 0.0837775319814682, -0.5739225745201111, -0.17942845821380615, 0.06667495518922806, 0.46038922667503357, 0.14962272346019745, -0.34685906767845154, 0.23869825899600983, -0.28814902901649475, -0.7657412886619568, -0.866352379322052, -0.9862637519836426, -0.18093055486679077, -0.2750402092933655, -0.2612379789352417, 0.14520415663719177, 0.41632893681526184, -0.3018798232078552}, {-0.15189743041992188, 0.24816209077835083, -0.39726874232292175, 0.10362628102302551, 0.22738219797611237, 0.13067540526390076, 0.29548943042755127, 0.37722209095954895, 0.17870138585567474, 0.2407064139842987, 0.19497083127498627, 0.3211122453212738, -0.09292492270469666, -0.12265130877494812, 0.4053817391395569, -0.11827366054058075, 0.45297837257385254, 0.11928819864988327, 0.9772109389305115, 0.5449104905128479, 0.39806750416755676, 0.4030953049659729, 0.16402702033519745, -0.14901259541511536, -0.15305542945861816, 0.16489744186401367, 0.21413367986679077, 0.5390959978103638}, {-0.054573457688093185, -0.22824183106422424, -0.3203968405723572, -0.15810002386569977, 0.5835301876068115, 0.38719215989112854, 0.4236435294151306, 0.640129566192627, -0.14881178736686707, 0.47540283203125, 0.09412529319524765, 0.06462755799293518, -0.6389226317405701, -0.10056259483098984, 0.5633905529975891, 0.08276329189538956, -0.1411363184452057, -0.009574373252689838, -0.03582749515771866, 0.6443657279014587, -0.017103971913456917, -0.17268119752407074, 0.06117372587323189, -0.04281193017959595, 0.7488794922828674, -0.06866982579231262, 0.06887611001729965, -0.11549514532089233}, {0.01342778280377388, -0.4836217761039734, -0.11072295904159546, 0.6476761698722839, 0.5931163430213928, -0.7808675169944763, -0.35797253251075745, -0.2272079437971115, 0.7021985054016113, -0.022765103727579117, -0.8641810417175293, -0.20821577310562134, -0.1716800034046173, -0.2285567671060562, -0.4907127618789673, -0.4427620768547058, 0.20067904889583588, 0.24365925788879395, -0.2677304446697235, -0.33728840947151184, 0.0702209398150444, 0.09022712707519531, 0.1330493539571762, -0.3614550530910492, -0.30246731638908386, 0.012839858420193195, 0.3226088583469391, 0.06072837859392166}, {-0.040193911641836166, -0.6861724853515625, -0.4070025682449341, 0.1424286812543869, 0.21161821484565735, 0.36073726415634155, 0.3628085255622864, -0.0990212932229042, 0.42990466952323914, 0.5575714707374573, 0.37092170119285583, 0.2522738575935364, 0.1157609149813652, 0.47637075185775757, 0.48690155148506165, 0.30947044491767883, 0.2960883677005768, 0.07852909713983536, 0.3973768353462219, 0.13431915640830994, 0.36592432856559753, 0.17452998459339142, 0.13116753101348877, -0.42777925729751587, -0.37024176120758057, -0.43283072113990784, -0.5338147878646851, -0.4905080199241638}, {-0.12332254648208618, 0.23759916424751282, -0.2621895968914032, 0.03406616672873497, 0.5511227250099182, -0.12509968876838684, -0.4177529215812683, -0.47927144169807434, 0.14296410977840424, 0.4820209741592407, 0.22033001482486725, -0.13066789507865906, -0.7484548091888428, 0.23563754558563232, 0.2622942626476288, 0.582843542098999, 0.7955005764961243, 0.9946928024291992, 0.14746436476707458, 0.043333325535058975, -0.07848695665597916, 0.10714565217494965, 0.12493138015270233, 0.1611987203359604, 0.04742865636944771, -0.26901474595069885, -0.10293031483888626, 0.010696852579712868}, {0.04099375382065773, -3.2305996417999268, 0.2543967366218567, -0.059577129781246185, -0.14682938158512115, -0.0733993723988533, -0.07150989025831223, -0.08204008638858795, -0.12635663151741028, -0.10393626242876053, -0.022796161472797394, 0.007641270756721497, -0.08665978163480759, -0.01694418303668499, -0.0025942830834537745, -0.03163212165236473, -0.022262264043092728, -0.07357636839151382, -0.07581206411123276, -0.06286846846342087, -0.1153038740158081, -0.04352688044309616, -0.08158870041370392, -0.08570341020822525, -0.06179278343915939, -0.11247510462999344, 0.0021329170558601618, -0.029320182278752327}, {0.029462160542607307, -0.5271976590156555, 0.18926401436328888, 0.02871791645884514, -0.23120182752609253, -0.786915123462677, 0.6471821665763855, 0.4379161298274994, 0.20970848202705383, -0.06591341644525528, -0.7760671973228455, 0.38167643547058105, 0.5764249563217163, 0.014545980840921402, 0.17091333866119385, -0.9253398776054382, -0.09902273863554001, -0.05899110808968544, 0.4204649329185486, 0.21064306795597076, -0.5640349984169006, -0.24353162944316864, -0.18500371277332306, -0.026613807305693626, -0.06437907367944717, -0.34146401286125183, -0.35460934042930603, -0.2743520736694336}, {-0.052965063601732254, -0.5605072379112244, 0.07962799817323685, -0.02648513950407505, -0.2291896939277649, -0.16507042944431305, -0.016116635873913765, 0.4122294485569, 0.023346038535237312, 0.06569206714630127, -0.0031419098377227783, 0.18163825571537018, 0.08935528993606567, -0.09544392675161362, -0.3773246705532074, 0.0589076466858387, 0.40520086884498596, -0.07905229926109314, -0.49348345398902893, -0.35177019238471985, -0.5805748105049133, 0.30384382605552673, 0.058458756655454636, -0.26937973499298096, -0.2887529134750366, -0.48755502700805664, 0.22864623367786407, 0.08268418908119202}, {-0.1134001687169075, -0.1595868170261383, 0.14256395399570465, 0.029054423794150352, 0.15920008718967438, 0.11821631342172623, 0.41081133484840393, 0.22583164274692535, 0.4875009059906006, -0.017819786444306374, 0.18353310227394104, 0.18164801597595215, 0.5451951622962952, 0.04068929702043533, 0.5024164319038391, 0.4954160749912262, 0.15857921540737152, 0.07034330070018768, 0.10076071321964264, -0.22763016819953918, 0.3141815662384033, 0.10078883916139603, 0.3922852873802185, 0.34453365206718445, 0.168269544839859, 0.42013704776763916, 0.07419819384813309, -0.14518938958644867}, {-0.06957618147134781, -0.06440338492393494, -0.7259829640388489, 0.5161219835281372, 0.09093577414751053, 0.4290890097618103, 0.4202098250389099, -0.027972804382443428, 0.545386791229248, 0.44505423307418823, -0.12706060707569122, 0.10054849833250046, 0.056948449462652206, 0.08831918239593506, 0.8375925421714783, 0.025092219933867455, 0.21887224912643433, 0.2599436938762665, -0.6995351910591125, 0.9659162163734436, 0.2467847764492035, 0.5137833952903748, 0.21108582615852356, -0.11285984516143799, 1.2240996360778809, -0.16404935717582703, 0.22046460211277008, 0.013526036404073238}, {-0.004826321732252836, -0.005929495673626661, 0.07865772396326065, -0.35655465722084045, -0.260633260011673, -0.37299594283103943, -0.3571874499320984, 0.6748940348625183, -0.013674028217792511, -0.27069777250289917, -0.28626859188079834, -0.02211541309952736, 0.8759161233901978, -0.2193540334701538, -0.2950937747955322, -0.1518949717283249, -0.01741132326424122, 0.7278527617454529, -0.10758645832538605, -0.14286479353904724, -0.12058365345001221, 0.05432174354791641, 0.7359171509742737, -0.20074452459812164, -0.24474677443504333, -0.20014965534210205, -0.2710004448890686, 0.5048877596855164}, {0.06318517029285431, -0.06626387685537338, 0.09102978557348251, 0.2806074619293213, -0.5871695280075073, 0.01448263693600893, -0.17774152755737305, -0.015175321139395237, 0.26823174953460693, -0.5144285559654236, -0.10162042826414108, -0.11051122844219208, -0.056919533759355545, -0.0963352620601654, -0.292245477437973, 0.07747644931077957, 0.049891501665115356, 0.04416292905807495, -0.10346058011054993, -0.27070391178131104, 0.16639839112758636, 0.13697180151939392, -0.03080388717353344, -0.3958549499511719, -0.08085988461971283, -0.15026159584522247, -0.2458583563566208, -0.1183728277683258}, {-0.031412992626428604, -0.5603559017181396, 0.23181116580963135, 0.13550354540348053, 0.1384330689907074, 0.466655433177948, 0.013126186095178127, -0.1315859854221344, 0.19236598908901215, 0.18724070489406586, 0.3651496469974518, -0.2081764191389084, -0.21705558896064758, -0.8947001695632935, -0.8844435811042786, -0.9548132419586182, -0.8363487720489502, -0.43193918466567993, 0.14401763677597046, 0.17948108911514282, 0.22730839252471924, -0.05247826129198074, -0.04454374313354492, 0.22061742842197418, 0.2703307569026947, 0.2895837426185608, -0.10765346139669418, -0.1715518683195114}, {-0.08773751556873322, 0.1905992329120636, -0.1878463476896286, -0.06142798811197281, -0.07157573848962784, -0.15859191119670868, 0.2888740599155426, 0.29501354694366455, -0.18804210424423218, 0.03719957917928696, 0.04348141327500343, 0.43497395515441895, 0.3348860740661621, 0.046619195491075516, -0.012931774370372295, 0.43330755829811096, 0.783429741859436, 0.7513718605041504, 0.42782992124557495, 0.4602666199207306, 0.8619009256362915, 0.21070736646652222, -0.6946675181388855, 0.36241528391838074, 0.5762568712234497, 0.41478705406188965, -0.7064434289932251, -0.7981423139572144}, {0.0158368032425642, -0.46186450123786926, -0.04968561232089996, 0.08248921483755112, 0.09503590315580368, -0.02358037419617176, -0.31207606196403503, 0.5838796496391296, -0.015739191323518753, 0.14295169711112976, 0.06756915897130966, -0.23699864745140076, -0.031251370906829834, 0.044411782175302505, 0.07595864683389664, -0.06131885573267937, -0.2911010682582855, -0.03894522413611412, 0.26580068469047546, 0.10324547439813614, -0.22770865261554718, -0.43839356303215027, -0.10662800073623657, -1.1684633493423462, -0.6824188828468323, -0.5405550003051758, -0.3048187494277954, 0.12504103779792786}}; const float dense1_biases[DENSE_NUM] = -{-1.7320090532302856, -1.6262712478637695, -0.7219676971435547, -1.6883859634399414, -1.355366587638855, -1.4961345195770264, -1.6774159669876099, -1.9836738109588623, -1.8204424381256104, -1.6768863201141357, -1.5860340595245361, 0.4256221652030945, -1.9900296926498413, -2.060673952102661, -1.487168788909912, -1.653613567352295, -0.49618664383888245, -1.0318562984466553, -1.2956619262695312, -2.130068778991699, -2.124798536300659, -1.6073938608169556, -1.4884546995162964, -1.7450541257858276, -1.508810043334961, -1.4361188411712646, -1.4151768684387207, -1.6134501695632935, -1.9257988929748535, -1.8976153135299683, -1.6919738054275513, -1.7137935161590576, -0.9487504363059998, -0.7779767513275146, -2.0696449279785156, -0.4453120529651642, -0.8720207214355469, -2.00007963180542, -1.6582602262496948, -0.6423311233520508, -1.3238186836242676, -1.8345296382904053, -1.4237842559814453, -0.6334408521652222, -1.3415791988372803, -1.5188286304473877, -1.5377963781356812, -1.4456733465194702, -1.7134979963302612, -1.762224793434143, -1.760365605354309, -1.7037813663482666, -1.612302541732788, -1.613434910774231, -1.8743529319763184, -1.6047550439834595, -1.9443285465240479, -1.041770577430725, 0.48393940925598145, -1.487646460533142, -2.1693429946899414, -1.207763671875, -0.9444307684898376, -1.1276359558105469}; +{-0.1444406658411026, -0.9969395995140076, -0.6437257528305054, -0.5090100169181824, -0.4562266170978546, -0.7947681546211243, -0.66095370054245, -0.0757993534207344, -0.6305758357048035, -0.6522586345672607, -0.6137698292732239, 0.06795938313007355, -0.5988752841949463, -0.022649021819233894, -0.559893012046814, -0.34122252464294434, 0.21291229128837585, -0.9544443488121033, -0.5839042663574219, -0.3325875997543335, -0.8768086433410645, -0.3371303975582123, -0.804802417755127, -0.7296857833862305, -0.24707458913326263, -0.9100144505500793, -0.7247095704078674, -0.6324146389961243, -0.42117181420326233, -1.2145949602127075, -0.7118635177612305, -0.9112556576728821, -0.21369697153568268, -0.10298735648393631, -0.8274878263473511, -0.6126794219017029, -0.7786099314689636, -0.5083696246147156, -0.38434338569641113, -0.468181848526001, -0.5246707201004028, -0.6266580820083618, -0.3932459354400635, -0.6446056365966797, -0.8690927028656006, -0.7806448936462402, -0.7514670491218567, -0.4992736577987671, -0.4725331962108612, -0.8359085321426392, -0.3995131254196167, -0.701408326625824, 0.13735836744308472, -0.7701425552368164, 0.37747254967689514, -0.8496323227882385, -0.41388845443725586, -0.3626680374145508, -0.4750637412071228, -1.0076007843017578, -0.4247843325138092, -0.8280375599861145, -0.8584521412849426, -0.49181294441223145}; const float output_weights[2][DENSE_NUM] = -{{-0.1246807649731636, -0.08505872637033463, -0.0652783066034317, 0.1350107192993164, 0.1698562055826187, 0.400063693523407, 0.17860691249370575, -0.1349184215068817, 0.20356398820877075, 0.16311302781105042, -0.036207523196935654, 0.7803400754928589, -0.13074463605880737, -0.06796154379844666, 0.20493201911449432, 0.14702282845973969, -0.11247620731592178, 0.22241809964179993, 0.1635751873254776, -0.08345462381839752, -0.2028568834066391, 0.12081773579120636, -0.1835630089044571, 0.1626814305782318, 0.16333818435668945, -0.27365756034851074, 0.13540410995483398, -0.13346917927265167, -0.1633249968290329, 0.17652902007102966, 0.1970495879650116, -0.0996168851852417, 0.1257164627313614, -0.02319495752453804, 0.1254752278327942, 0.004205659963190556, -0.11657992005348206, -0.13747099041938782, -0.12851183116436005, -0.13266359269618988, 0.15070892870426178, 0.18036587536334991, -0.120721235871315, -0.07944180071353912, -0.07511389255523682, -0.14644883573055267, 0.11276227235794067, 0.1335425227880478, -0.12701821327209473, 0.20198681950569153, -0.06599707156419754, -0.14891819655895233, 0.2015286684036255, 0.17373384535312653, 0.1385129988193512, 0.1480085849761963, 0.20751388370990753, -0.127104252576828, -0.5856947302818298, -0.26959943771362305, -0.10330907255411148, 0.14857497811317444, -0.168384850025177, -0.23837287724018097}, {0.05711914226412773, 0.1704198718070984, 0.07292810082435608, -0.1523439884185791, -0.20949530601501465, -0.33654606342315674, -0.23295333981513977, 0.09389320015907288, -0.23792678117752075, -0.17215877771377563, 0.06109726428985596, -0.7076484560966492, 0.0808710902929306, 0.06764110177755356, -0.08750396966934204, -0.12129006534814835, 0.08196759223937988, -0.22181545197963715, -0.10018306225538254, 0.09599480032920837, 0.2410762906074524, -0.16045424342155457, 0.12080714106559753, -0.14531971514225006, -0.14728260040283203, 0.389263778924942, -0.14980417490005493, 0.14908818900585175, 0.1427009552717209, -0.18783621490001678, -0.17802631855010986, 0.10279617458581924, -0.1660611927509308, 0.03492075577378273, -0.0730394646525383, 0.011791321448981762, 0.09671367704868317, 0.10834173858165741, 0.12392941862344742, 0.08413772284984589, -0.18994614481925964, -0.20133660733699799, 0.07802799344062805, 0.06276662647724152, 0.06052928790450096, 0.12486152350902557, -0.10323746502399445, -0.1355014443397522, 0.16498015820980072, -0.2137404978275299, 0.10234697163105011, 0.12195070087909698, -0.15739789605140686, -0.13428226113319397, -0.0960799902677536, -0.1424444168806076, -0.18782544136047363, 0.14121107757091522, 0.6669175624847412, 0.2753967046737671, 0.09798707813024521, -0.16682972013950348, 0.1646665632724762, 0.24278126657009125}}; +{{-0.10164133459329605, -0.06545510143041611, -0.12559004127979279, -0.09770263731479645, 0.020511239767074585, -0.11956804245710373, 0.0725698173046112, 0.09884587675333023, 0.03334106504917145, -0.07531746476888657, -0.04404358193278313, 0.04667624458670616, -0.10733920335769653, 0.11603111028671265, -0.09832630306482315, -0.029710080474615097, 0.6112914681434631, 0.09875980764627457, 0.04528747498989105, 0.04975724592804909, 0.05296019837260246, -0.1494731307029724, 0.06372635811567307, 0.05117323249578476, -0.4960876405239105, 0.08172430098056793, 0.09049712121486664, 0.16494503617286682, 0.12463495880365372, 0.10889994353055954, 0.0901939794421196, -0.07425925135612488, -0.09327994287014008, 0.07225991785526276, 0.0995996817946434, 0.1002214103937149, 0.13605892658233643, -0.2738678455352783, 0.07213583588600159, 0.031051557511091232, -0.09413432329893112, -0.05657240375876427, 0.023954149335622787, -0.11132869869470596, 0.0918613076210022, 0.1731780767440796, -0.048148252069950104, -0.08594620227813721, -0.07079077512025833, 0.028347637504339218, 0.04007003828883171, -0.08521876484155655, -0.13736766576766968, 0.0973486453294754, -0.3953056037425995, -0.09303829818964005, 0.0926792323589325, 0.08662958443164825, 0.07239469885826111, 0.12995171546936035, -0.08624651283025742, -0.13703757524490356, 0.1074426919221878, -0.05400789529085159}, {0.09475231915712357, 0.10763916373252869, 0.10490848124027252, 0.051702577620744705, -0.025973767042160034, 0.1243276372551918, -0.09184729307889938, -0.09110323339700699, -0.10927686840295792, 0.07648954540491104, 0.08314546942710876, -0.054432936012744904, 0.11420167982578278, -0.14501862227916718, 0.07449985295534134, 0.04114171117544174, -0.5540419816970825, -0.11702275276184082, -0.057106584310531616, -0.11389349400997162, -0.04799086973071098, 0.11528362333774567, -0.10561501979827881, -0.06099977344274521, 0.5406088829040527, -0.07843243330717087, -0.07121624052524567, -0.15534670650959015, -0.10739737004041672, -0.10599866509437561, -0.03090781159698963, 0.1024080142378807, 0.11164399981498718, -0.10347762703895569, -0.09762325882911682, -0.044070787727832794, -0.1382112205028534, 0.2635824978351593, -0.013381495140492916, -0.017522230744361877, 0.09075458347797394, 0.08058229833841324, -0.03840004280209541, 0.08596818149089813, -0.10802465677261353, -0.17988164722919464, 0.08185803890228271, 0.09076226502656937, 0.042497776448726654, -0.0991385206580162, -0.03188726678490639, 0.0789727196097374, 0.12080144137144089, -0.12002957612276077, 0.3941708207130432, 0.07739747315645218, -0.04954647645354271, -0.10626203566789627, -0.054530855268239975, -0.19077910482883453, 0.07939524203538895, 0.10724455863237381, -0.09315766394138336, 0.07806982845067978}}; const float output_bias[2] = -{0.5831990242004395, 0.4281694293022156}; +{0.3762611150741577, 0.6172211170196533}; diff --git a/include/weights.h b/include/weights.h index c4e0c3c..7a37ed9 100644 --- a/include/weights.h +++ b/include/weights.h @@ -15,10 +15,9 @@ along with ct. If not, see . */ -#define INP_NUM 3 + 5*5 +#define INP_NUM 3 + 5 * 5 #define DENSE_NUM 64 - extern const float dense1_weights[DENSE_NUM][INP_NUM]; extern const float dense1_biases[DENSE_NUM]; extern const float output_weights[2][DENSE_NUM]; diff --git a/include/xorshift64.h b/include/xorshift64.h index b9ba97a..c3542c6 100644 --- a/include/xorshift64.h +++ b/include/xorshift64.h @@ -22,13 +22,14 @@ extern uint64_t xors; -#define XORSHIFT64 { \ - xors ^= xors >> 12; \ - xors ^= xors << 25; \ - xors ^= xors >> 27; \ +#define XORSHIFT64 \ + { \ + xors ^= xors >> 12; \ + xors ^= xors << 25; \ + xors ^= xors >> 27; \ } -#define RANDOM64 (xors*0x2545F4914F6CDD1D) +#define RANDOM64 (xors * 0x2545F4914F6CDD1D) #define RANDOM32 ((uint32_t)RANDOM64) #endif diff --git a/include/zobrist.c b/include/zobrist.c index 1fdd8a9..d8d1856 100644 --- a/include/zobrist.c +++ b/include/zobrist.c @@ -27,13 +27,14 @@ static uint64_t *zobrist; // Exported method implementations // =================================================================== -int zobrist_init(void) { - if (zobrist != NULL) return EXIT_FAILURE; +int zobrist_init(const uint8_t board_size) { + if (zobrist != NULL) + return EXIT_FAILURE; - zobrist = malloc(sizeof(uint64_t)*board_size*board_size*(15*2*3)); + zobrist = malloc(sizeof(uint64_t) * board_size * board_size * (15 * 2 * 3)); // TODO: trap errno - for (int k=0; k>= 1) - hash ^= zobrist[l*(15*2*3)+h*2*3+(c&1)*3+s]; + for (uint8_t l = 0; l < state->board_size * state->board_size; l++) { + colour_stack_t c = state->colours[l]; + const uint8_t count = COUNT_AT(state, l); + enum STONE_VARIANT s = STONE_AT(state, l); + for (uint8_t h = 0; h < count; h++, c >>= 1) + hash ^= zobrist[l * (15 * 2 * 3) + h * 2 * 3 + (c & 1) * 3 + s]; } return hash; } diff --git a/include/zobrist.h b/include/zobrist.h index be93910..6a1de4f 100644 --- a/include/zobrist.h +++ b/include/zobrist.h @@ -15,12 +15,12 @@ along with ct. If not, see . */ -#include -#include #include +#include +#include void zobrist_free(void); -int zobrist_init(void); +int zobrist_init(const uint8_t board_size); -uint64_t zobrist_compute(void); +uint64_t zobrist_compute(tak_state_p state); -- cgit v1.2.3