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

View File

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

View File

@ -18,10 +18,13 @@
#include "skill.h"
#include "study.h"
#include <util/attrib.h>
#include <util/language.h>
#include <util/message.h>
#include <util/nrmessage.h>
#include <attributes/hate.h>
#include <CuTest.h>
#include <tests.h>
#include <assert.h>
@ -267,10 +270,35 @@ static void test_spawn_seaserpent(CuTest *tc) {
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 *suite = CuSuiteNew();
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_monsters_attack_ocean);
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;
}
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)
{
order *ord;

View File

@ -98,6 +98,7 @@ extern "C" {
int check_ship_allowed(struct ship *sh, const struct region * r);
direction_t drift_target(struct ship *sh);
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
}
#endif