refactoring: special directions into their own file (vortex.c).

moving spells.c out of spells.
figured that movewhere should be in move.c
This commit is contained in:
Enno Rehling 2014-08-27 21:09:39 +02:00
parent ecaeba3058
commit 932a615837
21 changed files with 7307 additions and 7171 deletions

View File

@ -51,9 +51,11 @@ ENDIF()
set (ERESSEA_SRC
move.c
spells.c
battle.c
alchemy.c
stealth.c
vortex.c
names.c
reports.c
eressea.c

View File

@ -1,7 +1,7 @@
#include <platform.h>
#include <kernel/config.h>
#include <spells/spells.h>
#include "spells.h"
/* kernel includes */
#include <kernel/faction.h>

View File

@ -2,14 +2,9 @@
#include <kernel/types.h>
#include "direction.h"
#include "util/language.h"
#include "tests.h"
#include <kernel/config.h>
#include <kernel/region.h>
#include <kernel/unit.h>
#include <kernel/race.h>
#include <kernel/terrain.h>
#include <util/language.h>
#include <CuTest.h>
@ -63,27 +58,6 @@ static void test_get_direction_default(CuTest *tc) {
CuAssertIntEquals(tc, D_EAST, get_direction("east", lang));
}
static void test_move_to_vortex(CuTest *tc) {
region *r1, *r2, *r = 0;
terrain_type *t_plain;
unit *u;
struct locale *lang;
test_cleanup();
lang = get_or_create_locale("en");
locale_setstring(lang, "vortex", "wirbel");
init_locale(lang);
register_special_direction("vortex");
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
r1 = test_create_region(0, 0, t_plain);
r2 = test_create_region(5, 0, t_plain);
CuAssertPtrNotNull(tc, create_special_direction(r1, r2, 10, "", "vortex", true));
u = test_create_unit(test_create_faction(rc_get_or_create("hodor")), r1);
CuAssertIntEquals(tc, E_MOVE_NOREGION, movewhere(u, "barf", r1, &r));
CuAssertIntEquals(tc, E_MOVE_OK, movewhere(u, "wirbel", r1, &r));
CuAssertPtrEquals(tc, r2, r);
}
#define SUITE_DISABLE_TEST(suite, test) (void)test
CuSuite *get_direction_suite(void)
@ -92,7 +66,6 @@ CuSuite *get_direction_suite(void)
SUITE_ADD_TEST(suite, test_init_direction);
SUITE_ADD_TEST(suite, test_init_directions);
SUITE_ADD_TEST(suite, test_finddirection);
SUITE_ADD_TEST(suite, test_move_to_vortex);
SUITE_DISABLE_TEST(suite, test_get_direction_default);
return suite;
}

View File

@ -10,8 +10,9 @@ This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#include "helpers.h"
#include <platform.h>
#include "helpers.h"
#include "vortex.h"
#include <util/attrib.h>
#include <util/base36.h>
@ -541,6 +542,7 @@ int tolua_toid(lua_State * L, int idx, int def)
void register_tolua_helpers(void)
{
at_register(&at_direction);
at_register(&at_building_action);
register_function((pf_generic) & lua_building_protection,

View File

@ -2667,40 +2667,6 @@ message *movement_error(unit * u, const char *token, order * ord,
return NULL;
}
int movewhere(const unit * u, const char *token, region * r, region ** resultp)
{
region *r2;
direction_t d;
if (!token || *token == '\0') {
*resultp = NULL;
return E_MOVE_OK;
}
d = get_direction(token, u->faction->locale);
switch (d) {
case D_PAUSE:
*resultp = r;
break;
case NODIRECTION:
r2 = find_special_direction(r, token, u->faction->locale);
if (r2 == NULL) {
return E_MOVE_NOREGION;
}
*resultp = r2;
break;
default:
r2 = rconnect(r, d);
if (r2 == NULL || move_blocked(u, r, r2)) {
return E_MOVE_BLOCKED;
}
*resultp = r2;
}
return E_MOVE_OK;
}
bool move_blocked(const unit * u, const region * r, const region * r2)
{
connection *b;
@ -2779,7 +2745,6 @@ void attrib_init(void)
at_register(&at_seenspell);
/* neue REGION-Attribute */
at_register(&at_direction);
at_register(&at_moveblock);
at_register(&at_deathcount);
at_register(&at_chaoscount);

View File

@ -339,15 +339,6 @@ extern "C" {
const struct region *dest);
void add_income(struct unit *u, int type, int want, int qty);
/* movewhere error codes */
enum {
E_MOVE_OK = 0, /* possible to move */
E_MOVE_NOREGION, /* no region exists in this direction */
E_MOVE_BLOCKED /* cannot see this region, there is a blocking connection. */
};
int movewhere(const struct unit *u, const char *token,
struct region *r, struct region **resultp);
const char *datapath(void);
void set_datapath(const char *path);

View File

@ -189,163 +189,6 @@ void chaoscounts(region * r, int fallen)
a_remove(&r->attribs, a);
}
/********************/
/* at_direction */
/********************/
static void a_initdirection(attrib * a)
{
a->data.v = calloc(1, sizeof(spec_direction));
}
static void a_freedirection(attrib * a)
{
free(a->data.v);
}
static int a_agedirection(attrib * a)
{
spec_direction *d = (spec_direction *) (a->data.v);
--d->duration;
return (d->duration > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE;
}
typedef struct dir_lookup {
char *name;
const char *oldname;
struct dir_lookup *next;
} dir_lookup;
static dir_lookup *dir_name_lookup;
void register_special_direction(const char *name)
{
struct locale *lang;
char *str = _strdup(name);
for (lang = locales; lang; lang = nextlocale(lang)) {
void **tokens = get_translations(lang, UT_SPECDIR);
const char *token = LOC(lang, name);
if (token) {
variant var;
var.v = str;
addtoken(tokens, token, var);
if (lang == default_locale) {
dir_lookup *dl = malloc(sizeof(dir_lookup));
dl->name = str;
dl->oldname = token;
dl->next = dir_name_lookup;
dir_name_lookup = dl;
}
} else {
log_error("no translation for spec_direction '%s' in locale '%s'\n", name, locale_name(lang));
}
}
}
static int a_readdirection(attrib * a, void *owner, struct storage *store)
{
spec_direction *d = (spec_direction *) (a->data.v);
READ_INT(store, &d->x);
READ_INT(store, &d->y);
READ_INT(store, &d->duration);
if (global.data_version < UNICODE_VERSION) {
char lbuf[16];
dir_lookup *dl = dir_name_lookup;
READ_TOK(store, NULL, 0);
READ_TOK(store, lbuf, sizeof(lbuf));
cstring_i(lbuf);
for (; dl; dl = dl->next) {
if (strcmp(lbuf, dl->oldname) == 0) {
d->keyword = _strdup(dl->name);
sprintf(lbuf, "%s_desc", d->keyword);
d->desc = _strdup(dl->name);
break;
}
}
if (dl == NULL) {
log_error("unknown spec_direction '%s'\n", lbuf);
assert(!"not implemented");
}
} else {
char lbuf[32];
READ_TOK(store, lbuf, sizeof(lbuf));
d->desc = _strdup(lbuf);
READ_TOK(store, lbuf, sizeof(lbuf));
d->keyword = _strdup(lbuf);
}
d->active = true;
return AT_READ_OK;
}
static void
a_writedirection(const attrib * a, const void *owner, struct storage *store)
{
spec_direction *d = (spec_direction *) (a->data.v);
WRITE_INT(store, d->x);
WRITE_INT(store, d->y);
WRITE_INT(store, d->duration);
WRITE_TOK(store, d->desc);
WRITE_TOK(store, d->keyword);
}
attrib_type at_direction = {
"direction",
a_initdirection,
a_freedirection,
a_agedirection,
a_writedirection,
a_readdirection
};
region *find_special_direction(const region * r, const char *token,
const struct locale *lang)
{
attrib *a;
spec_direction *d;
if (strlen(token) == 0)
return NULL;
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) {
d = (spec_direction *) (a->data.v);
if (d->active) {
void **tokens = get_translations(lang, UT_SPECDIR);
variant var;
if (findtoken(*tokens, token, &var) == E_TOK_SUCCESS) {
if (strcmp((const char *)var.v, d->keyword) == 0) {
return findregion(d->x, d->y);
}
}
}
}
return NULL;
}
attrib *create_special_direction(region * r, region * rt, int duration,
const char *desc, const char *keyword, bool active)
{
attrib *a = a_add(&r->attribs, a_new(&at_direction));
spec_direction *d = (spec_direction *) (a->data.v);
d->active = active;
d->x = rt->x;
d->y = rt->y;
d->duration = duration;
d->desc = _strdup(desc);
d->keyword = _strdup(keyword);
return a;
}
/* Moveblock wird zur Zeit nicht über Attribute, sondern ein Bitfeld
r->moveblock gemacht. Sollte umgestellt werden, wenn kompliziertere
Dinge gefragt werden. */
@ -630,49 +473,6 @@ int distance(const region * r1, const region * r2)
return koor_distance(r1->x, r1->y, r2->x, r2->y);
}
static direction_t
koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl)
{
int dir;
for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
int x = ax + delta_x[dir];
int y = ay + delta_y[dir];
pnormalize(&x, &y, pl);
if (bx == x && by == y)
return (direction_t)dir;
}
return NODIRECTION;
}
spec_direction *special_direction(const region * from, const region * to)
{
const attrib *a = a_findc(from->attribs, &at_direction);
while (a != NULL && a->type == &at_direction) {
spec_direction *sd = (spec_direction *) a->data.v;
if (sd->x == to->x && sd->y == to->y)
return sd;
a = a->next;
}
return NULL;
}
direction_t reldirection(const region * from, const region * to)
{
plane *pl = rplane(from);
if (pl == rplane(to)) {
direction_t dir = koor_reldirection(from->x, from->y, to->x, to->y, pl);
if (dir == NODIRECTION) {
spec_direction *sd = special_direction(from, to);
if (sd != NULL && sd->active)
return D_SPECIAL;
}
return dir;
}
return NODIRECTION;
}
void free_regionlist(region_list * rl)
{
while (rl) {

View File

@ -153,14 +153,6 @@ extern "C" {
struct message *r_addmessage(struct region *r, const struct faction *viewer,
struct message *msg);
typedef struct spec_direction {
int x, y;
int duration;
bool active;
char *desc;
char *keyword;
} spec_direction;
typedef struct {
direction_t dir;
} moveblock;
@ -169,11 +161,9 @@ extern "C" {
int distance(const struct region *, const struct region *);
int koor_distance(int ax, int ay, int bx, int by);
direction_t reldirection(const struct region *from, const struct region *to);
struct region *findregion(int x, int y);
struct region *findregionbyid(int uid);
extern struct attrib_type at_direction;
extern struct attrib_type at_moveblock;
extern struct attrib_type at_peasantluck;
extern struct attrib_type at_horseluck;
@ -189,14 +179,6 @@ extern "C" {
void free_regionlist(region_list * rl);
void add_regionlist(region_list ** rl, struct region *r);
struct region *find_special_direction(const struct region *r,
const char *token, const struct locale *lang);
void register_special_direction(const char *name);
struct spec_direction *special_direction(const region * from,
const region * to);
struct attrib *create_special_direction(struct region *r, struct region *rt,
int duration, const char *desc, const char *keyword, bool active);
int deathcount(const struct region *r);
int chaoscount(const struct region *r);

View File

@ -29,6 +29,8 @@ without prior permission by the authors of Eressea.
#include "spellbook.h"
#include "calendar.h"
#include "vortex.h"
/* util includes */
#include <util/attrib.h>
#include <util/bsdstring.h>

View File

@ -31,8 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "build.h"
#include "bindings.h"
#include "races/races.h"
#include "spells/spells.h"
#include "spells/borders.h"
#include "spells.h"
#include <lua.h>
#include <assert.h>
@ -266,7 +265,6 @@ int main(int argc, char **argv)
L = lua_init();
game_init();
register_races();
register_borders();
register_spells();
bind_monsters(L);
err = eressea_run(L, luafile);

View File

@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "move.h"
#include "reports.h"
#include "alchemy.h"
#include "vortex.h"
#include <kernel/build.h>
#include <kernel/building.h>
@ -543,6 +544,36 @@ void travelthru(const unit * u, region * r)
#endif
}
static direction_t
koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl)
{
int dir;
for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
int x = ax + delta_x[dir];
int y = ay + delta_y[dir];
pnormalize(&x, &y, pl);
if (bx == x && by == y)
return (direction_t)dir;
}
return NODIRECTION;
}
direction_t reldirection(const region * from, const region * to)
{
plane *pl = rplane(from);
if (pl == rplane(to)) {
direction_t dir = koor_reldirection(from->x, from->y, to->x, to->y, pl);
if (dir == NODIRECTION) {
spec_direction *sd = special_direction(from, to);
if (sd != NULL && sd->active)
return D_SPECIAL;
}
return dir;
}
return NODIRECTION;
}
static void leave_trail(ship * sh, region * from, region_list * route)
{
region *r = from;
@ -1038,6 +1069,40 @@ unit *is_guarded(region * r, unit * u, unsigned int mask)
return NULL;
}
int movewhere(const unit * u, const char *token, region * r, region ** resultp)
{
region *r2;
direction_t d;
if (!token || *token == '\0') {
*resultp = NULL;
return E_MOVE_OK;
}
d = get_direction(token, u->faction->locale);
switch (d) {
case D_PAUSE:
*resultp = r;
break;
case NODIRECTION:
r2 = find_special_direction(r, token, u->faction->locale);
if (r2 == NULL) {
return E_MOVE_NOREGION;
}
*resultp = r2;
break;
default:
r2 = rconnect(r, d);
if (r2 == NULL || move_blocked(u, r, r2)) {
return E_MOVE_BLOCKED;
}
*resultp = r2;
}
return E_MOVE_OK;
}
static const char *shortdirections[MAXDIRECTIONS] = {
"dir_nw",
"dir_ne",

View File

@ -1,7 +1,7 @@
/*
Copyright (c) 1998-2010, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -18,61 +18,74 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_KRNL_MOVEMENT
#define H_KRNL_MOVEMENT
#include "direction.h"
#ifdef __cplusplus
extern "C" {
#endif
struct unit;
struct ship;
struct building_type;
struct unit;
struct ship;
struct building_type;
/* die Zahlen sind genau äquivalent zu den race Flags */
extern struct attrib_type at_speedup;
/* die Zahlen sind genau äquivalent zu den race Flags */
#define MV_CANNOTMOVE (1<<5)
#define MV_FLY (1<<7) /* kann fliegen */
#define MV_SWIM (1<<8) /* kann schwimmen */
#define MV_WALK (1<<9) /* kann über Land gehen */
/* Die tragekapaz. ist hardcodiert mit defines, da es bis jetzt sowieso nur 2
** objekte gibt, die etwas tragen. */
/* Die tragekapaz. ist hardcodiert mit defines, da es bis jetzt sowieso nur 2
** objekte gibt, die etwas tragen. */
#define SILVERWEIGHT 1
#define SCALEWEIGHT 100 /* Faktor, um den die Anzeige von gewichten
* * skaliert wird */
* * skaliert wird */
#define HORSECAPACITY 7000
#define WAGONCAPACITY 14000
#define HORSESNEEDED 2
/* ein mensch wiegt 10, traegt also 5, ein pferd wiegt 50, traegt also 20. ein
** wagen wird von zwei pferden gezogen und traegt total 140, davon 40 die
** pferde, macht nur noch 100, aber samt eigenem gewicht (40) macht also 140. */
/* ein mensch wiegt 10, traegt also 5, ein pferd wiegt 50, traegt also 20. ein
** wagen wird von zwei pferden gezogen und traegt total 140, davon 40 die
** pferde, macht nur noch 100, aber samt eigenem gewicht (40) macht also 140. */
int personcapacity(const struct unit *u);
void movement(void);
void run_to(struct unit *u, struct region *to);
struct unit *is_guarded(struct region *r, struct unit *u, unsigned int mask);
bool is_guard(const struct unit *u, int mask);
int enoughsailors(const struct ship *sh, const struct region *r);
bool canswim(struct unit *u);
bool canfly(struct unit *u);
struct unit *get_captain(const struct ship *sh);
void travelthru(const struct unit *u, struct region *r);
struct ship *move_ship(struct ship *sh, struct region *from,
struct region *to, struct region_list *route);
int walkingcapacity(const struct unit *u);
void follow_unit(struct unit *u);
bool buildingtype_exists(const struct region *r,
const struct building_type *bt, bool working);
struct unit *owner_buildingtyp(const struct region *r,
const struct building_type *bt);
/* movewhere error codes */
enum {
E_MOVE_OK = 0, /* possible to move */
E_MOVE_NOREGION, /* no region exists in this direction */
E_MOVE_BLOCKED /* cannot see this region, there is a blocking connection. */
};
int movewhere(const struct unit *u, const char *token,
struct region *r, struct region **resultp);
direction_t reldirection(const struct region *from, const struct region *to);
extern struct attrib_type at_speedup;
int personcapacity(const struct unit *u);
void movement(void);
void run_to(struct unit *u, struct region *to);
struct unit *is_guarded(struct region *r, struct unit *u, unsigned int mask);
bool is_guard(const struct unit *u, int mask);
int enoughsailors(const struct ship *sh, const struct region *r);
bool canswim(struct unit *u);
bool canfly(struct unit *u);
struct unit *get_captain(const struct ship *sh);
void travelthru(const struct unit *u, struct region *r);
struct ship *move_ship(struct ship *sh, struct region *from,
struct region *to, struct region_list *route);
int walkingcapacity(const struct unit *u);
void follow_unit(struct unit *u);
bool buildingtype_exists(const struct region *r,
const struct building_type *bt, bool working);
struct unit *owner_buildingtyp(const struct region *r,
const struct building_type *bt);
#define SA_HARBOUR 2
#define SA_COAST 1
#define SA_NO_INSECT -1
#define SA_NO_COAST -2
extern int check_ship_allowed(struct ship *sh, const struct region * r);
int check_ship_allowed(struct ship *sh, const struct region * r);
#ifdef __cplusplus
}
#endif

View File

@ -38,6 +38,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "laws.h"
#include "move.h"
#include "alchemy.h"
#include "vortex.h"
/* kernel includes */
#include <kernel/ally.h>
@ -1127,46 +1128,47 @@ static void describe(FILE * F, const seen_region * sr, faction * f)
/* list directions */
dh = false;
for (d = 0; d != MAXDIRECTIONS; d++)
for (d = 0; d != MAXDIRECTIONS; d++) {
if (see[d]) {
region *r2 = rconnect(r, d);
if (!r2)
continue;
nrd--;
if (dh) {
char regname[4096];
if (nrd == 0) {
region *r2 = rconnect(r, d);
if (!r2)
continue;
nrd--;
if (dh) {
char regname[4096];
if (nrd == 0) {
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_final"), size);
}
else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_next"), size);
}
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, directions[d]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_final"), size);
f_regionid(r2, f, regname, sizeof(regname));
bytes = _snprintf(bufp, size, trailinto(r2, f->locale), regname);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_nb_next"), size);
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
MSG(("nr_vicinitystart", "dir region", d, r2), bufp, size, f->locale,
f);
bufp += strlen(bufp);
dh = true;
}
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, directions[d]), size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
f_regionid(r2, f, regname, sizeof(regname));
bytes = _snprintf(bufp, size, trailinto(r2, f->locale), regname);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
}
else {
bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER();
MSG(("nr_vicinitystart", "dir region", d, r2), bufp, size, f->locale,
f);
bufp += strlen(bufp);
dh = true;
}
}
}
/* Spezielle Richtungen */
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) {

6876
src/spells.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@ buildingcurse.c
combatspells.c
regioncurse.c
shipcurse.c
spells.c
unitcurse.c
)
FOREACH(_FILE ${_FILES})

File diff suppressed because it is too large Load Diff

View File

@ -44,20 +44,21 @@ int RunAllTests(void)
ADD_TESTS(suite, equipment);
ADD_TESTS(suite, item);
ADD_TESTS(suite, magic);
ADD_TESTS(suite, move);
ADD_TESTS(suite, reports);
ADD_TESTS(suite, save);
ADD_TESTS(suite, ship);
ADD_TESTS(suite, spellbook);
ADD_TESTS(suite, building);
ADD_TESTS(suite, spell);
ADD_TESTS(suite, battle);
ADD_TESTS(suite, ally);
/* gamecode */
ADD_TESTS(suite, stealth);
ADD_TESTS(suite, market);
ADD_TESTS(suite, laws);
ADD_TESTS(suite, battle);
ADD_TESTS(suite, economy);
ADD_TESTS(suite, laws);
ADD_TESTS(suite, market);
ADD_TESTS(suite, move);
ADD_TESTS(suite, stealth);
ADD_TESTS(suite, vortex);
CuSuiteRun(suite);
CuSuiteSummary(suite, output);

190
src/vortex.c Normal file
View File

@ -0,0 +1,190 @@
#include <config.h>
#include <platform.h>
#include "vortex.h"
#include <kernel/config.h>
#include <kernel/version.h>
#include <kernel/region.h>
#include <util/attrib.h>
#include <util/language.h>
#include <util/log.h>
#include <util/umlaut.h>
#include <util/variant.h>
#include <storage.h>
#include <assert.h>
typedef struct dir_lookup {
char *name;
const char *oldname;
struct dir_lookup *next;
} dir_lookup;
static dir_lookup *dir_name_lookup;
void register_special_direction(const char *name)
{
struct locale *lang;
char *str = _strdup(name);
for (lang = locales; lang; lang = nextlocale(lang)) {
void **tokens = get_translations(lang, UT_SPECDIR);
const char *token = LOC(lang, name);
if (token) {
variant var;
var.v = str;
addtoken(tokens, token, var);
if (lang == default_locale) {
dir_lookup *dl = malloc(sizeof(dir_lookup));
dl->name = str;
dl->oldname = token;
dl->next = dir_name_lookup;
dir_name_lookup = dl;
}
}
else {
log_error("no translation for spec_direction '%s' in locale '%s'\n", name, locale_name(lang));
}
}
}
/********************/
/* at_direction */
/********************/
static void a_initdirection(attrib * a)
{
a->data.v = calloc(1, sizeof(spec_direction));
}
static void a_freedirection(attrib * a)
{
free(a->data.v);
}
static int a_agedirection(attrib * a)
{
spec_direction *d = (spec_direction *)(a->data.v);
--d->duration;
return (d->duration > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE;
}
static int a_readdirection(attrib * a, void *owner, struct storage *store)
{
spec_direction *d = (spec_direction *)(a->data.v);
_CRT_UNUSED(owner);
READ_INT(store, &d->x);
READ_INT(store, &d->y);
READ_INT(store, &d->duration);
if (global.data_version < UNICODE_VERSION) {
char lbuf[16];
dir_lookup *dl = dir_name_lookup;
READ_TOK(store, NULL, 0);
READ_TOK(store, lbuf, sizeof(lbuf));
cstring_i(lbuf);
for (; dl; dl = dl->next) {
if (strcmp(lbuf, dl->oldname) == 0) {
d->keyword = _strdup(dl->name);
_snprintf(lbuf, sizeof(lbuf), "%s_desc", d->keyword);
d->desc = _strdup(dl->name);
break;
}
}
if (dl == NULL) {
log_error("unknown spec_direction '%s'\n", lbuf);
assert(!"not implemented");
}
}
else {
char lbuf[32];
READ_TOK(store, lbuf, sizeof(lbuf));
d->desc = _strdup(lbuf);
READ_TOK(store, lbuf, sizeof(lbuf));
d->keyword = _strdup(lbuf);
}
d->active = true;
return AT_READ_OK;
}
static void
a_writedirection(const attrib * a, const void *owner, struct storage *store)
{
spec_direction *d = (spec_direction *)(a->data.v);
_CRT_UNUSED(owner);
WRITE_INT(store, d->x);
WRITE_INT(store, d->y);
WRITE_INT(store, d->duration);
WRITE_TOK(store, d->desc);
WRITE_TOK(store, d->keyword);
}
attrib_type at_direction = {
"direction",
a_initdirection,
a_freedirection,
a_agedirection,
a_writedirection,
a_readdirection
};
region *find_special_direction(const region * r, const char *token,
const struct locale *lang)
{
attrib *a;
spec_direction *d;
if (strlen(token) == 0)
return NULL;
for (a = a_find(r->attribs, &at_direction); a && a->type == &at_direction;
a = a->next) {
d = (spec_direction *)(a->data.v);
if (d->active) {
void **tokens = get_translations(lang, UT_SPECDIR);
variant var;
if (findtoken(*tokens, token, &var) == E_TOK_SUCCESS) {
if (strcmp((const char *)var.v, d->keyword) == 0) {
return findregion(d->x, d->y);
}
}
}
}
return NULL;
}
attrib *create_special_direction(region * r, region * rt, int duration,
const char *desc, const char *keyword, bool active)
{
attrib *a = a_add(&r->attribs, a_new(&at_direction));
spec_direction *d = (spec_direction *)(a->data.v);
d->active = active;
d->x = rt->x;
d->y = rt->y;
d->duration = duration;
d->desc = _strdup(desc);
d->keyword = _strdup(keyword);
return a;
}
spec_direction *special_direction(const region * from, const region * to)
{
const attrib *a = a_findc(from->attribs, &at_direction);
while (a != NULL && a->type == &at_direction) {
spec_direction *sd = (spec_direction *)a->data.v;
if (sd->x == to->x && sd->y == to->y)
return sd;
a = a->next;
}
return NULL;
}

32
src/vortex.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef H_VORTEX
#define H_VORTEX
#ifdef __cplusplus
extern "C" {
#endif
struct region;
struct attrib;
struct locale;
typedef struct spec_direction {
int x, y;
int duration;
bool active;
char *desc;
char *keyword;
} spec_direction;
extern struct attrib_type at_direction;
struct region *find_special_direction(const struct region *r,
const char *token, const struct locale *lang);
void register_special_direction(const char *name);
struct spec_direction *special_direction(const struct region * from,
const struct region * to);
struct attrib *create_special_direction(struct region *r, struct region *rt,
int duration, const char *desc, const char *keyword, bool active);
#ifdef __cplusplus
}
#endif
#endif

48
src/vortex.test.c Normal file
View File

@ -0,0 +1,48 @@
#include <platform.h>
#include <kernel/types.h>
#include "vortex.h"
#include "move.h"
#include "tests.h"
#include <kernel/config.h>
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <kernel/unit.h>
#include <kernel/race.h>
#include <util/language.h>
#include <CuTest.h>
static void test_move_to_vortex(CuTest *tc) {
region *r1, *r2, *r = 0;
terrain_type *t_plain;
unit *u;
struct locale *lang;
test_cleanup();
lang = get_or_create_locale("en");
locale_setstring(lang, "vortex", "wirbel");
init_locale(lang);
register_special_direction("vortex");
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION);
r1 = test_create_region(0, 0, t_plain);
r2 = test_create_region(5, 0, t_plain);
CuAssertPtrNotNull(tc, create_special_direction(r1, r2, 10, "", "vortex", true));
u = test_create_unit(test_create_faction(rc_get_or_create("hodor")), r1);
CuAssertIntEquals(tc, E_MOVE_NOREGION, movewhere(u, "barf", r1, &r));
CuAssertIntEquals(tc, E_MOVE_OK, movewhere(u, "wirbel", r1, &r));
CuAssertPtrEquals(tc, r2, r);
}
static void test_vortex(CuTest *tc) {
}
CuSuite *get_vortex_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_vortex);
SUITE_ADD_TEST(suite, test_move_to_vortex);
return suite;
}