-/* src/server/ai.c */
+/* src/server/ai.c
+ *
+ * This file is part of PlomRogue. PlomRogue is licensed under the GPL version 3
+ * or any later version. For details on its copyright, license, and warranties,
+ * see the file NOTICE in the root directory of the PlomRogue source package.
+ */
#include "ai.h"
-#include <stddef.h> /* NULL */
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, int16_t, UINT16_MAX */
#include <stdlib.h> /* free() */
#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 */
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);
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;
}
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;
}
}
static uint8_t get_dir_to_nearest_thing(struct Thing * t_eye, char filter)
{
- char dir_to_nearest_enemy = 0;
+ char dir_to_nearest_thing = 0;
if (seeing_thing(t_eye, filter))
{
uint32_t map_size = world.map.length * world.map.length;
if (min_neighbor > neighbors[i])
{
min_neighbor = neighbors[i];
- dir_to_nearest_enemy = dirs[i];
+ dir_to_nearest_thing = dirs[i];
}
}
}
- if (dir_to_nearest_enemy)
+ if (dir_to_nearest_thing)
{
t_eye->command = get_thing_action_id_by_name(s[S_CMD_MOVE]);
- t_eye->arg = dir_to_nearest_enemy;
+ t_eye->arg = dir_to_nearest_thing;
return 1;
}
return 0;
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;
}
}
}
int16_t selection = -1;
struct Thing * t = t_owner->owns;;
uint8_t i;
- for (i = 0; t != NULL; t = t->next, i++)
+ for (i = 0; t; t = t->next, i++)
{
struct ThingType * tt = get_thing_type(t->type);
if (tt->consumable > compare_consumability)
static uint8_t standing_on_consumable(struct Thing * t_standing)
{
struct Thing * t = world.things;
- for (; t != NULL; t = t->next)
+ for (; t; t = t->next)
{
if ( t != t_standing
&& t->pos.y == t_standing->pos.y && t->pos.x == t_standing->pos.x)