forked from github/server
Merge pull request #278 from ennorehling/feature/bug-2128-travelthru-split
Bug 2128: Durchreisemeldugnen im NR sind zu lang
This commit is contained in:
commit
e5ffd50b4f
|
@ -6947,14 +6947,9 @@
|
||||||
<text locale="en">is helping</text>
|
<text locale="en">is helping</text>
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="has_moved_one">
|
<string name="travelthru_header">
|
||||||
<text locale="de">hat die Region durchquert.</text>
|
<text locale="de">Die Region wurde durchquert von </text>
|
||||||
<text locale="en">passed through the region.</text>
|
<text locale="en">The region was crossed by </text>
|
||||||
</string>
|
|
||||||
|
|
||||||
<string name="has_moved_many">
|
|
||||||
<text locale="de">haben die Region durchquert.</text>
|
|
||||||
<text locale="en">passed through the region.</text>
|
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<string name="see_travel">
|
<string name="see_travel">
|
||||||
|
|
|
@ -108,6 +108,7 @@ set (ERESSEA_SRC
|
||||||
spy.c
|
spy.c
|
||||||
study.c
|
study.c
|
||||||
summary.c
|
summary.c
|
||||||
|
travelthru.c
|
||||||
monsters.c
|
monsters.c
|
||||||
wormhole.c
|
wormhole.c
|
||||||
${SPELLS_SRC}
|
${SPELLS_SRC}
|
||||||
|
@ -180,6 +181,7 @@ set(TESTS_SRC
|
||||||
vortex.test.c
|
vortex.test.c
|
||||||
tests.test.c
|
tests.test.c
|
||||||
reports.test.c
|
reports.test.c
|
||||||
|
travelthru.test.c
|
||||||
callback.test.c
|
callback.test.c
|
||||||
direction.test.c
|
direction.test.c
|
||||||
economy.test.c
|
economy.test.c
|
||||||
|
|
|
@ -11,6 +11,7 @@ without prior permission by the authors of Eressea.
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
#include "buildno.h"
|
#include "buildno.h"
|
||||||
#include "creport.h"
|
#include "creport.h"
|
||||||
|
#include "travelthru.h"
|
||||||
|
|
||||||
/* tweakable features */
|
/* tweakable features */
|
||||||
#define RENDER_CRMESSAGES
|
#define RENDER_CRMESSAGES
|
||||||
|
@ -1189,7 +1190,7 @@ static void
|
||||||
cr_output_resources(FILE * F, report_context * ctx, seen_region * sr)
|
cr_output_resources(FILE * F, report_context * ctx, seen_region * sr)
|
||||||
{
|
{
|
||||||
char cbuf[BUFFERSIZE], *pos = cbuf;
|
char cbuf[BUFFERSIZE], *pos = cbuf;
|
||||||
region *r = sr->r;
|
const region *r = sr->r;
|
||||||
faction *f = ctx->f;
|
faction *f = ctx->f;
|
||||||
resource_report result[MAX_RAWMATERIALS];
|
resource_report result[MAX_RAWMATERIALS];
|
||||||
int n, size = report_resources(sr, result, MAX_RAWMATERIALS, f);
|
int n, size = report_resources(sr, result, MAX_RAWMATERIALS, f);
|
||||||
|
@ -1235,6 +1236,49 @@ cr_region_header(FILE * F, int plid, int nx, int ny, int uid)
|
||||||
fprintf(F, "%d;id\n", uid);
|
fprintf(F, "%d;id\n", uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct travel_data {
|
||||||
|
const faction *f;
|
||||||
|
FILE *file;
|
||||||
|
int n;
|
||||||
|
} travel_data;
|
||||||
|
|
||||||
|
static void cb_cr_travelthru_ship(region *r, unit *u, void *cbdata) {
|
||||||
|
travel_data *data = (travel_data *)cbdata;
|
||||||
|
const faction *f = data->f;
|
||||||
|
FILE *F = data->file;
|
||||||
|
|
||||||
|
if (u->ship && travelthru_cansee(r, f, u)) {
|
||||||
|
if (data->n++ == 0) {
|
||||||
|
fprintf(F, "DURCHSCHIFFUNG\n");
|
||||||
|
}
|
||||||
|
fprintf(F, "\"%s\"\n", shipname(u->ship));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_cr_travelthru_unit(region *r, unit *u, void *cbdata) {
|
||||||
|
travel_data *data = (travel_data *)cbdata;
|
||||||
|
const faction *f = data->f;
|
||||||
|
FILE *F = data->file;
|
||||||
|
|
||||||
|
if (!u->ship && travelthru_cansee(r, f, u)) {
|
||||||
|
if (data->n++ == 0) {
|
||||||
|
fprintf(F, "DURCHREISE\n");
|
||||||
|
}
|
||||||
|
fprintf(F, "\"%s\"\n", unitname(u));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cr_output_travelthru(FILE *F, region *r, const faction *f) {
|
||||||
|
/* describe both passed and inhabited regions */
|
||||||
|
travel_data cbdata = { 0 };
|
||||||
|
cbdata.f = f;
|
||||||
|
cbdata.file = F;
|
||||||
|
cbdata.n = 0;
|
||||||
|
travelthru_map(r, cb_cr_travelthru_ship, &cbdata);
|
||||||
|
cbdata.n = 0;
|
||||||
|
travelthru_map(r, cb_cr_travelthru_unit, &cbdata);
|
||||||
|
}
|
||||||
|
|
||||||
static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
|
static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
|
||||||
{
|
{
|
||||||
faction *f = ctx->f;
|
faction *f = ctx->f;
|
||||||
|
@ -1409,38 +1453,7 @@ static void cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* describe both passed and inhabited regions */
|
cr_output_travelthru(F, r, f);
|
||||||
if (fval(r, RF_TRAVELUNIT)) {
|
|
||||||
bool seeunits = false, seeships = false;
|
|
||||||
const attrib *ru;
|
|
||||||
/* show units pulled through region */
|
|
||||||
for (ru = a_find(r->attribs, &at_travelunit);
|
|
||||||
ru && ru->type == &at_travelunit; ru = ru->next) {
|
|
||||||
unit *u = (unit *)ru->data.v;
|
|
||||||
if (cansee_durchgezogen(f, r, u, 0) && r != u->region) {
|
|
||||||
if (u->ship && ship_owner(u->ship) == u) {
|
|
||||||
if (!seeships) {
|
|
||||||
fprintf(F, "DURCHSCHIFFUNG\n");
|
|
||||||
}
|
|
||||||
seeships = true;
|
|
||||||
fprintf(F, "\"%s\"\n", shipname(u->ship));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ru = a_find(r->attribs, &at_travelunit);
|
|
||||||
ru && ru->type == &at_travelunit; ru = ru->next) {
|
|
||||||
unit *u = (unit *)ru->data.v;
|
|
||||||
if (cansee_durchgezogen(f, r, u, 0) && r != u->region) {
|
|
||||||
if (!u->ship) {
|
|
||||||
if (!seeunits) {
|
|
||||||
fprintf(F, "DURCHREISE\n");
|
|
||||||
}
|
|
||||||
seeunits = true;
|
|
||||||
fprintf(F, "\"%s\"\n", unitname(u));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sr->mode == see_unit || sr->mode == see_travel) {
|
if (sr->mode == see_unit || sr->mode == see_travel) {
|
||||||
message_list *mlist = r_getmessages(r, f);
|
message_list *mlist = r_getmessages(r, f);
|
||||||
cr_output_messages(F, r->msgs, f);
|
cr_output_messages(F, r->msgs, f);
|
||||||
|
|
|
@ -525,18 +525,6 @@ attrib_type at_woodcount = {
|
||||||
ATF_UNIQUE
|
ATF_UNIQUE
|
||||||
};
|
};
|
||||||
|
|
||||||
/*********************/
|
|
||||||
/* at_travelunit */
|
|
||||||
/*********************/
|
|
||||||
attrib_type at_travelunit = {
|
|
||||||
"travelunit",
|
|
||||||
DEFAULT_INIT,
|
|
||||||
DEFAULT_FINALIZE,
|
|
||||||
DEFAULT_AGE,
|
|
||||||
NO_WRITE,
|
|
||||||
NO_READ
|
|
||||||
};
|
|
||||||
|
|
||||||
void rsetroad(region * r, direction_t d, int val)
|
void rsetroad(region * r, direction_t d, int val)
|
||||||
{
|
{
|
||||||
connection *b;
|
connection *b;
|
||||||
|
|
|
@ -169,7 +169,6 @@ extern "C" {
|
||||||
extern struct attrib_type at_horseluck;
|
extern struct attrib_type at_horseluck;
|
||||||
extern struct attrib_type at_woodcount;
|
extern struct attrib_type at_woodcount;
|
||||||
extern struct attrib_type at_deathcount;
|
extern struct attrib_type at_deathcount;
|
||||||
extern struct attrib_type at_travelunit;
|
|
||||||
|
|
||||||
void initrhash(void);
|
void initrhash(void);
|
||||||
void rhash(struct region *r);
|
void rhash(struct region *r);
|
||||||
|
|
28
src/move.c
28
src/move.c
|
@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
#include "alchemy.h"
|
#include "alchemy.h"
|
||||||
|
#include "travelthru.h"
|
||||||
#include "vortex.h"
|
#include "vortex.h"
|
||||||
#include "monster.h"
|
#include "monster.h"
|
||||||
#include "lighthouse.h"
|
#include "lighthouse.h"
|
||||||
|
@ -501,29 +502,6 @@ static ship *do_maelstrom(region * r, unit * u)
|
||||||
return u->ship;
|
return u->ship;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** sets a marker in the region telling that the unit has travelled through it
|
|
||||||
* this is used for two distinctly different purposes:
|
|
||||||
* - to report that a unit has travelled through. the report function
|
|
||||||
* makes sure to only report the ships of travellers, not the travellers
|
|
||||||
* themselves
|
|
||||||
* - to report the region to the traveller
|
|
||||||
*/
|
|
||||||
void travelthru(const unit * u, region * r)
|
|
||||||
{
|
|
||||||
attrib *ru = a_add(&r->attribs, a_new(&at_travelunit));
|
|
||||||
|
|
||||||
fset(r, RF_TRAVELUNIT);
|
|
||||||
|
|
||||||
ru->data.v = (void *)u;
|
|
||||||
|
|
||||||
/* the first and last region of the faction gets reset, because travelthrough
|
|
||||||
* could be in regions that are located before the [first, last] interval,
|
|
||||||
* and recalculation is needed */
|
|
||||||
#ifdef SMART_INTERVALS
|
|
||||||
update_interval(u->faction, r);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static direction_t
|
static direction_t
|
||||||
koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl)
|
koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl)
|
||||||
{
|
{
|
||||||
|
@ -589,12 +567,12 @@ static void leave_trail(ship * sh, region * from, region_list * route)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mark_travelthru(const unit * u, region * r, const region_list * route,
|
mark_travelthru(unit * u, region * r, const region_list * route,
|
||||||
const region_list * route_end)
|
const region_list * route_end)
|
||||||
{
|
{
|
||||||
/* kein travelthru in der letzten region! */
|
/* kein travelthru in der letzten region! */
|
||||||
while (route != route_end) {
|
while (route != route_end) {
|
||||||
travelthru(u, r);
|
travelthru_add(r, u);
|
||||||
r = route->data;
|
r = route->data;
|
||||||
route = route->next;
|
route = route->next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,6 @@ extern "C" {
|
||||||
int enoughsailors(const struct ship *sh, int sumskill);
|
int enoughsailors(const struct ship *sh, int sumskill);
|
||||||
bool canswim(struct unit *u);
|
bool canswim(struct unit *u);
|
||||||
bool canfly(struct unit *u);
|
bool canfly(struct unit *u);
|
||||||
void travelthru(const struct unit *u, struct region *r);
|
|
||||||
struct ship *move_ship(struct ship *sh, struct region *from,
|
struct ship *move_ship(struct ship *sh, struct region *from,
|
||||||
struct region *to, struct region_list *route);
|
struct region *to, struct region_list *route);
|
||||||
int walkingcapacity(const struct unit *u);
|
int walkingcapacity(const struct unit *u);
|
||||||
|
|
196
src/report.c
196
src/report.c
|
@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
|
#include "travelthru.h"
|
||||||
#include "monster.h"
|
#include "monster.h"
|
||||||
|
|
||||||
/* modules includes */
|
/* modules includes */
|
||||||
|
@ -140,6 +141,7 @@ void write_spaces(stream *out, size_t num) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void centre(stream *out, const char *s, bool breaking)
|
static void centre(stream *out, const char *s, bool breaking)
|
||||||
{
|
{
|
||||||
/* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme
|
/* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme
|
||||||
|
@ -183,7 +185,7 @@ char marker)
|
||||||
str = x + 2;
|
str = x + 2;
|
||||||
hanging_indent -= 2;
|
hanging_indent -= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mark = ▮
|
mark = ▮
|
||||||
}
|
}
|
||||||
|
@ -1344,85 +1346,6 @@ static void statistics(stream *out, const region * r, const faction * f)
|
||||||
i_free(i_remove(&items, items));
|
i_free(i_remove(&items, items));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void durchreisende(stream *out, const region * r, const faction * f)
|
|
||||||
{
|
|
||||||
if (fval(r, RF_TRAVELUNIT)) {
|
|
||||||
attrib *abegin = a_find(r->attribs, &at_travelunit), *a;
|
|
||||||
int counter = 0, maxtravel = 0;
|
|
||||||
char buf[8192];
|
|
||||||
char *bufp = buf;
|
|
||||||
int bytes;
|
|
||||||
size_t size = sizeof(buf) - 1;
|
|
||||||
|
|
||||||
/* How many are we listing? For grammar. */
|
|
||||||
for (a = abegin; a && a->type == &at_travelunit; a = a->next) {
|
|
||||||
unit *u = (unit *)a->data.v;
|
|
||||||
|
|
||||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
|
||||||
if (cansee_durchgezogen(f, r, u, 0)) {
|
|
||||||
++maxtravel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxtravel == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Auflisten. */
|
|
||||||
newline(out);
|
|
||||||
|
|
||||||
for (a = abegin; a && a->type == &at_travelunit; a = a->next) {
|
|
||||||
unit *u = (unit *)a->data.v;
|
|
||||||
|
|
||||||
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
|
||||||
if (cansee_durchgezogen(f, r, u, 0)) {
|
|
||||||
++counter;
|
|
||||||
if (u->ship != NULL) {
|
|
||||||
bytes = (int)strlcpy(bufp, shipname(u->ship), size);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bytes = (int)strlcpy(bufp, unitname(u), size);
|
|
||||||
}
|
|
||||||
if (wrptr(&bufp, &size, bytes) != 0) {
|
|
||||||
INFO_STATIC_BUFFER();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter + 1 < maxtravel) {
|
|
||||||
bytes = (int)strlcpy(bufp, ", ", size);
|
|
||||||
if (wrptr(&bufp, &size, bytes) != 0) {
|
|
||||||
INFO_STATIC_BUFFER();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (counter + 1 == maxtravel) {
|
|
||||||
bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size);
|
|
||||||
if (wrptr(&bufp, &size, bytes) != 0) {
|
|
||||||
INFO_STATIC_BUFFER();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (size > 0) {
|
|
||||||
CHECK_ERRNO();
|
|
||||||
if (maxtravel == 1) {
|
|
||||||
bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_many"));
|
|
||||||
}
|
|
||||||
CHECK_ERRNO();
|
|
||||||
if (wrptr(&bufp, &size, bytes) != 0)
|
|
||||||
WARN_STATIC_BUFFER_EX("durchreisende");
|
|
||||||
CHECK_ERRNO();
|
|
||||||
}
|
|
||||||
*bufp = 0;
|
|
||||||
paragraph(out, buf, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int buildingmaintenance(const building * b, const resource_type * rtype)
|
static int buildingmaintenance(const building * b, const resource_type * rtype)
|
||||||
{
|
{
|
||||||
|
@ -2007,6 +1930,104 @@ static void nr_paragraph(stream *out, message * m, faction * f)
|
||||||
paragraph(out, buf, 0, 0, 0);
|
paragraph(out, buf, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct cb_data {
|
||||||
|
stream *out;
|
||||||
|
char *start, *writep;
|
||||||
|
size_t size;
|
||||||
|
const faction *f;
|
||||||
|
int maxtravel, counter;
|
||||||
|
} cb_data;
|
||||||
|
|
||||||
|
static void init_cb(cb_data *data, stream *out, char *buffer, size_t size, const faction *f) {
|
||||||
|
data->out = out;
|
||||||
|
data->writep = buffer;
|
||||||
|
data->start = buffer;
|
||||||
|
data->size = size;
|
||||||
|
data->f = f;
|
||||||
|
data->maxtravel = 0;
|
||||||
|
data->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_write_travelthru(region *r, unit *u, void *cbdata) {
|
||||||
|
cb_data *data = (cb_data *)cbdata;
|
||||||
|
const faction *f = data->f;
|
||||||
|
|
||||||
|
if (data->counter >= data->maxtravel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (travelthru_cansee(r, f, u)) {
|
||||||
|
++data->counter;
|
||||||
|
do {
|
||||||
|
size_t len, size = data->size - (data->writep - data->start);
|
||||||
|
const char *str;
|
||||||
|
char *writep = data->writep;
|
||||||
|
|
||||||
|
if (u->ship != NULL) {
|
||||||
|
str = shipname(u->ship);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = unitname(u);
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
if (len < size && data->counter <= data->maxtravel) {
|
||||||
|
memcpy(writep, str, len);
|
||||||
|
writep += len;
|
||||||
|
size -= len;
|
||||||
|
if (data->counter == data->maxtravel) {
|
||||||
|
str = ".";
|
||||||
|
}
|
||||||
|
else if (data->counter + 1 == data->maxtravel) {
|
||||||
|
str = LOC(f->locale, "list_and");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = ", ";
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
if (len < size) {
|
||||||
|
memcpy(writep, str, len);
|
||||||
|
writep += len;
|
||||||
|
size -= len;
|
||||||
|
data->writep = writep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len >= size || data->counter == data->maxtravel) {
|
||||||
|
// buffer is full
|
||||||
|
*writep = 0;
|
||||||
|
paragraph(data->out, data->start, 0, 0, 0);
|
||||||
|
data->writep = data->start;
|
||||||
|
if (data->counter == data->maxtravel) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (data->writep == data->start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_travelthru(stream *out, region * r, const faction * f)
|
||||||
|
{
|
||||||
|
int maxtravel;
|
||||||
|
char buf[8192];
|
||||||
|
|
||||||
|
assert(r);
|
||||||
|
assert(f);
|
||||||
|
if (!fval(r, RF_TRAVELUNIT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* How many are we listing? For grammar. */
|
||||||
|
maxtravel = count_travelthru(r, f);
|
||||||
|
if (maxtravel > 0) {
|
||||||
|
cb_data cbdata;
|
||||||
|
|
||||||
|
init_cb(&cbdata, out, buf, sizeof(buf), f);
|
||||||
|
cbdata.maxtravel = maxtravel;
|
||||||
|
cbdata.writep +=
|
||||||
|
strlcpy(buf, LOC(f->locale, "travelthru_header"), sizeof(buf));
|
||||||
|
travelthru_map(r, cb_write_travelthru, &cbdata);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
report_plaintext(const char *filename, report_context * ctx,
|
report_plaintext(const char *filename, report_context * ctx,
|
||||||
const char *charset)
|
const char *charset)
|
||||||
|
@ -2118,7 +2139,7 @@ const char *charset)
|
||||||
}
|
}
|
||||||
if (no_people != f->num_people) {
|
if (no_people != f->num_people) {
|
||||||
f->num_people = no_people;
|
f->num_people = no_people;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
no_units = count_units(f);
|
no_units = count_units(f);
|
||||||
no_people = count_all(f);
|
no_people = count_all(f);
|
||||||
|
@ -2325,21 +2346,26 @@ const char *charset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
guards(out, r, f);
|
guards(out, r, f);
|
||||||
durchreisende(out, r, f);
|
newline(out);
|
||||||
|
write_travelthru(out, r, f);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (sr->mode == see_far) {
|
if (sr->mode == see_far) {
|
||||||
describe(out, sr, f);
|
describe(out, sr, f);
|
||||||
|
newline(out);
|
||||||
guards(out, r, f);
|
guards(out, r, f);
|
||||||
durchreisende(out, r, f);
|
newline(out);
|
||||||
|
write_travelthru(out, r, f);
|
||||||
}
|
}
|
||||||
else if (sr->mode == see_lighthouse) {
|
else if (sr->mode == see_lighthouse) {
|
||||||
describe(out, sr, f);
|
describe(out, sr, f);
|
||||||
durchreisende(out, r, f);
|
newline(out);
|
||||||
|
write_travelthru(out, r, f);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
describe(out, sr, f);
|
describe(out, sr, f);
|
||||||
durchreisende(out, r, f);
|
newline(out);
|
||||||
|
write_travelthru(out, r, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Statistik */
|
/* Statistik */
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#pragma once
|
||||||
/*
|
/*
|
||||||
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
|
||||||
| | Enno Rehling <enno@eressea.de>
|
| | Enno Rehling <enno@eressea.de>
|
||||||
|
@ -11,15 +12,20 @@
|
||||||
*/
|
*/
|
||||||
#ifndef H_GC_REPORT
|
#ifndef H_GC_REPORT
|
||||||
#define H_GC_REPORT
|
#define H_GC_REPORT
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct stream;
|
struct stream;
|
||||||
|
struct region;
|
||||||
|
struct faction;
|
||||||
void register_nr(void);
|
void register_nr(void);
|
||||||
void report_cleanup(void);
|
void report_cleanup(void);
|
||||||
void write_spaces(struct stream *out, size_t num);
|
void write_spaces(struct stream *out, size_t num);
|
||||||
|
void write_travelthru(struct stream *out, const struct region * r, const struct faction * f);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
113
src/reports.c
113
src/reports.c
|
@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
#include "laws.h"
|
#include "laws.h"
|
||||||
|
#include "travelthru.h"
|
||||||
#include "lighthouse.h"
|
#include "lighthouse.h"
|
||||||
|
|
||||||
/* kernel includes */
|
/* kernel includes */
|
||||||
|
@ -981,6 +982,38 @@ void add_seen_faction(faction *self, faction *seen) {
|
||||||
add_seen_faction_i(&self->seen_factions, seen);
|
add_seen_faction_i(&self->seen_factions, seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct address_data {
|
||||||
|
faction *f, *lastf;
|
||||||
|
quicklist **flist;
|
||||||
|
int stealthmod;
|
||||||
|
} address_data;
|
||||||
|
|
||||||
|
static void cb_add_address(region *r, unit *ut, void *cbdata) {
|
||||||
|
address_data *data = (address_data *)cbdata;
|
||||||
|
faction *f = data->f;
|
||||||
|
|
||||||
|
if (ut->faction==f) {
|
||||||
|
unit *u;
|
||||||
|
for (u = r->units; u; u = u->next) {
|
||||||
|
faction *sf = visible_faction(f, u);
|
||||||
|
assert(u->faction != f); /* if this is see_travel only, then I shouldn't be here. */
|
||||||
|
if (data->lastf != sf && cansee_unit(u, ut, data->stealthmod)) {
|
||||||
|
add_seen_faction_i(data->flist, sf);
|
||||||
|
data->lastf = sf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_travelthru_addresses(region *r, faction *f, quicklist **flist, int stealthmod) {
|
||||||
|
// for each traveling unit: add the faction of any unit is can see
|
||||||
|
address_data cbdata = { 0 };
|
||||||
|
cbdata.f = f;
|
||||||
|
cbdata.flist = flist;
|
||||||
|
cbdata.stealthmod = stealthmod;
|
||||||
|
travelthru_map(r, cb_add_address, &cbdata);
|
||||||
|
}
|
||||||
|
|
||||||
static void get_addresses(report_context * ctx)
|
static void get_addresses(report_context * ctx)
|
||||||
{
|
{
|
||||||
|
@ -1025,26 +1058,9 @@ static void get_addresses(report_context * ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sr->mode == see_travel) {
|
else if (sr->mode == see_travel) {
|
||||||
unit *u = r->units;
|
/* when we travel through a region, then we must add
|
||||||
while (u) {
|
* the factions of any units we saw */
|
||||||
faction *sf = visible_faction(ctx->f, u);
|
add_travelthru_addresses(r, ctx->f, &flist, stealthmod);
|
||||||
assert(u->faction != ctx->f); /* if this is see_travel only, then I shouldn't be here. */
|
|
||||||
if (lastf != sf) {
|
|
||||||
attrib *a = a_find(r->attribs, &at_travelunit);
|
|
||||||
while (a && a->type == &at_travelunit) {
|
|
||||||
unit *u2 = (unit *)a->data.v;
|
|
||||||
if (u2->faction == ctx->f) {
|
|
||||||
if (cansee_unit(u2, u, stealthmod)) {
|
|
||||||
add_seen_faction_i(&flist, sf);
|
|
||||||
lastf = sf;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a = a->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u = u->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (sr->mode > see_travel) {
|
else if (sr->mode > see_travel) {
|
||||||
const unit *u = r->units;
|
const unit *u = r->units;
|
||||||
|
@ -1465,6 +1481,13 @@ void reorder_units(region * r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cb_add_seen(region *r, unit *u, void *cbdata) {
|
||||||
|
unused_arg(cbdata);
|
||||||
|
if (u->faction) {
|
||||||
|
add_seen(u->faction->seen, r, see_travel, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void prepare_reports(void)
|
static void prepare_reports(void)
|
||||||
{
|
{
|
||||||
region *r;
|
region *r;
|
||||||
|
@ -1478,7 +1501,6 @@ static void prepare_reports(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (r = regions; r; r = r->next) {
|
for (r = regions; r; r = r->next) {
|
||||||
attrib *ru;
|
|
||||||
unit *u;
|
unit *u;
|
||||||
plane *p = rplane(r);
|
plane *p = rplane(r);
|
||||||
|
|
||||||
|
@ -1532,19 +1554,18 @@ static void prepare_reports(void)
|
||||||
|
|
||||||
|
|
||||||
if (fval(r, RF_TRAVELUNIT)) {
|
if (fval(r, RF_TRAVELUNIT)) {
|
||||||
for (ru = a_find(r->attribs, &at_travelunit);
|
travelthru_map(r, cb_add_seen, r);
|
||||||
ru && ru->type == &at_travelunit; ru = ru->next) {
|
|
||||||
unit *u = (unit *)ru->data.v;
|
|
||||||
|
|
||||||
/* make sure the faction has not been removed this turn: */
|
|
||||||
if (u->faction) {
|
|
||||||
add_seen(u->faction->seen, r, see_travel, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cb_set_last(region *r, unit *u, void *cbdata) {
|
||||||
|
faction *f = (faction *)cbdata;
|
||||||
|
if (u->faction == f) {
|
||||||
|
f->last = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static region *lastregion(faction * f)
|
static region *lastregion(faction * f)
|
||||||
{
|
{
|
||||||
#ifdef SMART_INTERVALS
|
#ifdef SMART_INTERVALS
|
||||||
|
@ -1571,15 +1592,7 @@ static region *lastregion(faction * f)
|
||||||
|
|
||||||
/* search the region for travelthru-attributes: */
|
/* search the region for travelthru-attributes: */
|
||||||
if (fval(r, RF_TRAVELUNIT)) {
|
if (fval(r, RF_TRAVELUNIT)) {
|
||||||
attrib *ru = a_find(r->attribs, &at_travelunit);
|
travelthru_map(r, cb_set_last, f);
|
||||||
while (ru && ru->type == &at_travelunit) {
|
|
||||||
u = (unit *)ru->data.v;
|
|
||||||
if (u->faction == f) {
|
|
||||||
f->last = r;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ru = ru->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (f->last == r)
|
if (f->last == r)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2378,6 +2391,28 @@ int stream_printf(struct stream * out, const char *format, ...) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct count_data {
|
||||||
|
int n;
|
||||||
|
const struct faction *f;
|
||||||
|
} count_data;
|
||||||
|
|
||||||
|
static void count_cb(region *r, unit *u, void *cbdata) {
|
||||||
|
count_data *data = (count_data *)cbdata;
|
||||||
|
const struct faction *f = data->f;
|
||||||
|
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||||
|
if (cansee_durchgezogen(f, r, u, 0)) {
|
||||||
|
++data->n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_travelthru(struct region *r, const struct faction *f) {
|
||||||
|
count_data data = { 0 };
|
||||||
|
data.f = f;
|
||||||
|
travelthru_map(r, count_cb, &data);
|
||||||
|
return data.n;
|
||||||
|
}
|
||||||
|
|
||||||
void register_reports(void)
|
void register_reports(void)
|
||||||
{
|
{
|
||||||
/* register datatypes for the different message objects */
|
/* register datatypes for the different message objects */
|
||||||
|
|
|
@ -157,6 +157,8 @@ extern "C" {
|
||||||
|
|
||||||
int stream_printf(struct stream * out, const char *format, ...);
|
int stream_printf(struct stream * out, const char *format, ...);
|
||||||
|
|
||||||
|
int count_travelthru(struct region *r, const struct faction *f);
|
||||||
|
|
||||||
#define GR_PLURAL 0x01 /* grammar: plural */
|
#define GR_PLURAL 0x01 /* grammar: plural */
|
||||||
#define MAX_INVENTORY 128 /* maimum number of different items in an inventory */
|
#define MAX_INVENTORY 128 /* maimum number of different items in an inventory */
|
||||||
#define MAX_RAWMATERIALS 8 /* maximum kinds of raw materials in a regions */
|
#define MAX_RAWMATERIALS 8 /* maximum kinds of raw materials in a regions */
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "reports.h"
|
#include "reports.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "creport.h"
|
#include "creport.h"
|
||||||
|
#include "move.h"
|
||||||
|
#include "travelthru.h"
|
||||||
|
|
||||||
#include <kernel/building.h>
|
#include <kernel/building.h>
|
||||||
#include <kernel/faction.h>
|
#include <kernel/faction.h>
|
||||||
|
@ -11,6 +13,8 @@
|
||||||
#include <kernel/ship.h>
|
#include <kernel/ship.h>
|
||||||
#include <kernel/unit.h>
|
#include <kernel/unit.h>
|
||||||
|
|
||||||
|
#include <util/language.h>
|
||||||
|
|
||||||
#include <quicklist.h>
|
#include <quicklist.h>
|
||||||
#include <stream.h>
|
#include <stream.h>
|
||||||
#include <memstream.h>
|
#include <memstream.h>
|
||||||
|
@ -178,6 +182,53 @@ static void test_cr_unit(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_write_travelthru(CuTest *tc) {
|
||||||
|
stream out = { 0 };
|
||||||
|
char buf[1024];
|
||||||
|
size_t len;
|
||||||
|
region *r;
|
||||||
|
faction *f;
|
||||||
|
unit *u;
|
||||||
|
struct locale *lang;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
lang = get_or_create_locale("de");
|
||||||
|
locale_setstring(lang, "travelthru_header", "Durchreise: ");
|
||||||
|
mstream_init(&out);
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
r->flags |= RF_TRAVELUNIT;
|
||||||
|
f = test_create_faction(0);
|
||||||
|
f->locale = lang;
|
||||||
|
u = test_create_unit(f, 0);
|
||||||
|
unit_setname(u, "Hodor");
|
||||||
|
unit_setid(u, 1);
|
||||||
|
|
||||||
|
write_travelthru(&out, r, f);
|
||||||
|
out.api->rewind(out.handle);
|
||||||
|
len = out.api->read(out.handle, buf, sizeof(buf));
|
||||||
|
CuAssertIntEquals_Msg(tc, "no travelers, no report", 0, (int)len);
|
||||||
|
mstream_done(&out);
|
||||||
|
|
||||||
|
mstream_init(&out);
|
||||||
|
travelthru_add(r, u);
|
||||||
|
write_travelthru(&out, r, f);
|
||||||
|
out.api->rewind(out.handle);
|
||||||
|
len = out.api->read(out.handle, buf, sizeof(buf));
|
||||||
|
buf[len] = '\0';
|
||||||
|
CuAssertStrEquals_Msg(tc, "list one unit", "Durchreise: Hodor (1).\n", buf);
|
||||||
|
mstream_done(&out);
|
||||||
|
|
||||||
|
mstream_init(&out);
|
||||||
|
move_unit(u, r, 0);
|
||||||
|
write_travelthru(&out, r, f);
|
||||||
|
out.api->rewind(out.handle);
|
||||||
|
len = out.api->read(out.handle, buf, sizeof(buf));
|
||||||
|
CuAssertIntEquals_Msg(tc, "do not list units that stopped in the region", 0, (int)len);
|
||||||
|
|
||||||
|
mstream_done(&out);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_reports_suite(void)
|
CuSuite *get_reports_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -188,5 +239,6 @@ CuSuite *get_reports_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_write_spaces);
|
SUITE_ADD_TEST(suite, test_write_spaces);
|
||||||
SUITE_ADD_TEST(suite, test_write_many_spaces);
|
SUITE_ADD_TEST(suite, test_write_many_spaces);
|
||||||
SUITE_ADD_TEST(suite, test_sparagraph);
|
SUITE_ADD_TEST(suite, test_sparagraph);
|
||||||
|
SUITE_ADD_TEST(suite, test_write_travelthru);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ int RunAllTests(void)
|
||||||
RUN_TESTS(suite, messages);
|
RUN_TESTS(suite, messages);
|
||||||
/* gamecode */
|
/* gamecode */
|
||||||
RUN_TESTS(suite, battle);
|
RUN_TESTS(suite, battle);
|
||||||
|
RUN_TESTS(suite, travelthru);
|
||||||
RUN_TESTS(suite, economy);
|
RUN_TESTS(suite, economy);
|
||||||
RUN_TESTS(suite, give);
|
RUN_TESTS(suite, give);
|
||||||
RUN_TESTS(suite, laws);
|
RUN_TESTS(suite, laws);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -85,6 +86,11 @@ void test_cleanup(void)
|
||||||
mt_register(mt_new_va("missing_message", "name:string", 0));
|
mt_register(mt_new_va("missing_message", "name:string", 0));
|
||||||
mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0));
|
mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0));
|
||||||
}
|
}
|
||||||
|
if (errno) {
|
||||||
|
int error = errno;
|
||||||
|
errno = 0;
|
||||||
|
log_error("errno: %d", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terrain_type *
|
terrain_type *
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.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
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
#include <kernel/config.h>
|
||||||
|
|
||||||
|
#include "travelthru.h"
|
||||||
|
#include "laws.h"
|
||||||
|
#include "report.h"
|
||||||
|
|
||||||
|
#include <kernel/unit.h>
|
||||||
|
#include <kernel/ship.h>
|
||||||
|
#include <kernel/region.h>
|
||||||
|
#include <kernel/faction.h>
|
||||||
|
#include <util/attrib.h>
|
||||||
|
#include <util/bsdstring.h>
|
||||||
|
#include <util/log.h>
|
||||||
|
#include <util/language.h>
|
||||||
|
|
||||||
|
#include <stream.h>
|
||||||
|
#include <quicklist.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*********************/
|
||||||
|
/* at_travelunit */
|
||||||
|
/*********************/
|
||||||
|
attrib_type at_travelunit = {
|
||||||
|
"travelunit",
|
||||||
|
DEFAULT_INIT,
|
||||||
|
DEFAULT_FINALIZE,
|
||||||
|
DEFAULT_AGE,
|
||||||
|
NO_WRITE,
|
||||||
|
NO_READ
|
||||||
|
};
|
||||||
|
|
||||||
|
/** sets a marker in the region telling that the unit has travelled through it
|
||||||
|
* this is used for two distinctly different purposes:
|
||||||
|
* - to report that a unit has travelled through. the report function
|
||||||
|
* makes sure to only report the ships of travellers, not the travellers
|
||||||
|
* themselves
|
||||||
|
* - to report the region to the traveller
|
||||||
|
*/
|
||||||
|
void travelthru_add(region * r, unit * u)
|
||||||
|
{
|
||||||
|
attrib *a;
|
||||||
|
quicklist *ql;
|
||||||
|
|
||||||
|
assert(r);
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
a = a_find(r->attribs, &at_travelunit);
|
||||||
|
if (!a) {
|
||||||
|
a = a_add(&r->attribs, a_new(&at_travelunit));
|
||||||
|
}
|
||||||
|
ql = (quicklist *)a->data.v;
|
||||||
|
|
||||||
|
fset(r, RF_TRAVELUNIT);
|
||||||
|
ql_push(&ql, u);
|
||||||
|
a->data.v = ql;
|
||||||
|
|
||||||
|
#ifdef SMART_INTERVALS
|
||||||
|
/* the first and last region of the faction gets reset, because travelthrough
|
||||||
|
* could be in regions that are located before the [first, last] interval,
|
||||||
|
* and recalculation is needed */
|
||||||
|
update_interval(u->faction, r);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u) {
|
||||||
|
if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) {
|
||||||
|
return cansee_durchgezogen(f, r, u, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void travelthru_map(region * r, void(*cb)(region *, struct unit *, void *), void *cbdata)
|
||||||
|
{
|
||||||
|
attrib *a;
|
||||||
|
assert(r);
|
||||||
|
a = a_find(r->attribs, &at_travelunit);
|
||||||
|
if (a) {
|
||||||
|
quicklist *ql;
|
||||||
|
ql_iter qi;
|
||||||
|
ql = (quicklist *)a->data.v;
|
||||||
|
for (qi = qli_init(&ql); qli_more(qi);) {
|
||||||
|
unit *u = (unit *)qli_next(&qi);
|
||||||
|
cb(r, u, cbdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef H_TRAVELTHRU
|
||||||
|
#define H_TRAVELTHRU
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct attrib;
|
||||||
|
struct stream;
|
||||||
|
struct region;
|
||||||
|
struct faction;
|
||||||
|
struct unit;
|
||||||
|
void travelthru_map(struct region * r, void(*cb)(struct region *r, struct unit *, void *), void *cbdata);
|
||||||
|
bool travelthru_cansee(const struct region *r, const struct faction *f, const struct unit *u);
|
||||||
|
void travelthru_add(struct region * r, struct unit * u);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include <platform.h>
|
||||||
|
#include <kernel/config.h>
|
||||||
|
#include <kernel/region.h>
|
||||||
|
#include <kernel/unit.h>
|
||||||
|
#include <kernel/faction.h>
|
||||||
|
#include <util/attrib.h>
|
||||||
|
|
||||||
|
#include "travelthru.h"
|
||||||
|
#include "reports.h"
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
#include <CuTest.h>
|
||||||
|
|
||||||
|
struct attrib;
|
||||||
|
|
||||||
|
static void count_travelers(region *r, unit *u, void *cbdata) {
|
||||||
|
int *n = (int *)cbdata;
|
||||||
|
unused_arg(r);
|
||||||
|
*n += u->number;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct travel_fixture {
|
||||||
|
region *r;
|
||||||
|
faction *f;
|
||||||
|
} travel_fixture;
|
||||||
|
|
||||||
|
static void setup_travelthru(travel_fixture *fix, int nunits) {
|
||||||
|
region *r;
|
||||||
|
faction *f;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
r = test_create_region(0, 0, 0);
|
||||||
|
while (r->attribs) {
|
||||||
|
a_remove(&r->attribs, r->attribs);
|
||||||
|
}
|
||||||
|
f = test_create_faction(0);
|
||||||
|
while (nunits--) {
|
||||||
|
unit *u = test_create_unit(f, 0);
|
||||||
|
travelthru_add(r, u);
|
||||||
|
}
|
||||||
|
fix->r = r;
|
||||||
|
fix->f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_travelthru_count(CuTest *tc) {
|
||||||
|
travel_fixture fix;
|
||||||
|
setup_travelthru(&fix, 0);
|
||||||
|
CuAssertIntEquals(tc, 0, count_travelthru(fix.r, fix.f));
|
||||||
|
|
||||||
|
setup_travelthru(&fix, 1);
|
||||||
|
CuAssertIntEquals(tc, 1, count_travelthru(fix.r, fix.f));
|
||||||
|
|
||||||
|
setup_travelthru(&fix, 2);
|
||||||
|
CuAssertIntEquals(tc, 2, count_travelthru(fix.r, fix.f));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_travelthru_map(CuTest *tc) {
|
||||||
|
int n = 0;
|
||||||
|
travel_fixture fix;
|
||||||
|
|
||||||
|
setup_travelthru(&fix, 0);
|
||||||
|
travelthru_map(fix.r, count_travelers, &n);
|
||||||
|
CuAssertIntEquals(tc, 0, n);
|
||||||
|
|
||||||
|
setup_travelthru(&fix, 1);
|
||||||
|
travelthru_map(fix.r, count_travelers, &n);
|
||||||
|
CuAssertIntEquals(tc, 1, n);
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
CuSuite *get_travelthru_suite(void)
|
||||||
|
{
|
||||||
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
SUITE_ADD_TEST(suite, test_travelthru_count);
|
||||||
|
SUITE_ADD_TEST(suite, test_travelthru_map);
|
||||||
|
return suite;
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#include <CuTest.h>
|
#include <CuTest.h>
|
||||||
#include "bsdstring.h"
|
#include "bsdstring.h"
|
||||||
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void test_strlcat(CuTest * tc)
|
static void test_strlcat(CuTest * tc)
|
||||||
|
@ -38,6 +39,7 @@ static void test_strlcpy(CuTest * tc)
|
||||||
CuAssertIntEquals(tc, 8, (int)strlcpy(buffer, "herpderp", 8));
|
CuAssertIntEquals(tc, 8, (int)strlcpy(buffer, "herpderp", 8));
|
||||||
CuAssertStrEquals(tc, "herpder", buffer);
|
CuAssertStrEquals(tc, "herpder", buffer);
|
||||||
CuAssertIntEquals(tc, 0x7f, buffer[8]);
|
CuAssertIntEquals(tc, 0x7f, buffer[8]);
|
||||||
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_slprintf(CuTest * tc)
|
static void test_slprintf(CuTest * tc)
|
||||||
|
|
Loading…
Reference in New Issue