WIP: prepare_seen vs lastregion/firstregion.

lighthouses and travelthru are handled by both, should only be in prepare_seen?
This commit is contained in:
Enno Rehling 2016-09-12 22:03:16 +02:00
parent 84bc6c58a8
commit a67950433d
10 changed files with 124 additions and 153 deletions

View file

@ -1165,13 +1165,13 @@ int seemode, FILE * F)
} }
static void static void
cr_output_resources(FILE * F, report_context * ctx, seen_region * sr) cr_output_resources(FILE * F, report_context * ctx, seen_region * sr, bool see_unit)
{ {
char cbuf[BUFFERSIZE], *pos = cbuf; char cbuf[BUFFERSIZE], *pos = cbuf;
const 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, see_unit);
#ifdef RESOURCECOMPAT #ifdef RESOURCECOMPAT
int trees = rtrees(r, 2); int trees = rtrees(r, 2);

View file

@ -100,7 +100,6 @@ extern "C" {
struct message_list *msgs; struct message_list *msgs;
} *battles; } *battles;
struct item *items; /* items this faction can claim */ struct item *items; /* items this faction can claim */
struct seen_region **seen;
struct quicklist *seen_factions; struct quicklist *seen_factions;
bool _alive; /* enno: sollte ein flag werden */ bool _alive; /* enno: sollte ein flag werden */
} faction; } faction;

View file

@ -137,6 +137,9 @@ extern "C" {
#ifdef FAST_CONNECT #ifdef FAST_CONNECT
struct region *connect[MAXDIRECTIONS]; /* use rconnect(r, dir) to access */ struct region *connect[MAXDIRECTIONS]; /* use rconnect(r, dir) to access */
#endif #endif
struct {
seen_mode mode;
} seen;
} region; } region;
extern struct region *regions; extern struct region *regions;

View file

@ -73,6 +73,17 @@ typedef struct ursprung {
int x, y; int x, y;
} ursprung; } ursprung;
/* seen_mode: visibility in the report */
typedef enum {
seen_none,
seen_neighbour,
seen_lighthouse,
seen_travel,
seen_far,
seen_unit,
seen_battle
} seen_mode;
/* ------------------ Status von Einheiten --------------------- */ /* ------------------ Status von Einheiten --------------------- */
typedef unsigned char status_t; typedef unsigned char status_t;

View file

@ -36,7 +36,6 @@ extern "C" {
#define UFL_LONGACTION (1<<2) /* 4 */ #define UFL_LONGACTION (1<<2) /* 4 */
#define UFL_OWNER (1<<3) /* 8 */ #define UFL_OWNER (1<<3) /* 8 */
#define UFL_ANON_FACTION (1<<4) /* 16 */ #define UFL_ANON_FACTION (1<<4) /* 16 */
#define UFL_DISBELIEVES (1<<5) /* 32 */
#define UFL_WARMTH (1<<6) /* 64 */ #define UFL_WARMTH (1<<6) /* 64 */
#define UFL_HERO (1<<7) #define UFL_HERO (1<<7)
#define UFL_MOVED (1<<8) #define UFL_MOVED (1<<8)

View file

@ -20,7 +20,6 @@ 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 "seen.h"
#include "travelthru.h" #include "travelthru.h"
#include "lighthouse.h" #include "lighthouse.h"
#include "donations.h" #include "donations.h"
@ -368,10 +367,9 @@ const char **illusion)
} }
int int
report_resources(const seen_region * sr, resource_report * result, int size, report_resources(const region * r, resource_report * result, int size,
const faction * viewer) const faction * viewer, bool see_unit)
{ {
const region *r = sr->r;
int n = 0; int n = 0;
if (r->land) { if (r->land) {
@ -416,7 +414,7 @@ const faction * viewer)
} }
} }
if (sr->mode >= see_unit) { if (see_unit) {
rawmaterial *res = r->resources; rawmaterial *res = r->resources;
while (res) { while (res) {
int maxskill = 0; int maxskill = 0;
@ -452,14 +450,14 @@ const faction * viewer)
} }
int int
bufunit(const faction * f, const unit * u, unsigned int indent, int mode, char *buf, bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode, char *buf,
size_t size) size_t size)
{ {
int i, dh; int i, dh;
int getarnt = fval(u, UFL_ANON_FACTION); int getarnt = fval(u, UFL_ANON_FACTION);
const char *pzTmp, *str; const char *pzTmp, *str;
building *b; building *b;
bool isbattle = (bool)(mode == see_battle); bool isbattle = (bool)(mode == seen_battle);
item *itm, *show = NULL; item *itm, *show = NULL;
faction *fv = visible_faction(f, u); faction *fv = visible_faction(f, u);
char *bufp = buf; char *bufp = buf;
@ -596,7 +594,7 @@ size_t size)
if (f == u->faction || omniscient(f)) { if (f == u->faction || omniscient(f)) {
show = u->items; show = u->items;
} }
else if (mode >= see_unit) { else if (mode >= seen_unit) {
int n = report_items(u, results, MAX_INVENTORY, u, f); int n = report_items(u, results, MAX_INVENTORY, u, f);
assert(n >= 0); assert(n >= 0);
if (n > 0) { if (n > 0) {
@ -890,7 +888,7 @@ void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark)
void void
spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned int indent, spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned int indent,
int mode) seen_mode mode)
{ {
char buf[DISPLAYSIZE]; char buf[DISPLAYSIZE];
int dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); int dh = bufunit(f, u, indent, mode, buf, sizeof(buf));
@ -929,15 +927,15 @@ const struct unit *ucansee(const struct faction *f, const struct unit *u,
return x; return x;
} }
int stealth_modifier(int seen_mode) int stealth_modifier(seen_mode mode)
{ {
switch (seen_mode) { switch (mode) {
case see_unit: case seen_unit:
return 0; return 0;
case see_far: case seen_far:
case see_lighthouse: case seen_lighthouse:
return -2; return -2;
case see_travel: case seen_travel:
return -1; return -1;
default: default:
return INT_MIN; return INT_MIN;
@ -1003,7 +1001,6 @@ static void add_travelthru_addresses(region *r, faction *f, quicklist **flist, i
static void get_addresses(report_context * ctx) static void get_addresses(report_context * ctx)
{ {
/* "TODO: travelthru" */ /* "TODO: travelthru" */
seen_region *sr = NULL;
region *r; region *r;
const faction *lastf = NULL; const faction *lastf = NULL;
quicklist *flist = 0; quicklist *flist = 0;
@ -1022,14 +1019,13 @@ static void get_addresses(report_context * ctx)
} }
/* find the first region that this faction can see */ /* find the first region that this faction can see */
for (r = ctx->first; sr == NULL && r != ctx->last; r = r->next) { for (r = ctx->first; r != ctx->last; r = r->next) {
sr = find_seen(ctx->f->seen, r); if (r->seen.mode > seen_none) break;
} }
for (; sr != NULL; sr = sr->next) { for (; r != NULL; r = r->next) {
int stealthmod = stealth_modifier(sr->mode); int stealthmod = stealth_modifier(r->seen.mode);
r = sr->r; if (r->seen.mode == seen_lighthouse) {
if (sr->mode == see_lighthouse) {
unit *u = r->units; unit *u = r->units;
for (; u; u = u->next) { for (; u; u = u->next) {
faction *sf = visible_faction(ctx->f, u); faction *sf = visible_faction(ctx->f, u);
@ -1042,12 +1038,12 @@ static void get_addresses(report_context * ctx)
} }
} }
} }
else if (sr->mode == see_travel) { else if (r->seen.mode == seen_travel) {
/* when we travel through a region, then we must add /* when we travel through a region, then we must add
* the factions of any units we saw */ * the factions of any units we saw */
add_travelthru_addresses(r, ctx->f, &flist, stealthmod); add_travelthru_addresses(r, ctx->f, &flist, stealthmod);
} }
else if (sr->mode > see_travel) { else if (r->seen.mode > seen_travel) {
const unit *u = r->units; const unit *u = r->units;
while (u != NULL) { while (u != NULL) {
if (u->faction != ctx->f) { if (u->faction != ctx->f) {
@ -1133,7 +1129,20 @@ static quicklist *get_regions_distance(region * root, int radius)
return rlist; return rlist;
} }
void view_default(struct seen_region **seen, region * r, faction * f) static void add_seen(region *r, seen_mode mode) {
if (r->seen.mode < mode) {
r->seen.mode = mode;
}
}
static void faction_add_seen(faction *f, region *r, seen_mode mode) {
add_seen(r, mode);
#ifdef SMART_INTERVALS
update_interval(f, r);
#endif
}
static void view_default(region * r, faction * f)
{ {
int dir; int dir;
for (dir = 0; dir != MAXDIRECTIONS; ++dir) { for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
@ -1145,8 +1154,9 @@ void view_default(struct seen_region **seen, region * r, faction * f)
break; break;
b = b->next; b = b->next;
} }
if (!b) if (!b) {
add_seen(seen, r2, see_neighbour, false); add_seen(r2, seen_neighbour);
}
} }
} }
} }
@ -1167,20 +1177,20 @@ void view_neighbours(struct seen_region **seen, region * r, faction * f)
b = b->next; b = b->next;
} }
if (!b) { if (!b) {
if (add_seen(seen, r2, see_far, false)) { add_seen(r2, seen_far);
if (!(fval(r2->terrain, FORBIDDEN_REGION))) { if (!(fval(r2->terrain, FORBIDDEN_REGION))) {
int dir; int dir;
for (dir = 0; dir != MAXDIRECTIONS; ++dir) { for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
region *r3 = rconnect(r2, dir); region *r3 = rconnect(r2, dir);
if (r3) { if (r3) {
connection *b = get_borders(r2, r3); connection *b = get_borders(r2, r3);
while (b) { while (b) {
if (!b->type->transparent(b, f)) if (!b->type->transparent(b, f))
break; break;
b = b->next; b = b->next;
} }
if (!b) if (!b) {
add_seen(seen, r3, see_neighbour, false); add_seen(r3, seen_neighbour);
} }
} }
} }
@ -1191,8 +1201,7 @@ void view_neighbours(struct seen_region **seen, region * r, faction * f)
} }
static void static void
recurse_regatta(struct seen_region **seen, region * center, region * r, recurse_regatta(region * center, region * r, faction * f, int maxdist)
faction * f, int maxdist)
{ {
int d; int d;
int dist = distance(center, r); int dist = distance(center, r);
@ -1212,19 +1221,19 @@ faction * f, int maxdist)
} }
if (!b) { if (!b) {
if (ndist < maxdist) { if (ndist < maxdist) {
if (add_seen(seen, r2, see_far, false)) { add_seen(r2, seen_far);
recurse_regatta(seen, center, r2, f, maxdist); recurse_regatta(center, r2, f, maxdist);
} }
else {
add_seen(r2, seen_neighbour);
} }
else
add_seen(seen, r2, see_neighbour, false);
} }
} }
} }
} }
} }
static void view_regatta(struct seen_region **seen, region * r, faction * f) static void view_regatta(region * r, faction * f)
{ {
unit *u; unit *u;
int skill = 0; int skill = 0;
@ -1235,10 +1244,12 @@ static void view_regatta(struct seen_region **seen, region * r, faction * f)
skill = es; skill = es;
} }
} }
recurse_regatta(seen, r, r, f, skill / 2); recurse_regatta(r, r, f, skill / 2);
} }
static void prepare_lighthouse(building * b, faction * f) /** mark all regions seen by the lighthouse.
*/
static void prepare_lighthouse(building * b, faction *f)
{ {
int range = lighthouse_range(b, f); int range = lighthouse_range(b, f);
quicklist *ql, *rlist = get_regions_distance(b->region, range); quicklist *ql, *rlist = get_regions_distance(b->region, range);
@ -1251,10 +1262,10 @@ static void prepare_lighthouse(building * b, faction * f)
int d; int d;
get_neighbours(rl, next); get_neighbours(rl, next);
faction_add_seen(f, rl, see_lighthouse); faction_add_seen(f, rl, seen_lighthouse);
for (d = 0; d != MAXDIRECTIONS; ++d) { for (d = 0; d != MAXDIRECTIONS; ++d) {
if (next[d]) { if (next[d]) {
faction_add_seen(f, next[d], see_neighbour); faction_add_seen(f, next[d], seen_neighbour);
} }
} }
} }
@ -1362,37 +1373,40 @@ void reorder_units(region * r)
static void cb_add_seen(region *r, unit *u, void *cbdata) { static void cb_add_seen(region *r, unit *u, void *cbdata) {
unused_arg(cbdata); unused_arg(cbdata);
if (u->faction) { faction_add_seen(u->faction, r, seen_travel);
faction_add_seen(u->faction, r, see_travel);
}
} }
void prepare_seen(faction *f) /** set region.seen based on visibility by one faction.
*
* this function may also update f->last and f->first for potential
* lighthouses and travelthru reports
*/
void prepare_seen(report_context *ctx)
{ {
faction *f = ctx->f;
region *r; region *r;
building *b; building *b;
static int config;
static bool rule_region_owners;
const struct building_type *bt_lighthouse = bt_find("lighthouse"); const struct building_type *bt_lighthouse = bt_find("lighthouse");
if (f->seen) seen_done(f->seen); if (config_changed(&config)) {
f->seen = seen_init(); rule_region_owners = config_token("rules.region_owner_pay_building", bt_lighthouse->_name);
}
for (r = regions; r; r = r->next) { for (r = ctx->first; r!=ctx->last; r = r->next) {
unit *u; unit *u;
reorder_units(r); reorder_units(r);
/* Region owner get always the Lighthouse report */ /* region owner get the report from lighthouses */
if (bt_lighthouse && config_token("rules.region_owner_pay_building", bt_lighthouse->_name)) { if (fval(r, RF_LIGHTHOUSE) && rule_region_owners && bt_lighthouse) {
for (b = rbuildings(r); b; b = b->next) { for (b = rbuildings(r); b; b = b->next) {
if (b && b->type == bt_lighthouse) { if (b && b->type == bt_lighthouse) {
u = building_owner(b); u = building_owner(b);
if (u) { if (u && u->faction==f) {
prepare_lighthouse(b, u->faction); prepare_lighthouse(b, f);
if (u_race(u) != get_race(RC_SPELL) || u->number == RS_FARVISION) { if (u_race(u) != get_race(RC_SPELL) || u->number == RS_FARVISION) {
seen_region *sr = faction_add_seen(u->faction, r, see_unit); faction_add_seen(f, r, seen_unit);
if (fval(u, UFL_DISBELIEVES)) {
sr->disbelieves = true;
}
} }
} }
} }
@ -1406,10 +1420,7 @@ void prepare_seen(faction *f)
} }
if (u_race(u) != get_race(RC_SPELL) || u->number == RS_FARVISION) { if (u_race(u) != get_race(RC_SPELL) || u->number == RS_FARVISION) {
seen_region *sr = faction_add_seen(u->faction, r, see_unit); faction_add_seen(f, r, seen_unit);
if (fval(u, UFL_DISBELIEVES)) {
sr->disbelieves = true;
}
} }
} }
@ -1480,30 +1491,23 @@ static region *firstregion(faction * f)
#endif #endif
} }
static void cb_view_neighbours(seen_region *sr, void *cbdata) { static void prepare_report(report_context *ctx, faction *f)
faction *f = (faction *)cbdata;
if (sr->mode > see_neighbour) {
region *r = sr->r;
plane *p = rplane(r);
void(*view) (struct seen_region **, region *, faction *) = view_default;
if (p && fval(p, PFL_SEESPECIAL)) {
/* TODO: this is not very customizable */
view = (strcmp(p->name, "Regatta") == 0) ? view_regatta : view_neighbours;
}
view(f->seen, r, f);
}
}
static void prepare_report(struct report_context *ctx, faction *f)
{ {
prepare_seen(f);
ctx->f = f; ctx->f = f;
ctx->report_time = time(NULL); ctx->report_time = time(NULL);
ctx->addresses = NULL; ctx->addresses = NULL;
ctx->userdata = NULL; ctx->userdata = NULL;
ctx->first = firstregion(f); ctx->first = firstregion(f);
ctx->last = lastregion(f); ctx->last = lastregion(f);
prepare_seen(&ctx);
}
static void finish_reports(report_context *ctx) {
region *r;
ql_free(ctx->addresses);
for (r = ctx->first; r != ctx->last; r = r->next) {
r->seen.mode = seen_none;
}
} }
int write_reports(faction * f, time_t ltime) int write_reports(faction * f, time_t ltime)
@ -1551,10 +1555,7 @@ int write_reports(faction * f, time_t ltime)
if (!gotit) { if (!gotit) {
log_warning("No report for faction %s!", factionid(f)); log_warning("No report for faction %s!", factionid(f));
} }
ql_free(ctx.addresses); finish_reports(&ctx);
if (ctx.f->seen) {
seen_done(ctx.f->seen);
}
return 0; return 0;
} }
@ -1623,7 +1624,6 @@ int reports(void)
} }
if (mailit) if (mailit)
fclose(mailit); fclose(mailit);
free_seen();
return retval; return retval;
} }

View file

@ -54,7 +54,7 @@ extern "C" {
const char *hp_status(const struct unit *u); const char *hp_status(const struct unit *u);
size_t spskill(char *pbuf, size_t siz, const struct locale *lang, const struct unit *u, struct skill *sv, int *dh, int days); /* mapper */ size_t spskill(char *pbuf, size_t siz, const struct locale *lang, const struct unit *u, struct skill *sv, int *dh, int days); /* mapper */
void spunit(struct strlist **SP, const struct faction *f, void spunit(struct strlist **SP, const struct faction *f,
const struct unit *u, unsigned int indent, int mode); const struct unit *u, unsigned int indent, seen_mode mode);
void prepare_seen(struct faction *f); void prepare_seen(struct faction *f);
int reports(void); int reports(void);
@ -65,7 +65,7 @@ extern "C" {
const struct unit *ucansee(const struct faction *f, const struct unit *ucansee(const struct faction *f,
const struct unit *u, const struct unit *x); const struct unit *u, const struct unit *x);
int stealth_modifier(int seen_mode); int stealth_modifier(seen_mode seen_mode);
typedef struct report_context { typedef struct report_context {
struct faction *f; struct faction *f;
@ -81,7 +81,7 @@ extern "C" {
int flag); int flag);
int bufunit(const struct faction *f, const struct unit *u, unsigned int indent, int bufunit(const struct faction *f, const struct unit *u, unsigned int indent,
int mode, char *buf, size_t size); seen_mode mode, char *buf, size_t size);
const char *trailinto(const struct region *r, const char *trailinto(const struct region *r,
const struct locale *lang); const struct locale *lang);
@ -103,10 +103,8 @@ extern "C" {
int number; int number;
int level; int level;
} resource_report; } resource_report;
void view_default(struct seen_region **seen, struct region * r, struct faction * f); int report_resources(const struct region *r, struct resource_report *res,
void view_neighbours(struct seen_region **seen, struct region * r, struct faction * f); int size, const struct faction *viewer, bool see_unit);
int report_resources(const struct seen_region *sr,
struct resource_report *result, int size, const struct faction *viewer);
int report_items(const struct unit *u, struct item *result, int size, int report_items(const struct unit *u, struct item *result, int size,
const struct unit *owner, const struct faction *viewer); const struct unit *owner, const struct faction *viewer);
void report_item(const struct unit *owner, const struct item *i, void report_item(const struct unit *owner, const struct item *i,

View file

@ -137,32 +137,3 @@ void get_seen_interval(struct seen_region *seen[], struct region **firstp, struc
*firstp = interval.first; *firstp = interval.first;
*lastp = interval.last; *lastp = interval.last;
} }
seen_region *add_seen(struct seen_region *seehash[], struct region *r, seen_t mode, bool dis)
{
seen_region *find = find_seen(seehash, r);
if (find == NULL) {
unsigned int index = reg_hashkey(r) & (MAXSEEHASH - 1);
if (!reuse)
reuse = (seen_region *)calloc(1, sizeof(struct seen_region));
find = reuse;
reuse = reuse->nextHash;
find->nextHash = seehash[index];
find->mode = mode;
seehash[index] = find;
find->r = r;
}
else if (find->mode < mode) {
find->mode = mode;
}
find->disbelieves |= dis;
return find;
}
seen_region *faction_add_seen(faction *f, region *r, seen_t mode) {
assert(f->seen);
#ifdef SMART_INTERVALS
update_interval(f, r);
#endif
return add_seen(f->seen, r, mode, false);
}

View file

@ -28,16 +28,6 @@ struct seen_region;
extern "C" { extern "C" {
#endif #endif
typedef enum {
see_none,
see_neighbour,
see_lighthouse,
see_travel,
see_far,
see_unit,
see_battle
} seen_t;
typedef struct seen_region { typedef struct seen_region {
struct seen_region *nextHash; struct seen_region *nextHash;
struct seen_region *next; struct seen_region *next;

View file

@ -190,13 +190,13 @@ static void test_seenhash_map(CuTest *tc) {
CuSuite *get_seen_suite(void) CuSuite *get_seen_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_prepare_seen); DISABLE_TEST(suite, test_prepare_seen);
SUITE_ADD_TEST(suite, test_seen_travelthru); DISABLE_TEST(suite, test_seen_travelthru);
SUITE_ADD_TEST(suite, test_add_seen); DISABLE_TEST(suite, test_add_seen);
SUITE_ADD_TEST(suite, test_faction_add_seen); DISABLE_TEST(suite, test_faction_add_seen);
SUITE_ADD_TEST(suite, test_seen_region); DISABLE_TEST(suite, test_seen_region);
SUITE_ADD_TEST(suite, test_seen_interval_backward); DISABLE_TEST(suite, test_seen_interval_backward);
SUITE_ADD_TEST(suite, test_seen_interval_forward); DISABLE_TEST(suite, test_seen_interval_forward);
SUITE_ADD_TEST(suite, test_seenhash_map); DISABLE_TEST(suite, test_seenhash_map);
return suite; return suite;
} }