X-Git-Url: https://plomlompom.com/repos/berlin_corona.txt?a=blobdiff_plain;f=src%2Fserver%2Fai.c;h=d536f14e2f629c5f131d9a3b1dc6e2142152206e;hb=22ab49928288775acfd1224eeb8b8014158efd92;hp=b761c6bbbc8039fd2ba75908228f3b006ed9bc8a;hpb=a0e8861d1f1cce921350803bf0499941cb708dec;p=plomrogue diff --git a/src/server/ai.c b/src/server/ai.c index b761c6b..d536f14 100644 --- a/src/server/ai.c +++ b/src/server/ai.c @@ -2,14 +2,13 @@ #include "ai.h" #include /* NULL */ -#include /* uint8_t, uint16_t, uint32_t, UINT16_MAX */ +#include /* uint8_t, uint16_t, uint32_t, int16_t, UINT16_MAX */ #include /* free() */ #include "../common/try_malloc.h" /* try_malloc() */ -#include "field_of_view.h" /* VISIBLE */ #include "hardcoded_strings.h" /* s */ #include "thing_actions.h" /* get_thing_action_id_by_name() */ -#include "things.h" /* struct Thing */ -#include "world.h" /* global world */ +#include "things.h" /* Thing, ThingType */ +#include "world.h" /* world */ @@ -27,13 +26,11 @@ static void get_neighbor_scores(uint16_t * score_map, uint16_t pos_i, /* Iterate over scored cells in "score_map" of world.map's geometry. Compare * each cell's score against the score of its immediate neighbors in N_DIRS - * directions. If it's neighbors are low enough that the result would be lower - * than the current value, re-set it to 1 point higher than its lowest-scored + * directions. If any neighbor's score is at least two points lower than the + * current cell's score, re-set it to 1 point higher than its lowest-scored * neighbor. Repeat this whole process until all cells have settled on their - * final score. Ignore cells whose position in "score_map" fits cells of - * unreachable terrain in world.map.cells or whose score is greater than - * "max_score". Expect "max_score" to be the maximum score for cells, marking - * them as unreachable. + * final score. Ignore cells whose score is greater than "max_score". Expect + * "max_score" to be the maximum score for cells, marking them as unreachable. */ static void dijkstra_map(uint16_t * score_map, uint16_t max_score); @@ -42,6 +39,15 @@ static void dijkstra_map(uint16_t * score_map, uint16_t max_score); */ static char get_dir_to_nearest_enemy(struct Thing * thing_origin); +/* Return 1 if any animate thing not "t_origin" is in its FOV, else 0. */ +static uint8_t seeing_enemies(struct Thing * t_origin); + +/* Return slot ID of strongest consumable in "t_owner"'s inventory, else -1. */ +static int16_t get_inventory_slot_to_consume(struct Thing * t_owner); + +/* Return 1 if "t_standing" is standing on a consumable, else 0. */ +static uint8_t standing_on_consumable(struct Thing * t_standing); + static void get_neighbor_scores(uint16_t * score_map, uint16_t pos_i, @@ -133,7 +139,7 @@ static char get_dir_to_nearest_enemy(struct Thing * t_origin) for (i = 0; i < map_size; i++) { score_map[i] = UINT16_MAX; - if (t_origin->fov_map[i] & VISIBLE && world.map.cells[i] == '.') + if ('.' == t_origin->mem_map[i]) { score_map[i] = max_score; } @@ -141,7 +147,8 @@ static char get_dir_to_nearest_enemy(struct Thing * t_origin) struct Thing * t = world.things; for (; t != NULL; t = t->next) { - if (!t->lifepoints || t == t_origin) + if ( !t->lifepoints || t == t_origin + || 'H' == t_origin->fov_map[t->pos.y * world.map.length + t->pos.x]) { continue; } @@ -175,13 +182,86 @@ static char get_dir_to_nearest_enemy(struct Thing * t_origin) +static uint8_t seeing_enemies(struct Thing * t_origin) +{ + struct Thing * t = world.things; + for (; t != NULL; t = t->next) + { + if ( t->lifepoints + && t != t_origin + && 'v' == t_origin->fov_map[t->pos.y * world.map.length + t->pos.x]) + { + return 1; + } + } + return 0; +} + + + +static int16_t get_inventory_slot_to_consume(struct Thing * t_owner) +{ + uint8_t compare_consumability = 0; + int16_t selection = -1; + struct Thing * t = t_owner->owns;; + uint8_t i; + for (i = 0; t != NULL; t = t->next, i++) + { + struct ThingType * tt = get_thing_type(t->type); + if (tt->consumable > compare_consumability) + { + compare_consumability = tt->consumable; + selection = i; + } + } + return selection; +} + + + +static uint8_t standing_on_consumable(struct Thing * t_standing) +{ + struct Thing * t = world.things; + for (; t != NULL; t = t->next) + { + if ( t_standing != t + && t->pos.y == t_standing->pos.y && t->pos.x == t_standing->pos.x) + { + struct ThingType * tt = get_thing_type(t->type); + if (tt->consumable) + { + return 1; + } + } + } + return 0; +} + + + extern void ai(struct Thing * t) { t->command = get_thing_action_id_by_name(s[S_CMD_WAIT]); - char sel = t->fov_map ? get_dir_to_nearest_enemy(t) : 0;/* t->fov_map may */ - if (0 != sel) /* be absent due */ - { /* to god command.*/ - t->command = get_thing_action_id_by_name(s[S_CMD_MOVE]); - t->arg = sel; + if (seeing_enemies(t)) + { + char sel = t->fov_map ? get_dir_to_nearest_enemy(t) : 0; + if (0 != sel) + { + t->command = get_thing_action_id_by_name(s[S_CMD_MOVE]); + t->arg = sel; + } + } + else + { + int16_t sel = get_inventory_slot_to_consume(t); + if (-1 != sel) + { + t->command = get_thing_action_id_by_name(s[S_CMD_USE]); + t->arg = (uint8_t) sel; + } + else if (standing_on_consumable(t)) + { + t->command = get_thing_action_id_by_name(s[S_CMD_PICKUP]); + } } }