diff options
Diffstat (limited to 'include/ptn.c')
| -rw-r--r-- | include/ptn.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/include/ptn.c b/include/ptn.c new file mode 100644 index 0000000..58648b9 --- /dev/null +++ b/include/ptn.c @@ -0,0 +1,86 @@ +#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; +} |
