From ac4df079495af8e1e141408a3d936420f7d02b0f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Feb 2025 18:38:05 +0100 Subject: [PATCH 1/2] unit debugging helpers --- scripts/debug.lua | 13 ++++ src/attributes/attributes.c | 1 - src/attributes/attributes.h | 4 -- src/bindings.c | 9 +++ src/kernel/attrib.c | 10 +++ src/kernel/attrib.h | 135 +++++++++++++++++------------------- src/kernel/curse.c | 14 +++- src/kernel/event.c | 21 +++++- src/kernel/event.h | 109 ++++++++++++++--------------- src/kernel/save.c | 1 - src/kernel/unit.c | 12 ++++ src/kernel/unit.h | 2 + src/triggers/createcurse.c | 12 +++- src/triggers/timeout.c | 13 +++- 14 files changed, 218 insertions(+), 138 deletions(-) create mode 100644 scripts/debug.lua diff --git a/scripts/debug.lua b/scripts/debug.lua new file mode 100644 index 000000000..e6020a1a2 --- /dev/null +++ b/scripts/debug.lua @@ -0,0 +1,13 @@ +require 'eressea.path' +require 'eressea' +require 'eressea.xmlconf' + +function gmtool_on_keypressed(keycode) + local warp = require('eressea.warpgate') + if keycode == gmtool.KEY_F1 then + warp.gm_edit() + end +end + +eressea.read_game(get_turn() .. ".dat") +dump_unit("jiha") diff --git a/src/attributes/attributes.c b/src/attributes/attributes.c index b73bc3583..e214c8655 100644 --- a/src/attributes/attributes.c +++ b/src/attributes/attributes.c @@ -10,7 +10,6 @@ #include "iceberg.h" #include "key.h" #include "stealth.h" -#include "magic.h" #include "movement.h" #include "otherfaction.h" #include "racename.h" diff --git a/src/attributes/attributes.h b/src/attributes/attributes.h index 075f56d4b..6c1cf6552 100644 --- a/src/attributes/attributes.h +++ b/src/attributes/attributes.h @@ -1,6 +1,4 @@ #pragma once -#ifndef H_ATTRIBUTE_ATTRIBUTES -#define H_ATTRIBUTE_ATTRIBUTES struct attrib_type; struct region; @@ -12,5 +10,3 @@ void set_observer(struct region *r, struct faction *f, int perception, int turns int get_observer(const struct region *r, const struct faction *f); extern struct attrib_type at_unitdissolve; - -#endif diff --git a/src/bindings.c b/src/bindings.c index 0f1b83032..6f951a86b 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -530,6 +530,14 @@ static int tolua_get_unit(lua_State * L) return 1; } +static int tolua_dump_unit(lua_State * L) +{ + int no = tolua_toid(L, 1, 0); + unit *u = findunit(no); + dump_unit(u); + return 0; +} + static int tolua_alliance_create(lua_State * L) { int id = (int)tolua_tonumber(L, 1, 0); @@ -984,6 +992,7 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile) } tolua_endmodule(L); tolua_function(L, "get_region_by_id", tolua_get_region_byid); tolua_function(L, "get_unit", tolua_get_unit); + tolua_function(L, "dump_unit", tolua_dump_unit); tolua_function(L, "get_alliance", tolua_get_alliance); tolua_function(L, "get_ship", tolua_get_ship); tolua_function(L, "get_building", tolua_get_building); diff --git a/src/kernel/attrib.c b/src/kernel/attrib.c index fc3947b42..f199f3326 100644 --- a/src/kernel/attrib.c +++ b/src/kernel/attrib.c @@ -498,3 +498,13 @@ void attrib_done(void) { cb_clear(&cb_deprecated); hmfree(at_hash); } + +void dump_attrib(const attrib *a) { + if (a) { + fprintf(stdout, "- %s\n", a->type->name); + if (a->type->dump) { + a->type->dump(a); + } + } + else fputs("null", stdout); +} diff --git a/src/kernel/attrib.h b/src/kernel/attrib.h index 9302b5412..f6eaf20a3 100644 --- a/src/kernel/attrib.h +++ b/src/kernel/attrib.h @@ -1,77 +1,76 @@ -#ifndef ATTRIB_H -#define ATTRIB_H +#pragma once -#include #include "../util/variant.h" -#ifdef __cplusplus -extern "C" { -#endif - - union variant; - struct gamedata; - struct storage; - typedef void(*afun) (void); - - typedef struct attrib { - const struct attrib_type *type; - union variant data; - /* internal data, do not modify: */ - struct attrib *next; /* next attribute in the list */ - struct attrib *nexttype; /* skip to attribute of a different type */ - } attrib; + +#include + +union variant; +struct gamedata; +struct storage; +typedef void(*afun) (void); + +typedef struct attrib { + const struct attrib_type *type; + union variant data; + /* internal data, do not modify: */ + struct attrib *next; /* next attribute in the list */ + struct attrib *nexttype; /* skip to attribute of a different type */ +} attrib; #define ATF_UNIQUE (1<<0) /* only one per attribute-list */ #define ATF_PRESERVE (1<<1) /* preserve order in list. append to back */ #define ATF_USER_DEFINED (1<<2) /* use this to make udf */ - typedef struct attrib_type { - const char *name; - void(*initialize) (union variant *); - void(*finalize) (union variant *); - int(*age) (struct attrib *, void *owner); - /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ - void(*write) (const union variant *, const void *owner, struct storage *); - int(*read) (union variant *, void *owner, struct gamedata *); /* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */ - void(*upgrade) (struct attrib **alist, struct attrib *a); - unsigned int flags; - } attrib_type; - - void at_register(attrib_type * at); - void at_deprecate(const char * name, int (*reader)(variant *, void *, struct gamedata *)); - struct attrib_type *at_find(const char *name); - - void write_attribs(struct storage *store, struct attrib *alist, const void *owner); - int read_attribs(struct gamedata *store, struct attrib **alist, void *owner); - - attrib *a_select(attrib * a, const void *data, bool(*compare) (const attrib *, const void *)); - attrib *a_find(attrib * a, const attrib_type * at); - attrib *a_add(attrib ** pa, attrib * at); - int a_remove(attrib ** pa, attrib * at); - void a_removeall(attrib ** a, const attrib_type * at); - attrib *a_new(const attrib_type * at); - int a_age(attrib ** attribs, void *owner); - - void a_free_voidptr(union variant *v); - int a_read_orig(struct gamedata *data, attrib ** attribs, void *owner); - int a_read(struct gamedata *data, attrib ** attribs, void *owner); - void a_write(struct storage *store, const attrib * attribs, const void *owner); - - int a_readint(union variant *v, void *owner, struct gamedata *); - void a_writeint(const union variant *v, const void *owner, - struct storage *store); - int a_readshorts(union variant *v, void *owner, struct gamedata *); - void a_writeshorts(const union variant *v, const void *owner, - struct storage *store); - int a_readchars(union variant *v, void *owner, struct gamedata *); - void a_writechars(const union variant *v, const void *owner, - struct storage *store); - int a_readstring(union variant *v, void *owner, struct gamedata *); - void a_writestring(const union variant *v, const void *owner, - struct storage *); - void a_finalizestring(union variant *v); - - void attrib_done(void); +typedef struct attrib_type { + const char *name; + void(*initialize) (union variant *); + void(*finalize) (union variant *); + int(*age) (struct attrib *, void *owner); + /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ + void(*write) (const union variant *, const void *owner, struct storage *); + int(*read) (union variant *, void *owner, struct gamedata *); /* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */ + void(*upgrade) (struct attrib **alist, struct attrib *a); + unsigned int flags; + void(*dump) (const struct attrib *a); +} attrib_type; + +void at_register(attrib_type * at); +void at_deprecate(const char * name, int (*reader)(variant *, void *, struct gamedata *)); +struct attrib_type *at_find(const char *name); + +void write_attribs(struct storage *store, struct attrib *alist, const void *owner); +int read_attribs(struct gamedata *store, struct attrib **alist, void *owner); + +attrib *a_select(attrib * a, const void *data, bool(*compare) (const attrib *, const void *)); +attrib *a_find(attrib * a, const attrib_type * at); +attrib *a_add(attrib ** pa, attrib * at); +int a_remove(attrib ** pa, attrib * at); +void a_removeall(attrib ** a, const attrib_type * at); +attrib *a_new(const attrib_type * at); +int a_age(attrib ** attribs, void *owner); + +void a_free_voidptr(union variant *v); +int a_read_orig(struct gamedata *data, attrib ** attribs, void *owner); +int a_read(struct gamedata *data, attrib ** attribs, void *owner); +void a_write(struct storage *store, const attrib * attribs, const void *owner); + +int a_readint(union variant *v, void *owner, struct gamedata *); +void a_writeint(const union variant *v, const void *owner, + struct storage *store); +int a_readshorts(union variant *v, void *owner, struct gamedata *); +void a_writeshorts(const union variant *v, const void *owner, + struct storage *store); +int a_readchars(union variant *v, void *owner, struct gamedata *); +void a_writechars(const union variant *v, const void *owner, + struct storage *store); +int a_readstring(union variant *v, void *owner, struct gamedata *); +void a_writestring(const union variant *v, const void *owner, + struct storage *); +void a_finalizestring(union variant *v); + +void attrib_done(void); +void dump_attrib(const struct attrib *a); #define DEFAULT_AGE NULL #define DEFAULT_INIT NULL #define DEFAULT_FINALIZE NULL @@ -85,7 +84,3 @@ extern "C" { #define AT_AGE_REMOVE 0 /* remove the attribute after calling age() */ #define AT_AGE_KEEP 1 /* keep the attribute for another turn */ -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/kernel/curse.c b/src/kernel/curse.c index d94152d72..5b2dbcbe0 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -250,6 +250,17 @@ void curse_write(const variant * var, const void *owner, struct storage *store) } } +static void curse_dump(const attrib *a) +{ + curse *c = (curse *)a->data.v; + const curse_type *ct = c->type; + fprintf(stdout, " type: %s\n", ct->cname); + fprintf(stdout, " mage: %s\n", unitname(c->magician)); + fprintf(stdout, " duration: %d\n", c->duration); + fprintf(stdout, " effect: %lf\n", c->effect); + fprintf(stdout, " vigour: %lf\n", c->vigour); +} + attrib_type at_curse = { "curse", curse_init, @@ -257,7 +268,8 @@ attrib_type at_curse = { curse_age, curse_write, curse_read, - NULL + NULL, + .dump = curse_dump, }; /* ------------------------------------------------------------- */ diff --git a/src/kernel/event.c b/src/kernel/event.c index 51b4a6ef2..bd2762106 100644 --- a/src/kernel/event.c +++ b/src/kernel/event.c @@ -152,13 +152,32 @@ static int read_handler(variant *var, void *owner, gamedata *data) return AT_READ_FAIL; } +void dump_trigger(const trigger *t, int indent) +{ + fprintf(stdout, "%*s- trigger: %s\n", indent, "", t->type->name); + if (t->type->dump) { + t->type->dump(t, indent + 2); + } +} + +static void dump_handler(const attrib *a) +{ + const handler_info *hi = (const handler_info *)a->data.v; + const trigger *t; + fprintf(stdout, " event: %s\n", hi->event); + for (t = hi->triggers; t; t = t->next) { + dump_trigger(t, 2); + } +} + attrib_type at_eventhandler = { "eventhandler", init_handler, free_handler, NULL, write_handler, - read_handler + read_handler, + .dump = dump_handler }; struct trigger **get_triggers(struct attrib *ap, const char *eventname) diff --git a/src/kernel/event.h b/src/kernel/event.h index f83d264bb..a49fcb12e 100644 --- a/src/kernel/event.h +++ b/src/kernel/event.h @@ -1,72 +1,65 @@ -#ifndef EVENT_H -#define EVENT_H -#ifdef __cplusplus -extern "C" { -#endif +#pragma once #include - struct attrib; - struct trigger; - struct storage; - struct gamedata; +struct attrib; +struct trigger; +struct storage; +struct gamedata; - typedef struct trigger_type { - const char *name; - void(*initialize) (struct trigger *); - void(*finalize) (struct trigger *); - int(*handle) (struct trigger *, void *); - void(*write) (const struct trigger *, struct storage * store); - int(*read) (struct trigger *, struct gamedata * store); +typedef struct trigger_type { + const char *name; + void(*initialize) (struct trigger *); + void(*finalize) (struct trigger *); + int(*handle) (struct trigger *, void *); + void(*write) (const struct trigger *, struct storage * store); + int(*read) (struct trigger *, struct gamedata * store); + void(*dump) (const struct trigger *, int indent); + struct trigger_type *next; +} trigger_type; - struct trigger_type *next; - } trigger_type; +trigger_type *tt_find(const char *name); +void tt_register(trigger_type * ttype); - trigger_type *tt_find(const char *name); - void tt_register(trigger_type * ttype); +typedef struct trigger { + struct trigger_type *type; + struct trigger *next; - typedef struct trigger { - struct trigger_type *type; - struct trigger *next; + variant data; +} trigger; - variant data; - } trigger; +typedef struct event_arg { + const char *type; + variant data; +} event_arg; - typedef struct event_arg { - const char *type; - variant data; - } event_arg; +typedef struct handler_info { + char *event; + trigger *triggers; +} handler_info; - typedef struct handler_info { - char *event; - trigger *triggers; - } handler_info; +trigger *t_new(trigger_type * ttype); +void t_free(trigger * t); +void t_add(trigger ** tlist, trigger * t); +/** add and handle triggers **/ - trigger *t_new(trigger_type * ttype); - void t_free(trigger * t); - void t_add(trigger ** tlist, trigger * t); - /** add and handle triggers **/ +/* add a trigger to a list of attributes */ +void add_trigger(struct attrib **ap, const char *eventname, +struct trigger *t); +void remove_triggers(struct attrib **ap, const char *eventname, + const trigger_type * tt); +struct trigger **get_triggers(struct attrib *ap, + const char *eventname); +/* calls handle() for each of these. e.g. used in timeout */ +void handle_event(struct attrib *attribs, const char *eventname, + void *data); - /* add a trigger to a list of attributes */ - void add_trigger(struct attrib **ap, const char *eventname, - struct trigger *t); - void remove_triggers(struct attrib **ap, const char *eventname, - const trigger_type * tt); - struct trigger **get_triggers(struct attrib *ap, - const char *eventname); - /* calls handle() for each of these. e.g. used in timeout */ - void handle_event(struct attrib *attribs, const char *eventname, - void *data); +/* functions for making complex triggers: */ +void free_triggers(trigger * triggers); /* release all these triggers */ +void write_triggers(struct storage *store, const trigger * t); +int read_triggers(struct gamedata *data, trigger ** tp); +int handle_triggers(trigger ** triggers, void *data); - /* functions for making complex triggers: */ - void free_triggers(trigger * triggers); /* release all these triggers */ - void write_triggers(struct storage *store, const trigger * t); - int read_triggers(struct gamedata *data, trigger ** tp); - int handle_triggers(trigger ** triggers, void *data); +extern struct attrib_type at_eventhandler; - extern struct attrib_type at_eventhandler; - -#ifdef __cplusplus -} -#endif -#endif +void dump_trigger(const trigger *t, int indent); diff --git a/src/kernel/save.c b/src/kernel/save.c index 2e9aa0915..7d864326b 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1827,7 +1827,6 @@ int read_game(gamedata *data) } log_debug("Done loading turn %d.", turn); - return 0; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index db60e7377..036df18b1 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1895,3 +1895,15 @@ void translate_orders(unit *u, const struct locale *lang, order **list, bool del po = &ord->next; } } + +void dump_unit(const unit *u) { + if (u) { + const attrib *a; + fprintf(stdout, "%s, %s, %d %s\n", unitname(u), factionname(u->faction), u->number, u->_race->_name); + for (a = u->attribs; a; a = a->next) { + dump_attrib(a); + } + } + else fputs("null", stdout); +} + diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 1a2531498..a027543e0 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -244,4 +244,6 @@ bool is_limited_skill(enum skill_t sk); bool unit_is_slaved(const struct unit *u); +void dump_unit(const struct unit *u); + #endif diff --git a/src/triggers/createcurse.c b/src/triggers/createcurse.c index bc12b640a..4a41ff94c 100644 --- a/src/triggers/createcurse.c +++ b/src/triggers/createcurse.c @@ -101,13 +101,23 @@ static int createcurse_read(trigger * t, gamedata *data) return AT_READ_OK; } +static void createcurse_dump(const trigger *t, int indent) +{ + createcurse_data *td = (createcurse_data *)t->data.v; + fprintf(stdout, "%*sduration: %d\n", indent, "", td->duration); + fprintf(stdout, "%*scurse: %s\n", indent, "", td->type->cname); + fprintf(stdout, "%*smage: %s\n", indent, "", unitname(td->mage)); + fprintf(stdout, "%*starget: %s\n", indent, "", unitname(td->target)); +} + trigger_type tt_createcurse = { "createcurse", createcurse_init, createcurse_free, createcurse_handle, createcurse_write, - createcurse_read + createcurse_read, + createcurse_dump }; trigger *trigger_createcurse(struct unit * mage, struct unit * target, diff --git a/src/triggers/timeout.c b/src/triggers/timeout.c index 148111dc3..3c5273916 100644 --- a/src/triggers/timeout.c +++ b/src/triggers/timeout.c @@ -65,13 +65,24 @@ static int timeout_read(trigger * t, gamedata *data) return AT_READ_FAIL; } +static void timeout_dump(const trigger *t, int indent) +{ + timeout_data *td = (timeout_data *)t->data.v; + trigger *tc; + fprintf(stdout, "%*stimer: %d\n", indent, "", td->timer); + for (tc = td->triggers; tc; tc = tc->next) { + dump_trigger(tc, indent); + } +} + trigger_type tt_timeout = { "timeout", timeout_init, timeout_free, timeout_handle, timeout_write, - timeout_read + timeout_read, + timeout_dump }; trigger *trigger_timeout(int time, trigger * callbacks) From 81f4bc2b5c79aa483d57ec0c84ab35320cb655d8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 10 Feb 2025 20:47:51 +0100 Subject: [PATCH 2/2] fix change_race --- src/kernel/event.c | 4 ---- src/magic.test.c | 10 +++++++++- src/spells.test.c | 6 +++--- src/triggers/changerace.c | 39 ++++++++++++++++++++++++--------------- src/triggers/changerace.h | 39 +++++++++++++++------------------------ 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/kernel/event.c b/src/kernel/event.c index bd2762106..051c6ac10 100644 --- a/src/kernel/event.c +++ b/src/kernel/event.c @@ -279,7 +279,3 @@ const trigger_type * tt) tp = &t->next; } } - -/*** - ** default events - **/ diff --git a/src/magic.test.c b/src/magic.test.c index 64fb2037a..83e9948bd 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -842,7 +842,7 @@ static void test_fumble_toad(CuTest *tc) { unit* u; struct race* rc_toad; const struct race* rc; - trigger* t; + trigger *t, *tr, **tlist; changerace_data* crd; test_setup(); @@ -850,6 +850,9 @@ static void test_fumble_toad(CuTest *tc) { CuAssertPtrEquals(tc, rc_toad, (race *)get_race(RC_TOAD)); u = test_create_unit(test_create_faction(), test_create_plain(0, 0)); + tr = trigger_timeout(10, trigger_timeout(0, NULL)); + add_trigger(&u->attribs, "timer", tr); + rc = u_race(u); fumble_toad(u, NULL, 6); CuAssertPtrEquals(tc, rc_toad, (race*)u_race(u)); @@ -857,6 +860,11 @@ static void test_fumble_toad(CuTest *tc) { CuAssertPtrNotNull(tc, crd = (changerace_data*)t->data.v); CuAssertPtrEquals(tc, (race*)rc, (race*)crd->race); CuAssertPtrEquals(tc, NULL, (race*)crd->irace); + tlist = get_triggers(u->attribs, "timer"); + CuAssertPtrNotNull(tc, tlist); + CuAssertPtrEquals(tc, tr, *tlist); + CuAssertPtrNotNull(tc, tr->next); + CuAssertPtrEquals(tc, &tt_timeout, tr->next->type); test_teardown(); } diff --git a/src/spells.test.c b/src/spells.test.c index db2474753..173474de8 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -146,13 +146,13 @@ static void test_change_race(CuTest* tc) { CuAssertPtrEquals(tc, (void*)u->faction->race, (void*)crd->race); CuAssertPtrEquals(tc, NULL, (void*)crd->irace); - /* change race, but do not add a second change_race trigger */ + /* change race, but do not add a second change_race timeout */ CuAssertPtrEquals(tc, tr, change_race(u, 2, rcsmurf, NULL)); + CuAssertPtrEquals(tc, (void *)rcsmurf, (void *)u->_race); + CuAssertPtrEquals(tc, NULL, (void *)u->irace); CuAssertPtrNotNull(tc, u->attribs); CuAssertPtrEquals(tc, NULL, u->attribs->next); CuAssertPtrEquals(tc, NULL, tr->next); - CuAssertPtrEquals(tc, (void*)rcsmurf, (void*)u->_race); - CuAssertPtrEquals(tc, NULL, (void*)u->irace); td = (timeout_data*)tr->data.v; CuAssertPtrNotNull(tc, td); CuAssertIntEquals(tc, 2, td->timer); diff --git a/src/triggers/changerace.c b/src/triggers/changerace.c index 6c02a605c..03e122fef 100644 --- a/src/triggers/changerace.c +++ b/src/triggers/changerace.c @@ -96,26 +96,35 @@ trigger *trigger_changerace(unit * u, const race * prace, const race * irace) } static struct trigger *change_race_i(struct unit *u, int duration, const struct race *rc, bool is_stealth) { - trigger **texists = get_triggers(u->attribs, "timer"); - trigger *tr = NULL; - - assert(rc); - if (texists) { - tr = *texists; + trigger *tr = NULL, *tt = NULL; + trigger **tp = get_triggers(u->attribs, "timer"); + if (tp) + { + while (*tp) { + trigger *t = *tp; + if (t->type == &tt_timeout) { + timeout_data *td = (timeout_data *)t->data.v; + for (tr = td->triggers; tr; tr = tr->next) { + if (tr->type == &tt_changerace) { + tt = t; /* return the old timeout, don't create a new one */ + break; + } + } + } + tp = &t->next; + } } - else { - trigger* trestore; + /* only add another change_race timeout if there wasn't one already (toad becomes smurf) */ + if (!tt) { if (is_stealth) { - trestore = trigger_changerace(u, NULL, u->irace); + tr = trigger_changerace(u, NULL, u->irace); } else { - trestore = trigger_changerace(u, u_race(u), u->irace); - } - if (trestore) { - tr = trigger_timeout(duration, trestore); + tr = trigger_changerace(u, u_race(u), u->irace); } if (tr) { - add_trigger(&u->attribs, "timer", tr); + tt = trigger_timeout(duration, tr); + add_trigger(&u->attribs, "timer", tt); } } if (tr) { @@ -127,7 +136,7 @@ static struct trigger *change_race_i(struct unit *u, int duration, const struct u->irace = NULL; } } - return tr; + return tt; } struct trigger* change_race(struct unit* u, int duration, const struct race* urace, const struct race* irace) { diff --git a/src/triggers/changerace.h b/src/triggers/changerace.h index 3bb60deba..124415037 100644 --- a/src/triggers/changerace.h +++ b/src/triggers/changerace.h @@ -1,28 +1,19 @@ -#ifndef CHANGERACE_H -#define CHANGERACE_H -#ifdef __cplusplus -extern "C" { -#endif +#pragma once - /* all types we use are defined here to reduce dependencies */ - struct trigger_type; - struct trigger; - struct unit; - struct race; +/* all types we use are defined here to reduce dependencies */ +struct trigger_type; +struct trigger; +struct unit; +struct race; - typedef struct changerace_data { - struct unit *u; - const struct race *race; - const struct race *irace; - } changerace_data; +typedef struct changerace_data { + struct unit *u; + const struct race *race; + const struct race *irace; +} changerace_data; - extern struct trigger_type tt_changerace; +extern struct trigger_type tt_changerace; - struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace); - void restore_race(struct unit *u, const struct race *rc); - struct trigger *get_change_race_trigger(struct unit *u); - -#ifdef __cplusplus -} -#endif -#endif +struct trigger *change_race(struct unit *u, int duration, const struct race *urace, const struct race *irace); +void restore_race(struct unit *u, const struct race *rc); +struct trigger *get_change_race_trigger(struct unit *u);