From b745286c163a4a50789e0620eeac0555a940954c Mon Sep 17 00:00:00 2001 From: Christian Heller <c.heller@plomlompom.de> Date: Thu, 5 Mar 2015 14:44:26 +0100 Subject: [PATCH] Server/py: Add map navigation infrastructure / API to libplomrogue.c. --- libplomrogue.c | 127 +++++++++++++++++++++++++++++++++++++++++++- plomrogue-server.py | 18 ++++--- 2 files changed, 136 insertions(+), 9 deletions(-) diff --git a/libplomrogue.c b/libplomrogue.c index c6f5724..eb108c4 100644 --- a/libplomrogue.c +++ b/libplomrogue.c @@ -1,4 +1,20 @@ -#include <stdint.h> /* uint16_t, uint32_t */ +#include <stdint.h> /* 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) { diff --git a/plomrogue-server.py b/plomrogue-server.py index 1751544..3234c4a 100755 --- a/plomrogue-server.py +++ b/plomrogue-server.py @@ -32,6 +32,10 @@ def prep_library(): libpr.seed_rrand.restype = ctypes.c_uint32 libpr.rrand.argtypes = [] libpr.rrand.restype = ctypes.c_uint16 + libpr.set_maplength.argtypes = [ctypes.c_uint16] + libpr.mv_yx_in_dir_legal_wrap.argtypes = [ctypes.c_char, ctypes.c_uint8, + ctypes.c_uint8] + libpr.mv_yx_in_dir_legal_wrap.restype = ctypes.c_uint8 return libpr @@ -740,8 +744,6 @@ def play_commander(action, args=False): if None != val: world_db["Things"][0]["T_ARGUMENT"] = val set_command() - else: - print("Ignoring: Argument must be integer >= 0 <=255.") def set_command_and_argument_movestring(str_arg): dirs = {"east": "d", "south-east": "c", "south-west": "x", @@ -765,8 +767,6 @@ def command_seedrandomness(seed_string): val = integer_test(seed_string, 0, 4294967295) if None != val: rand.seed = val - else: - print("Ignoring: Value must be integer >= 0, <= 4294967295.") def command_seedmap(seed_string): @@ -810,7 +810,6 @@ def command_makeworld(seed_string): val = integer_test(seed_string, 0, 4294967295) if None == val: - print("Ignoring: Value must be integer >= 0, <= 4294967295.") return rand.seed = val world_db["SEED_MAP"] = val @@ -851,9 +850,12 @@ def command_makeworld(seed_string): def command_maplength(maplength_string): """Redefine map length. Invalidate map, therefore lose all things on it.""" - set_world_inactive() - world_db["Things"] = {} - setter(None, "MAP_LENGTH", 1, 256)(maplength_string) + val = integer_test(val_string, 1, 256) + if None != val: + world_db["MAP_LENGTH"] = val + set_world_inactive() + world_db["Things"] = {} + libpr.set_maplength = val def command_worldactive(worldactive_string): -- 2.30.2