refactor monster movement planning, test at_hate.

This commit is contained in:
Enno Rehling 2018-04-22 18:04:09 +01:00
parent fc4b7ba73d
commit 0171c74e19
5 changed files with 67 additions and 24 deletions

View file

@ -55,7 +55,6 @@
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
#include <util/base36.h> #include <util/base36.h>
#include <util/bsdstring.h>
#include <util/event.h> #include <util/event.h>
#include <util/language.h> #include <util/language.h>
#include <util/lists.h> #include <util/lists.h>
@ -502,41 +501,30 @@ static attrib *set_new_dragon_target(unit * u, region * r, int range)
return NULL; return NULL;
} }
static order *make_movement_order(unit * u, const region * target, int moves, static order *plan_move_to_target(unit * u, const region * target, int moves,
bool(*allowed) (const region *, const region *)) bool(*allowed) (const region *, const region *))
{ {
region *r = u->region; region *r = u->region;
region **plan; region **plan;
int position = 0; direction_t steps[DRAGON_RANGE];
char zOrder[128], *bufp = zOrder; int position;
size_t size = sizeof(zOrder) - 1;
if (monster_is_waiting(u)) if (monster_is_waiting(u))
return NULL; return NULL;
plan = path_find(r, target, DRAGON_RANGE * 5, allowed); plan = path_find(r, target, DRAGON_RANGE, allowed);
if (plan == NULL) if (plan == NULL)
return NULL; return NULL;
while (position != moves && plan[position + 1]) { for (position = 0; position != moves && plan[position + 1]; ++position) {
int bytes;
region *prev = plan[position]; region *prev = plan[position];
region *next = plan[++position]; region *next = plan[position + 1];
direction_t dir = reldirection(prev, next); direction_t dir = reldirection(prev, next);
assert(dir != NODIRECTION && dir != D_SPECIAL); assert(dir != NODIRECTION && dir != D_SPECIAL);
if (size > 1 && bufp != zOrder) { steps[position] = dir;
*bufp++ = ' ';
--size;
}
bytes =
(int)str_strlcpy(bufp,
(const char *)LOC(u->faction->locale, directions[dir]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
} }
*bufp = 0; return make_movement_order(u->faction->locale, steps, position);
return create_order(K_MOVE, u->faction->locale, zOrder);
} }
void random_growl(const unit *u, region *target, int rand) void random_growl(const unit *u, region *target, int rand)
@ -689,15 +677,15 @@ static order *plan_dragon(unit * u)
assert(long_order == NULL); assert(long_order == NULL);
/* TODO: per-race planning functions? */ /* TODO: per-race planning functions? */
if (rc == rc_wyrm) { if (rc == rc_wyrm) {
long_order = make_movement_order(u, tr, 1, allowed_dragon); long_order = plan_move_to_target(u, tr, 1, allowed_dragon);
} }
else { else {
switch (old_race(rc)) { switch (old_race(rc)) {
case RC_FIREDRAGON: case RC_FIREDRAGON:
long_order = make_movement_order(u, tr, 4, allowed_dragon); long_order = plan_move_to_target(u, tr, 4, allowed_dragon);
break; break;
case RC_DRAGON: case RC_DRAGON:
long_order = make_movement_order(u, tr, 3, allowed_dragon); long_order = plan_move_to_target(u, tr, 3, allowed_dragon);
break; break;
default: default:
break; break;
@ -793,7 +781,7 @@ void plan_monsters(faction * f)
if (canfly(u)) { if (canfly(u)) {
allowed = allowed_fly; allowed = allowed_fly;
} }
long_order = make_movement_order(u, tu->region, 2, allowed); long_order = plan_move_to_target(u, tu->region, 2, allowed);
} }
else else
a_remove(&u->attribs, ta); a_remove(&u->attribs, ta);

View file

@ -28,6 +28,8 @@ extern "C" {
struct unit; struct unit;
struct region; struct region;
struct faction; struct faction;
struct order;
struct locale;
struct unit *spawn_seaserpent(struct region *r, struct faction *f); struct unit *spawn_seaserpent(struct region *r, struct faction *f);
void spawn_dragons(void); void spawn_dragons(void);

View file

@ -18,10 +18,13 @@
#include "skill.h" #include "skill.h"
#include "study.h" #include "study.h"
#include <util/attrib.h>
#include <util/language.h> #include <util/language.h>
#include <util/message.h> #include <util/message.h>
#include <util/nrmessage.h> #include <util/nrmessage.h>
#include <attributes/hate.h>
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>
#include <assert.h> #include <assert.h>
@ -267,10 +270,35 @@ static void test_spawn_seaserpent(CuTest *tc) {
test_teardown(); test_teardown();
} }
static void test_monsters_hate(CuTest *tc) {
unit *mu, *tu;
order *ord;
char buffer[32];
const struct locale *lang;
test_setup();
tu = test_create_unit(test_create_faction(NULL), test_create_plain(1, 0));
mu = test_create_unit(get_monsters(), test_create_plain(0, 0));
lang = mu->faction->locale;
a_add(&mu->attribs, make_hate(tu));
plan_monsters(mu->faction);
CuAssertPtrNotNull(tc, mu->orders);
for (ord = mu->orders; ord; ord = ord->next) {
if (K_MOVE == getkeyword(ord)) {
break;
}
}
CuAssertPtrNotNull(tc, ord);
CuAssertIntEquals(tc, K_MOVE, getkeyword(ord));
CuAssertStrEquals(tc, "move east", get_command(ord, lang, buffer, sizeof(buffer)));
test_teardown();
}
CuSuite *get_monsters_suite(void) CuSuite *get_monsters_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_monsters_attack); SUITE_ADD_TEST(suite, test_monsters_attack);
SUITE_ADD_TEST(suite, test_monsters_hate);
SUITE_ADD_TEST(suite, test_spawn_seaserpent); SUITE_ADD_TEST(suite, test_spawn_seaserpent);
SUITE_ADD_TEST(suite, test_monsters_attack_ocean); SUITE_ADD_TEST(suite, test_monsters_attack_ocean);
SUITE_ADD_TEST(suite, test_seaserpent_piracy); SUITE_ADD_TEST(suite, test_seaserpent_piracy);

View file

@ -1131,6 +1131,30 @@ order * cycle_route(order * ord, const struct locale *lang, int gereist)
return norder; return norder;
} }
order * make_movement_order(const struct locale *lang, direction_t steps[], int length)
{
char zOrder[128], *bufp = zOrder;
size_t size = sizeof(zOrder) - 1;
int i;
for (i = 0; i != length; ++i) {
int bytes;
direction_t dir = steps[i];
if (size > 1 && bufp != zOrder) {
*bufp++ = ' ';
--size;
}
bytes =
(int)str_strlcpy(bufp,
(const char *)LOC(lang, directions[dir]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
*bufp = 0;
return create_order(K_MOVE, lang, zOrder);
}
static bool transport(unit * ut, unit * u) static bool transport(unit * ut, unit * u)
{ {
order *ord; order *ord;

View file

@ -98,6 +98,7 @@ extern "C" {
int check_ship_allowed(struct ship *sh, const struct region * r); int check_ship_allowed(struct ship *sh, const struct region * r);
direction_t drift_target(struct ship *sh); direction_t drift_target(struct ship *sh);
struct order * cycle_route(struct order * ord, const struct locale *lang, int gereist); struct order * cycle_route(struct order * ord, const struct locale *lang, int gereist);
struct order * make_movement_order(const struct locale *lang, direction_t steps[], int length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif