X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=src%2Fserver%2Fai.c;h=1a296ce18ffc7038bed075d77da719be39d817ef;hb=109dc4e8a5d9f09541ef2dcb84bd6b6ac2e2fb00;hp=d8a9d2e402e51c42321d1637fe2fde05103cafa4;hpb=f36dc55279993c54c1dcd1d318bf5ee5cc8c9735;p=plomrogue diff --git a/src/server/ai.c b/src/server/ai.c index d8a9d2e..1a296ce 100644 --- a/src/server/ai.c +++ b/src/server/ai.c @@ -10,6 +10,7 @@ #include /* free() */ #include "../common/try_malloc.h" /* try_malloc() */ #include "hardcoded_strings.h" /* s */ +#include "rrand.h" /* rrand() */ #include "thing_actions.h" /* get_thing_action_id_by_name() */ #include "things.h" /* Thing, ThingType, ThingInMemory, get_thing_type() */ #include "world.h" /* world */ @@ -56,6 +57,9 @@ static uint8_t score_map_filter_search(uint8_t filter, uint16_t * score_map, static void init_score_map(char filter, uint16_t * score_map, uint32_t map_size, struct Thing * t_eye); +/* From "targets" select random "cmp" match as directory by order in "dirs". */ +static char rand_target_dir(char * dirs, uint16_t cmp, uint16_t * targets); + /* Helper to get_dir_to_nearest_target(). */ static char get_dir_from_neighbors(char filter, struct Thing * t_eye, uint16_t * score_map); @@ -63,14 +67,14 @@ static char get_dir_from_neighbors(char filter, struct Thing * t_eye, /* Set (if possible) as "t_eye"'s command a move to the path to the path-wise * nearest target that is not "t_eye" and fits criteria set by "filter". On * success, return !0, else 0. Values for "filter": - * "a": thing in FOV is animate, but of a type that is not "t_eye"'s, and - * starts out weaker than it is; build path as avoiding things of "t_eye"'s - * type + * "a": thing in FOV is below a certain distance, animate, but of a type that is + * not "t_eye"'s, and starts out weaker than it is; build path as avoiding + * things of "t_eye"'s type * "f": neighbor cell (not inhabited by any animate thing) further away from * animate thing not further than x steps away and in FOV and of a type * that is not "t_eye"'s, and starts out stronger or as strong as "t_eye" * is currently; or (cornered), if no such flight cell, but thing of above - * criteria is in neighbor cell, that cell + * criteria is too near, a cell closer to it, or, if less near, just wait * "c": thing in memorized map is consumable * "s": memory map cell with greatest-reachable degree of unexploredness */ @@ -287,6 +291,24 @@ static void init_score_map(char filter, uint16_t * score_map, uint32_t map_size, } +static char rand_target_dir(char * dirs, uint16_t cmp, uint16_t * targets) +{ + char candidates[N_DIRS]; + uint8_t n_candidates = 0; + uint8_t i; + for (i = 0; i < N_DIRS; i++) + { + if (cmp == targets[i]) + { + candidates[n_candidates] = dirs[i]; + n_candidates++; + } + } + return n_candidates ? candidates[rrand() % n_candidates] : 0; +} + + + static char get_dir_from_neighbors(char filter, struct Thing * t_eye, uint16_t * score_map) { @@ -295,7 +317,8 @@ static char get_dir_from_neighbors(char filter, struct Thing * t_eye, char * dirs = "edcxsw"; /* get_neighbor_scores()'s clockwise dir order. */ uint16_t neighbors[N_DIRS]; get_neighbor_scores(score_map, pos_i, UINT16_MAX, neighbors, 'f'==filter); - uint16_t minmax_neighbor = 'f' == filter ? 0 : UINT16_MAX-1; + uint16_t minmax_start = 'f' == filter ? 0 : UINT16_MAX-1; + uint16_t minmax_neighbor = minmax_start; uint8_t i; for (i = 0; i < N_DIRS; i++) { @@ -304,27 +327,34 @@ static char get_dir_from_neighbors(char filter, struct Thing * t_eye, || ('f' != filter && minmax_neighbor > neighbors[i])) { minmax_neighbor = neighbors[i]; - dir_to_nearest_target = dirs[i]; } } + if (minmax_neighbor != minmax_start) + { + dir_to_nearest_target = rand_target_dir(dirs,minmax_neighbor,neighbors); + } if ('f' == filter) { - if (!dir_to_nearest_target && 1 == score_map[pos_i]) + if (!dir_to_nearest_target) { - get_neighbor_scores(score_map, pos_i, UINT16_MAX, neighbors, 0); - for (i = 0; i < N_DIRS; i++) + if (1 == score_map[pos_i]) /* Attack if cornered too closely. */ { - if (!neighbors[i]) - { - dir_to_nearest_target = dirs[i]; - break; - } + dir_to_nearest_target = rand_target_dir(dirs, 0, neighbors); + } + else if (3 >= score_map[pos_i]) /* If less closely, just wait. */ + { + t_eye->command = get_thing_action_id_by_name(s[S_CMD_WAIT]); + return 1; } } - else if (dir_to_nearest_target && minmax_neighbor > 3) - { - dir_to_nearest_target = 0; - } + else if (dir_to_nearest_target && 3 < score_map[pos_i]) /* Don't flee */ + { /* enemy of */ + dir_to_nearest_target = 0; /* a certain */ + } /* distance. */ + } + else if ('a' == filter && 10 <= score_map[pos_i]) + { + dir_to_nearest_target = 0; } return dir_to_nearest_target; }