From: Christian Heller Date: Sun, 17 Aug 2014 01:58:06 +0000 (+0200) Subject: Server: Add inanimate things to map memory, integrate into AI searches. X-Git-Tag: tce~657 X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/decks/%7B%7Bdb.prefix%7D%7D/static/bar%20baz.html?a=commitdiff_plain;h=3dedf6344c941891491773d1cc5d647aa664b218;p=plomrogue Server: Add inanimate things to map memory, integrate into AI searches. --- diff --git a/SERVER_COMMANDS b/SERVER_COMMANDS index 50ac853..8af195f 100644 --- a/SERVER_COMMANDS +++ b/SERVER_COMMANDS @@ -164,6 +164,10 @@ T_MEMMAP [0 to 255] [string] Set part of selected thing's memory of the game map to string argument: the line of the argument's number. +T_MEMTHING [0 to 255] [0 to 255] [0 to 255] +Add to selected thing's memory of things on map thing of ID of first argument, +y position of second argument and x position of third argument. + TT_ID [-32768 to 32767] Select thing type to manipulate by argument as ID. If argument is <0 or <255, change it to the lowest unused thing type ID. If thing type of ID does not exist diff --git a/src/server/ai.c b/src/server/ai.c index b6c8cbc..cdefca8 100644 --- a/src/server/ai.c +++ b/src/server/ai.c @@ -7,7 +7,7 @@ #include "../common/try_malloc.h" /* try_malloc() */ #include "hardcoded_strings.h" /* s */ #include "thing_actions.h" /* get_thing_action_id_by_name() */ -#include "things.h" /* Thing, ThingType */ +#include "things.h" /* Thing, ThingType, ThingInMemory */ #include "world.h" /* world */ @@ -39,18 +39,18 @@ static void init_score_map(char filter, uint16_t * score_map, uint32_t map_size, struct Thing * t_eye); /* Set (if possible) as "t_eye"'s command a move to the path to the path-wise - * nearest thing that is in "t_eye"'s field of view and not "t_eye" and fits - * criteria set by "filter". On success, return 1, else 0. Values for "filter": - * "e": thing searched for animate, but not of "t_eye"'s thing type; build - * path as avoiding things of "t_eye"'s type - * "c": thing searched for is consumable. + * nearest thing that is not "t_eye" and fits criteria set by "filter". On + * success, return 1, else 0. Values for "filter": + * "e": thing in FOV is animate, but not of "t_eye"'s thing type; build path as + * avoiding things of "t_eye"'s type + * "c": thing in memorized map is consumable. */ static uint8_t get_dir_to_nearest_thing(struct Thing * t_eye, char filter); -/* Return 1 if any thing not "t_eye" is in its FOV and fulfills some criterion - * defined by "filter", else 0. Values for "filter": - * "e": thing searched for is animate, but not of "t_eye"'s thing type - * "c": thing searched for is consumable +/* Return 1 if any thing not "t_eye" is known and fulfills some criteria defined + * by "filter", else 0. Values for "filter": + * "e": thing in FOV is animate, but not of "t_eye"'s thing type + * "c": thing in memorized map is consumable */ static uint8_t seeing_thing(struct Thing * t_eye, char filter); @@ -150,16 +150,13 @@ static void init_score_map(char filter, uint16_t * score_map, uint32_t map_size, score_map[i] = UINT16_MAX-1; } } - struct Thing * t = world.things; - for (; t != NULL; t = t->next) + if ('e' == filter) { - if (t==t_eye || 'H'==t_eye->fov_map[t->pos.y*world.map.length+t->pos.x]) - { - continue; - } - if ('e' == filter) + struct Thing * t = world.things; + for (; t; t = t->next) { - if (!t->lifepoints) + if ( t==t_eye || !t->lifepoints + || 'H' == t_eye->fov_map[t->pos.y*world.map.length + t->pos.x]) { continue; } @@ -168,16 +165,25 @@ static void init_score_map(char filter, uint16_t * score_map, uint32_t map_size, score_map[t->pos.y * world.map.length + t->pos.x] = UINT16_MAX; continue; } + score_map[t->pos.y * world.map.length + t->pos.x] = 0; } - else if ('c' == filter) + } + else if ('c' == filter) + { + struct ThingInMemory * tm = t_eye->t_mem; + for (; tm; tm = tm->next) { - struct ThingType * tt = get_thing_type(t->type); + if (' ' == t_eye->mem_map[tm->pos.y * world.map.length + tm->pos.x]) + { + continue; + } + struct ThingType * tt = get_thing_type(tm->type); if (!tt->consumable) { continue; } + score_map[tm->pos.y * world.map.length + tm->pos.x] = 0; } - score_map[t->pos.y * world.map.length + t->pos.x] = 0; } } @@ -221,25 +227,32 @@ static uint8_t get_dir_to_nearest_thing(struct Thing * t_eye, char filter) static uint8_t seeing_thing(struct Thing * t_eye, char filter) { - if (t_eye->fov_map) + if (t_eye->fov_map && 'e' == filter) { struct Thing * t = world.things; - for (; t != NULL; t = t->next) + for (; t; t = t->next) { if ( t != t_eye && 'v' == t_eye->fov_map[t->pos.y*world.map.length + t->pos.x]) { - if ('e' == filter && t->lifepoints && t->type != t_eye->type) + if (t->lifepoints && t->type != t_eye->type) { return 1; } - else if ('c' == filter) + } + } + } + else if (t_eye->mem_map && 'c' == filter) + { + struct ThingInMemory * tm = t_eye->t_mem; + for (; tm; tm = tm->next) + { + if (' ' != t_eye->mem_map[tm->pos.y * world.map.length + tm->pos.x]) + { + struct ThingType * tt = get_thing_type(tm->type); + if (tt->consumable) { - struct ThingType * tt = get_thing_type(t->type); - if (tt->consumable) - { - return 1; - } + return 1; } } } diff --git a/src/server/field_of_view.c b/src/server/field_of_view.c index ae8aa9c..4b1ac00 100644 --- a/src/server/field_of_view.c +++ b/src/server/field_of_view.c @@ -6,7 +6,7 @@ #include /* memset() */ #include "../common/rexit.h" /* exit_trouble() */ #include "../common/try_malloc.h" /* try_malloc() */ -#include "things.h" /* Thing */ +#include "things.h" /* Thing, ThingInMemory, add_thing_to_memory_map() */ #include "yx_uint8.h" /* yx_uint8 */ #include "world.h" /* world */ @@ -84,7 +84,9 @@ static void eval_position(uint16_t dist, uint16_t hex_i, char * fov_map, struct yx_uint8 * test_pos, struct shadow_angle ** shadows); -/* Update "t"'s .mem_map memory with what's in its current field of view. */ +/* Update "t"'s .mem_map memory with what's in its current FOV, remove from its + * .t_mem all memorized things in FOV and add inanimiate things in FOV to it. + */ static void update_map_memory(struct Thing * t, uint32_t map_size); @@ -354,19 +356,49 @@ static void eval_position(uint16_t dist, uint16_t hex_i, char * fov_map, -static void update_map_memory(struct Thing * t, uint32_t map_size) +static void update_map_memory(struct Thing * t_eye, uint32_t map_size) { - if (!t->mem_map) + if (!t_eye->mem_map) { - t->mem_map = try_malloc(map_size, __func__); - memset(t->mem_map, ' ', map_size); + t_eye->mem_map = try_malloc(map_size, __func__); + memset(t_eye->mem_map, ' ', map_size); } uint32_t i; for (i = 0; i < map_size; i++) { - if (' ' == t->mem_map[i] && t->fov_map[i] == 'v') + if (' ' == t_eye->mem_map[i] && t_eye->fov_map[i] == 'v') + { + t_eye->mem_map[i] = world.map.cells[i]; + } + } + struct ThingInMemory * tm = t_eye->t_mem; + struct ThingInMemory * tm_prev = NULL; + struct ThingInMemory * tm_next = NULL; + for (; tm != NULL; tm = tm_next) + { + tm_next = tm->next; + if ('v' == t_eye->fov_map[tm->pos.y * world.map.length + tm->pos.x]) + { + if (tm_prev) + { + tm_prev->next = tm->next; + } + else + { + t_eye->t_mem = tm->next; + } + free(tm); + continue; + } + tm_prev = tm; + } + struct Thing * t = world.things; + for (; t != NULL; t = t->next) + { + if ( !t->lifepoints + && 'v' == t_eye->fov_map[t->pos.y * world.map.length + t->pos.x]) { - t->mem_map[i] = world.map.cells[i]; + add_thing_to_memory_map(t_eye, t->type, t->pos.y, t->pos.x); } } } diff --git a/src/server/god_commands.c b/src/server/god_commands.c index 755acd5..09aeece 100644 --- a/src/server/god_commands.c +++ b/src/server/god_commands.c @@ -18,7 +18,7 @@ * actor_use(), actor_pickup(), actor_drop() */ #include "things.h" /* Thing, ThingType, add_thing(), get_thing(), own_thing(), - * free_things() + * free_things(), add_thing_to_memory_map(),get_thing_type() */ #include "world.h" /* world */ @@ -475,3 +475,34 @@ extern uint8_t parse_god_command_2arg(char * tok0, char * tok1, char * tok2) } return 1; } + + + +extern uint8_t parse_god_command_3arg(char * tok0, char * tok1, char * tok2, + char * tok3) +{ + if (!t && !strcmp(tok0, s[S_CMD_T_MEMTHING])) + { + err_line(1, "No thing defined to manipulate yet."); + return 1; + } + if (!strcmp(tok0, s[S_CMD_T_MEMTHING])) + { + uint8_t id = atoi(tok1); + uint8_t y = atoi(tok2); + uint8_t x = atoi(tok3); + if ( parsetest_int(tok1, '8') || !get_thing_type(id) + || parsetest_int(tok2, '8') || y >= world.map.length + || parsetest_int(tok3, '8') || x >= world.map.length) + { + err_line(1, "Illegal value for thing type or position."); + return 1; + } + add_thing_to_memory_map(t, id, y, x); + } + else + { + return 0; + } + return 1; +} diff --git a/src/server/god_commands.h b/src/server/god_commands.h index d9b1558..7899b20 100644 --- a/src/server/god_commands.h +++ b/src/server/god_commands.h @@ -14,6 +14,8 @@ /* Parse/apply god command "tok0" with argument "tok1", "tok2" etc. . */ extern uint8_t parse_god_command_1arg(char * tok0, char * tok1); extern uint8_t parse_god_command_2arg(char * tok0, char * tok1, char * tok2); +extern uint8_t parse_god_command_3arg(char * tok0, char * tok1, char * tok2, + char * tok3); diff --git a/src/server/hardcoded_strings.c b/src/server/hardcoded_strings.c index 82f7a3e..64bcc59 100644 --- a/src/server/hardcoded_strings.c +++ b/src/server/hardcoded_strings.c @@ -4,7 +4,7 @@ -char * s[40]; +char * s[41]; @@ -37,6 +37,7 @@ extern void init_strings() s[S_CMD_T_HP] = "T_LIFEPOINTS"; s[S_CMD_T_CARRIES] = "T_CARRIES"; s[S_CMD_T_MEMMAP] = "T_MEMMAP"; + s[S_CMD_T_MEMTHING] = "T_MEMTHINGß"; s[S_CMD_AI] = "ai"; s[S_CMD_WAIT] = "wait"; s[S_CMD_MOVE] = "move"; diff --git a/src/server/hardcoded_strings.h b/src/server/hardcoded_strings.h index ebfa079..7ee0ec9 100644 --- a/src/server/hardcoded_strings.h +++ b/src/server/hardcoded_strings.h @@ -37,6 +37,7 @@ enum string_num S_CMD_T_HP, S_CMD_T_CARRIES, S_CMD_T_MEMMAP, + S_CMD_T_MEMTHING, S_CMD_AI, S_CMD_WAIT, S_CMD_MOVE, @@ -54,7 +55,7 @@ enum string_num extern void init_strings(); -extern char * s[40]; +extern char * s[41]; diff --git a/src/server/io.c b/src/server/io.c index 0f65cea..8f8f738 100644 --- a/src/server/io.c +++ b/src/server/io.c @@ -18,8 +18,8 @@ #include "../common/try_malloc.h" /* try_malloc() */ #include "cleanup.h" /* set_cleanup_flag() */ #include "hardcoded_strings.h" /* s */ -#include "things.h" /* Thing, ThingType, ThingAction, get_thing_type(), - * get_player() +#include "things.h" /* Thing, ThingType, ThingInMemory, ThingAction, + * get_thing_type(), get_player() */ #include "world.h" /* global world */ @@ -67,7 +67,7 @@ static char * build_visible_map(struct Thing * player); /* Write to "file" game map as visible to "player" right now, as drawn by * build_visible_map(), and thereafter game map as memorized by player in its - * .mem_map. Write one row per \n-delimited line. + * .mem_map and .t_mem. Write one row per \n-delimited line. */ static void write_map(struct Thing * player, FILE * file); @@ -165,6 +165,17 @@ static void write_thing(FILE * file, struct Thing * t) try_fputc('\n', file, __func__); } free(mem_map_copy); + struct ThingInMemory * tm = t->t_mem; + for (; tm; tm = tm->next) + { + write_key_space(file, s[S_CMD_T_MEMTHING]); + write_value(file, tm->type); + try_fputc(' ', file, __func__); + write_value(file, tm->pos.y); + try_fputc(' ', file, __func__); + write_value(file, tm->pos.x); + try_fputc('\n', file, __func__); + } } try_fputc('\n', file, __func__); } @@ -354,14 +365,36 @@ static void write_map(struct Thing * player, FILE * file) try_fputc('\n', file, __func__); } free(visible_map); + uint32_t map_size = world.map.length * world.map.length; + char * mem_map = try_malloc(map_size, __func__); + memcpy(mem_map, player->mem_map, map_size); + uint8_t i; + struct ThingInMemory * tm; + for (i = 0; i < 2; i++) + { + for (tm = player->t_mem; tm != NULL; tm = tm->next) + { + if (' ' != player->mem_map[tm->pos.y*world.map.length+tm->pos.x]) + { + struct ThingType * tt = get_thing_type(tm->type); + if ( (0 == i && !tt->consumable) + || (1 == i && tt->consumable)) + { + char c = tt->char_on_map; + mem_map[tm->pos.y * world.map.length + tm->pos.x] = c; + } + } + } + } for (y = 0; y < world.map.length; y++) { for (x = 0; x < world.map.length; x++) { - try_fputc(player->mem_map[y*world.map.length+x], file, __func__); + try_fputc(mem_map[y * world.map.length + x], file, __func__); } try_fputc('\n', file, __func__); } + free(mem_map); } diff --git a/src/server/run.c b/src/server/run.c index 8c1297d..906bed2 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -20,7 +20,7 @@ #include "../common/try_malloc.h" /* try_malloc() */ #include "ai.h" /* ai() */ #include "cleanup.h" /* unset_cleanup_flag() */ -#include "god_commands.h" /* parse_god_command_1arg(),parse_god_command_2arg()*/ +#include "god_commands.h" /* parse_god_command_(1|2|3)arg() */ #include "hardcoded_strings.h" /* s */ #include "io.h" /* io_round(), save_world() */ #include "things.h" /* Thing, get_thing_action_id_by_name(), get_player() */ @@ -165,6 +165,14 @@ static uint8_t parse_command(char * tok0) { return 1; } + else + { + char * tok3 = token_from_line(NULL); + if (tok2 && parse_god_command_3arg(tok0, tok1, tok2, tok3)) + { + return 1; + } + } } } return 0; diff --git a/src/server/things.c b/src/server/things.c index e73a09a..7d0f62d 100644 --- a/src/server/things.c +++ b/src/server/things.c @@ -28,6 +28,9 @@ struct NextAndId +/* Free ThingsInMemory chain starting at "tm". */ +static void free_things_in_memory(struct ThingInMemory * tm); + /* To linked list of NextAndId structs (or rather structs whose start region is * compatible to it) starting at "start", add newly allocated element of * "n_size" and an ID that is either "id" or, if "id" is <= UINT8_MAX and >= @@ -40,6 +43,18 @@ static struct NextAndId * add_to_struct_list(size_t n_size, uint8_t start_id, +static void free_things_in_memory(struct ThingInMemory * tm) +{ + if (NULL == tm) + { + return; + } + free_things_in_memory(tm->next); + free(tm); +} + + + static struct NextAndId * add_to_struct_list(size_t n_size, uint8_t start_id, int16_t id, uint8_t struct_id, struct NextAndId ** start) @@ -121,6 +136,19 @@ extern struct Thing * add_thing(int16_t id, uint8_t type, uint8_t y, uint8_t x) +extern void add_thing_to_memory_map(struct Thing * t, uint8_t type, + uint8_t y, uint8_t x) +{ + struct ThingInMemory * tm=try_malloc(sizeof(struct ThingInMemory),__func__); + tm->type = type; + tm->pos.y = y; + tm->pos.x = x; + tm->next = t->t_mem; + t->t_mem = tm; +} + + + extern void free_thing_actions(struct ThingAction * ta) { if (NULL == ta) @@ -157,6 +185,7 @@ extern void free_things(struct Thing * t) free_things(t->next); free(t->fov_map); free(t->mem_map); + free_things_in_memory(t->t_mem); free(t); if (t == world.things) /* So add_things()' NULL-delimited thing */ { /* iteration loop does not iterate over */ diff --git a/src/server/things.h b/src/server/things.h index ea37a81..365e308 100644 --- a/src/server/things.h +++ b/src/server/things.h @@ -15,16 +15,24 @@ struct Thing { struct Thing * next; - uint8_t id; /* individual thing's unique identifier */ - struct Thing * owns; /* chain of things owned / in inventory */ - struct yx_uint8 pos; /* coordinate on map */ - char * fov_map; /* thing's FOV map; 'v':visible, 'H':hidden */ - char * mem_map; /* map knowledge of thing by FOV and memory */ - uint8_t type; /* ID of appropriate thing definition */ - uint8_t lifepoints; /* 0: thing is inanimate; >0: hitpoints */ - uint8_t command; /* thing's current action; 0 if none */ - uint8_t arg; /* optional field for .command argument */ - uint8_t progress; /* turns already passed to realize .command */ + uint8_t id; /* individual thing's unique identifier */ + struct Thing * owns; /* chain of things owned / in inventory */ + struct ThingInMemory * t_mem; /* chain of things remembered */ + struct yx_uint8 pos; /* coordinate on map */ + char * fov_map; /* thing's FOV map; 'v':visible, 'H':hidden */ + char * mem_map; /* map knowledge of thing by FOV and memory */ + uint8_t type; /* ID of appropriate thing definition */ + uint8_t lifepoints; /* 0: thing is inanimate; >0: hitpoints */ + uint8_t command; /* thing's current action; 0 if none */ + uint8_t arg; /* optional field for .command argument */ + uint8_t progress; /* turns already passed to realize .command */ +}; + +struct ThingInMemory +{ + struct ThingInMemory * next; + struct yx_uint8 pos; /* position on memorized */ + uint8_t type; /* thing type identifier */ }; struct ThingType @@ -67,7 +75,11 @@ extern struct ThingType * add_thing_type(int16_t id); */ extern struct Thing * add_thing(int16_t id, uint8_t type, uint8_t y, uint8_t x); -/* Free ThingAction/ThingType/Thing * chain starting at "ta"/"tt"/"t". */ +/* Add to thing memory of "t" thing of type id "type" and position "y"/"x". */ +extern void add_thing_to_memory_map(struct Thing * t, uint8_t type, + uint8_t y, uint8_t x); + +/* Free ThingAction/ThingType/Thing chain starting at "ta"/"tt"/"t". */ extern void free_thing_actions(struct ThingAction * ta); extern void free_thing_types(struct ThingType * tt); extern void free_things(struct Thing * t);