X-Git-Url: https://plomlompom.com/repos/?p=plomrogue;a=blobdiff_plain;f=libplomrogue.c;h=eb108c4eb966b0fcca3834052df3efa68f444366;hp=c6f572416339559cfdfbb35ee7a25a2d64377092;hb=b745286c163a4a50789e0620eeac0555a940954c;hpb=555930c81055c3eab2fb3daa55cf3343faec5fd2 diff --git a/libplomrogue.c b/libplomrogue.c index c6f5724..eb108c4 100644 --- a/libplomrogue.c +++ b/libplomrogue.c @@ -1,4 +1,20 @@ -#include /* uint16_t, uint32_t */ +#include /* uint8_t, uint16_t, uint32_t, INT8_MIN, INT8_MAX */ + + + +/* Coordinate for maps of max. 256x256 cells. */ +struct yx_uint8 +{ + uint8_t y; + uint8_t x; +}; + +/* Storage for map_length, set by set_maplength(). */ +static uint16_t maplength = 0; +extern void set_maplength(uint16_t maplength_input) +{ + maplength = maplength_input; +} @@ -7,6 +23,115 @@ static uint32_t seed = 0; +/* Helper to mv_yx_in_dir_legal(). Move "yx" into hex direction "d". */ +static void mv_yx_in_dir(char d, struct yx_uint8 * yx) +{ + if (d == 'e') + { + yx->x = yx->x + (yx->y % 2); + yx->y--; + } + else if (d == 'd') + { + yx->x++; + } + else if (d == 'c') + { + yx->x = yx->x + (yx->y % 2); + yx->y++; + } + else if (d == 'x') + { + yx->x = yx->x - !(yx->y % 2); + yx->y++; + } + else if (d == 's') + { + yx->x--; + } + else if (d == 'w') + { + yx->x = yx->x - !(yx->y % 2); + yx->y--; + } +} + + + +/* Move "yx" into hex direction "dir". Available hex directions are: 'e' + * (north-east), 'd' (east), 'c' (south-east), 'x' (south-west), 's' (west), 'w' + * (north-west). Returns 1 if the move was legal, 0 if not, and -1 when internal + * wrapping limits were exceeded. + * + * A move is legal if "yx" ends up within the the map and the original wrap + * space. The latter is left to a neighbor wrap space if "yx" moves beyond the + * minimal (0) or maximal (UINT8_MAX) column or row of possible map space – in + * which case "yx".y or "yx".x will snap to the respective opposite side. The + * current wrapping state is kept between successive calls until a "yx" of NULL + * is passed, in which case the function does nothing but zero the wrap state. + * Successive wrapping may move "yx" several wrap spaces into either direction, + * or return it into the original wrap space. + */ +static int8_t mv_yx_in_dir_legal(char dir, struct yx_uint8 * yx) +{ + static int8_t wrap_west_east = 0; + static int8_t wrap_north_south = 0; + if (!yx) + { + wrap_west_east = wrap_north_south = 0; + return 0; + } + if ( INT8_MIN == wrap_west_east || INT8_MIN == wrap_north_south + || INT8_MAX == wrap_west_east || INT8_MAX == wrap_north_south) + { + return -1; + } + struct yx_uint8 original = *yx; + mv_yx_in_dir(dir, yx); + if (('e' == dir || 'd' == dir || 'c' == dir) && yx->x < original.x) + { + wrap_west_east++; + } + else if (('x' == dir || 's' == dir || 'w' == dir) && yx->x > original.x) + { + wrap_west_east--; + } + if (('w' == dir || 'e' == dir) && yx->y > original.y) + { + wrap_north_south--; + } + else if (('x' == dir || 'c' == dir) && yx->y < original.y) + { + wrap_north_south++; + } + if ( !wrap_west_east && !wrap_north_south + && yx->x < maplength && yx->y < maplength) + { + return 1; + } + return 0; +} + + + +/* Wrapper around mv_yx_in_dir_legal() that stores the new coordinate in the + * globals res_y, res_x. + */ +uint8_t res_y = 0; +uint8_t res_x = 0; +extern uint8_t mv_yx_in_dir_legal_wrap(char dir, uint8_t y, uint8_t x) +{ + struct yx_uint8 yx; + yx.y = y; + yx.x = x; + uint8_t result = mv_yx_in_dir_legal(dir, &yx); + res_y = yx.y; + res_x = yx.x; + return result; +} + + + /* With set_seed set, set seed global to seed_input. In any case, return it. */ extern uint32_t seed_rrand(uint8_t set_seed, uint32_t seed_input) {