#include "ptn.h" #define ASSERT_NONEMPTY { if (ptn == 0 || *ptn == 0) return PTN_INVALID; } #define ASSERT_MORE { if (*ptn == 0) return PTN_INVALID; } enum PTN_PARSE_RESULT parse_place(const uint8_t board_size, char *ptn, uint8_t *out_location, enum STONE_VARIANT *out_stone) { if (board_size < 5 || board_size > 6) return PTN_INVALID; 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; }; } ASSERT_MORE; if ( (*ptn < 'a') || (*ptn > '`' + board_size) ) return PTN_INVALID; *out_location = *ptn - 'a'; ptn++; ASSERT_MORE; if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; *out_location += board_size * (*ptn - '1'); if (*(++ptn) > 0) return PTN_INVALID; return PTN_VALID; } enum PTN_PARSE_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]) { if (board_size < 5 || board_size > 6) return PTN_INVALID; ASSERT_NONEMPTY; uint8_t picked_up = 0; if ( (*ptn >= '1') && (*ptn <= '0' + board_size)) { picked_up = *ptn - '0'; ptn++; ASSERT_MORE; } if ( (*ptn < 'a') || (*ptn > '`' + board_size) ) return PTN_INVALID; *out_location = *ptn - 'a'; ptn++; ASSERT_MORE; if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; *out_location += board_size * (*ptn - '1'); ptn++; ASSERT_MORE; 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; } ptn++; // Handle the case '' as // '11' for convenience if (*ptn == 0) { if (picked_up == 0) { *out_steps = 1; out_drops[0] = 1; } else { return PTN_INVALID; } } *out_steps = 0; uint8_t total = 0; while (*ptn) { if ( (*ptn < '1') || (*ptn > '0' + board_size) ) { return PTN_INVALID; } if ( (*out_steps + 1 >= board_size) && *ptn) return PTN_INVALID; out_drops[*out_steps] = *ptn - '0'; total += out_drops[*out_steps]; *out_steps += 1; ptn++; } if ( (picked_up > 0) && (total != picked_up) ) return PTN_INVALID; return PTN_VALID; }