#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 *location, enum STONE_VARIANT *stone) { ASSERT_NONEMPTY; *stone = STONE_FLAT; switch (*ptn) { case 'C' : { ptn++; *stone = STONE_CAPSTONE; break; }; case 'S' : { ptn++; *stone = STONE_STANDING; break; }; case 'F' : { ptn++; break; }; } ASSERT_MORE; if ( (*ptn < 'a') || (*ptn > '`' + board_size) ) return PTN_INVALID; *location = *ptn - 'a'; ptn++; ASSERT_MORE; if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; *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 *location, enum MOVE_DIRECTION *direction, uint8_t *steps, uint8_t drops[5]) { 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; *location = *ptn - 'a'; ptn++; ASSERT_MORE; if ( (*ptn < '1') || (*ptn > board_size + '0') ) return PTN_INVALID; *location += board_size * (*ptn - '1'); ptn++; ASSERT_MORE; switch (*ptn) { case '+': { *direction = M_UP; break; } case '-': { *direction = M_DOWN; break; } case '<': { *direction = M_LEFT; break; } case '>': { *direction = M_RIGHT; break; } default: return PTN_INVALID; } ptn++; ASSERT_MORE; *steps = 0; uint8_t total = 0; while (*ptn) { if ( (*ptn < '1') || (*ptn > '0' + board_size) ) { return PTN_INVALID; } // TODO: Correct? if ( (*steps >= board_size) && *ptn) return PTN_INVALID; drops[*steps] = *ptn - '0'; total += drops[*steps]; *steps += 1; ptn++; } if ( (picked_up > 0) && (total != picked_up) ) return PTN_INVALID; return PTN_VALID; }