diff options
Diffstat (limited to 'include/tps.c')
| -rw-r--r-- | include/tps.c | 351 |
1 files changed, 201 insertions, 150 deletions
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<count; k++, s >>=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, "\"]"); } |
