diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c
index 7e6adf07d..facf61ee5 100644
--- a/src/common/gamecode/creport.c
+++ b/src/common/gamecode/creport.c
@@ -793,11 +793,12 @@ cr_output_unit(FILE * F, const region * r,
assert(u->ship->region);
fprintf(F, "%d;Schiff\n", u->ship->no);
}
- if (getguard(u))
+ if (is_guard(u, GUARD_ALL)!=0) {
fprintf(F, "%d;bewacht\n", 1);
- if ((b=usiege(u))!=NULL)
+ }
+ if ((b=usiege(u))!=NULL) {
fprintf(F, "%d;belagert\n", b->no);
-
+ }
/* additional information for own units */
if (u->faction == f || omniscient(f)) {
order * ord;
diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c
index 1933fcc82..5ca313e60 100644
--- a/src/common/gamecode/economy.c
+++ b/src/common/gamecode/economy.c
@@ -1489,7 +1489,7 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
if (rdata->guard!=0) {
unit * u2;
for (u2 = r->units; u2; u2 = u2->next) {
- if ((getguard(u2) & rdata->guard) && can_guard(u2, u)) {
+ if (is_guard(u2, rdata->guard)!=0 && can_guard(u2, u)) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, u->thisorder, "region_guarded", "guard", u2));
return;
@@ -1504,7 +1504,7 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
if (itype == olditemtype[I_IRON] || itype == olditemtype[I_LAEN]) {
unit * u2;
for (u2 = r->units; u2; u2 = u2->next ) {
- if (getguard(u) & GUARD_MINING
+ if (is_guard(u, GUARD_MINING)
&& !fval(u2, UFL_ISNEW)
&& u2->number
&& !alliedunit(u2, u->faction, HELP_GUARD))
diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c
index 26d7b44c0..a16ad5eb3 100644
--- a/src/common/gamecode/laws.c
+++ b/src/common/gamecode/laws.c
@@ -2613,8 +2613,16 @@ update_guards(void)
for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) {
- if (can_start_guarding(u)!=E_GUARD_OK) {
- setguard(u, GUARD_NONE);
+ if (fval(u, UFL_GUARD)) {
+ if (can_start_guarding(u)!=E_GUARD_OK) {
+ setguard(u, GUARD_NONE);
+ } else {
+ attrib * a = a_find(u->attribs, &at_guard);
+ if (a && a->data.i==(int)guard_flags(u)) {
+ /* this is really rather not necessary */
+ a_remove(&u->attribs, a);
+ }
+ }
}
}
}
diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c
index 27aeddc26..dbbd04524 100644
--- a/src/common/gamecode/monster.c
+++ b/src/common/gamecode/monster.c
@@ -158,7 +158,7 @@ get_money_for_dragon(region * r, unit * u, int wanted)
/* attackiere bewachende einheiten */
for (u2 = r->units; u2; u2 = u2->next) {
- if (u2 != u && getguard(u2)&GUARD_TAX) {
+ if (u2 != u && is_guard(u2, GUARD_TAX)) {
order * ord = monster_attack(u, u2);
if (ord) addlist(&u->orders, ord);
}
@@ -177,7 +177,7 @@ get_money_for_dragon(region * r, unit * u, int wanted)
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction != u->faction && cansee(u->faction, r, u2, 0)) {
int m = get_money(u2);
- if (m==0 || (getguard(u2) & GUARD_TAX)) continue;
+ if (m==0 || is_guard(u2, GUARD_TAX)) continue;
else {
order * ord = monster_attack(u, u2);
if (ord) {
diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c
index a5d8bde31..678709dae 100644
--- a/src/common/gamecode/report.c
+++ b/src/common/gamecode/report.c
@@ -1625,7 +1625,7 @@ guards(FILE * F, const region * r, const faction * see)
/* Bewachung */
for (u = r->units; u; u = u->next) {
- if (getguard(u)) {
+ if (is_guard(u, GUARD_ALL)!=0) {
faction *f = u->faction;
faction *fv = visible_faction(see, u);
diff --git a/src/common/gamecode/xmlreport.c b/src/common/gamecode/xmlreport.c
index 91356116e..93f526c8d 100644
--- a/src/common/gamecode/xmlreport.c
+++ b/src/common/gamecode/xmlreport.c
@@ -239,7 +239,7 @@ xml_unit(report_context * ctx, unit * u, int mode)
}
/* possible info */
- if (getguard(u)) {
+ if (is_guard(u, GUARD_ALL)!=0) {
xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "guard"));
}
diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c
index ac06d6e26..06643ed8a 100644
--- a/src/common/kernel/battle.c
+++ b/src/common/kernel/battle.c
@@ -2416,7 +2416,7 @@ make_side(battle * b, const faction * f, const group * g, unsigned int flags, co
} else {
unit * u;
for (u = b->region->units; u; u = u->next) {
- if (getguard(u)) {
+ if (is_guard(u, HELP_ALL)) {
if (alliedunit(u, f, HELP_GUARD)) {
flags |= SIDE_HASGUARDS;
break;
diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c
index 4dce24d32..9b967d252 100644
--- a/src/common/kernel/build.c
+++ b/src/common/kernel/build.c
@@ -243,7 +243,7 @@ siege_cmd(unit * u, order * ord)
return;
}
- if (!(getguard(u) & GUARD_TRAVELTHRU)) {
+ if (!is_guard(u, GUARD_TRAVELTHRU)) {
/* abbruch, wenn die einheit nicht vorher die region bewacht - als
* warnung fuer alle anderen! */
cmistake(u, ord, 81, MSG_EVENT);
@@ -301,7 +301,7 @@ destroy_road(unit *u, int nmax, struct order * ord)
else if (nmax<0) n = 0;
for (u2=r->units;u2;u2=u2->next) {
- if (u2->faction!=u->faction && getguard(u2)&GUARD_TAX
+ if (u2->faction!=u->faction && is_guard(u2, GUARD_TAX)
&& cansee(u2->faction, u->region, u, 0)
&& !alliedunit(u, u2->faction, HELP_GUARD)) {
cmistake(u, ord, 70, MSG_EVENT);
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index 60a14fe5d..b4d2f3005 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -1011,7 +1011,7 @@ cansee(const faction * f, const region * r, const unit * u, int modifier)
if (u2==NULL) return false;
/* simple visibility, just gotta have a unit in the region to see 'em */
- if (getguard(u) || usiege(u) || u->building || u->ship) {
+ if (is_guard(u, GUARD_ALL)!=0 || usiege(u) || u->building || u->ship) {
return true;
}
@@ -1048,7 +1048,7 @@ cansee_unit(const unit * u, const unit * target, int modifier)
else {
int n, rings, o;
- if (getguard(target) || usiege(target) || target->building || target->ship) {
+ if (is_guard(target, GUARD_ALL)!=0 || usiege(target) || target->building || target->ship) {
return true;
}
@@ -1087,7 +1087,7 @@ cansee_durchgezogen(const faction * f, const region * r, const unit * u, int mod
else {
int rings;
- if (getguard(u) || usiege(u) || u->building || u->ship) {
+ if (is_guard(u, GUARD_ALL)!=0 || usiege(u) || u->building || u->ship) {
return true;
}
@@ -2271,19 +2271,25 @@ setguard(unit * u, unsigned int flags)
}
fset(u, UFL_GUARD);
fset(u->region, RF_GUARDED);
- if (!a) a = a_add(&u->attribs, a_new(&at_guard));
- a->data.i = (int)flags;
+ if ((int)flags==guard_flags(u)) {
+ if (a) a_remove(&u->attribs, a);
+ } else {
+ if (!a) a = a_add(&u->attribs, a_new(&at_guard));
+ a->data.i = (int)flags;
+ }
}
unsigned int
getguard(const unit * u)
{
- if (fval(u->region->terrain, SEA_REGION)) return GUARD_NONE;
- if (fval(u, UFL_GUARD)) {
- attrib * a = a_find(u->attribs, &at_guard);
- if (a) return (unsigned int)a->data.i;
+ attrib * a;
+
+ assert((u->building && fval(u, UFL_OWNER)) || fval(u, UFL_GUARD) || !"you're doing it wrong! check is_guard first");
+ a = a_find(u->attribs, &at_guard);
+ if (a) {
+ return (unsigned int)a->data.i;
}
- return GUARD_NONE;
+ return guard_flags(u);
}
#ifndef HAVE_STRDUP
@@ -2433,10 +2439,9 @@ make_undead_unit(unit * u)
fset(u, UFL_ISNEW);
}
-void
-guard(unit * u, unsigned int mask)
+unsigned int guard_flags(const unit * u)
{
- int flags = GUARD_CREWS | GUARD_LANDING | GUARD_TRAVELTHRU | GUARD_TAX;
+ unsigned int flags = GUARD_CREWS | GUARD_LANDING | GUARD_TRAVELTHRU | GUARD_TAX;
#if GUARD_DISABLES_PRODUCTION == 1
flags |= GUARD_PRODUCE;
#endif
@@ -2454,6 +2459,13 @@ guard(unit * u, unsigned int mask)
flags = GUARD_MINING;
break;
}
+ return flags;
+}
+
+void
+guard(unit * u, unsigned int mask)
+{
+ unsigned int flags = guard_flags(u);
setguard(u, flags & mask);
}
diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h
index f23cf817f..85e5a0306 100644
--- a/src/common/kernel/eressea.h
+++ b/src/common/kernel/eressea.h
@@ -333,6 +333,7 @@ extern void guard(struct unit * u, unsigned int mask);
/* Einheit setzt "BEWACHE", rassenspezifzisch.
* 'mask' kann einzelne flags zusätzlich und-maskieren.
*/
+unsigned int guard_flags(const struct unit * u);
extern boolean hunger(int number, struct unit * u);
extern int lifestyle(const struct unit*);
diff --git a/src/common/kernel/move.c b/src/common/kernel/move.c
index 897c7ca3b..736929538 100644
--- a/src/common/kernel/move.c
+++ b/src/common/kernel/move.c
@@ -865,7 +865,7 @@ bewegung_blockiert_von(unit * reisender, region * r)
if (fval(reisender->race, RCF_ILLUSIONARY)) return NULL;
for (u=r->units;u && !contact;u=u->next) {
- if (getguard(u) & GUARD_TRAVELTHRU) {
+ if (is_guard(u, GUARD_TRAVELTHRU)) {
int sk = eff_skill(u, SK_PERCEPTION, r);
if (invisible(reisender, u) >= reisender->number) continue;
if (u->faction == reisender->faction) contact = true;
@@ -890,28 +890,44 @@ bewegung_blockiert_von(unit * reisender, region * r)
}
static boolean
-is_guardian_u(unit * u2, unit *u, unsigned int mask)
+is_guardian_u(const unit * guard, unit *u, unsigned int mask)
{
- if (u2->faction == u->faction) return false;
- if ((getguard(u2) & mask) == 0) return false;
- if (alliedunit(u2, u->faction, HELP_GUARD)) return false;
- if (ucontact(u2, u)) return false;
- if (!cansee(u2->faction, u->region, u, 0)) return false;
+ if (guard->faction == u->faction) return false;
+ if (is_guard(guard, mask) == 0) return false;
+ if (alliedunit(guard, u->faction, HELP_GUARD)) return false;
+ if (ucontact(guard, u)) return false;
+ if (!cansee(guard->faction, u->region, u, 0)) return false;
return true;
}
static boolean
-is_guardian_r(unit * u2)
+is_guardian_r(const unit * guard)
{
- if (u2->number == 0) return false;
- if ((u2->flags&UFL_GUARD)==0) return false;
- if (besieged(u2)) return false;
- if (!armedmen(u2, true) && !fval(u2->race, RCF_UNARMEDGUARD)) return false;
+ if (guard->number == 0) return false;
+ if (besieged(guard)) return false;
+ if (guard->building && fval(guard, UFL_OWNER)) {
+ faction * owner = region_get_owner(guard->region);
+ if (owner==guard->faction) {
+ building * bowner = largestbuilding(guard->region, &is_owner_building, false);
+ if (bowner==guard->building) {
+ return true;
+ }
+ }
+ }
+ if ((guard->flags&UFL_GUARD)==0) return false;
+ if (!armedmen(guard, true) && !fval(guard->race, RCF_UNARMEDGUARD)) return false;
return true;
}
+boolean is_guard(const struct unit * u, int mask)
+{
+ return is_guardian_r(u) && (getguard(u) & mask)!=0;
+}
+
#define MAXGUARDCACHE 16
+/** returns the guard which prevents 'u' from doing 'mask' actions in 'r'.
+*/
unit *
is_guarded(region * r, unit * u, unsigned int mask)
{
@@ -919,6 +935,7 @@ is_guarded(region * r, unit * u, unsigned int mask)
int i;
static unit * guardcache[MAXGUARDCACHE], * lastguard; /* STATIC_XCALL: used across calls */
static int gamecookie = -1;
+
if (gamecookie!=global.cookie) {
if (gamecookie>=0) {
/* clear the previous turn's cache */
diff --git a/src/common/kernel/move.h b/src/common/kernel/move.h
index b65a8cddb..c2b4da390 100644
--- a/src/common/kernel/move.h
+++ b/src/common/kernel/move.h
@@ -19,51 +19,42 @@ extern "C" {
struct unit;
struct ship;
+struct building_type;
-/* ------------------------------------------------------------- */
/* 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
- * objecte gibt, die etwas tragen. */
-
+** objekte gibt, die etwas tragen. */
#define SILVERWEIGHT 1
-
#define SCALEWEIGHT 100 /* Faktor, um den die Anzeige von gewichten
* * skaliert wird */
-
-extern int personcapacity(const struct unit *u);
-
#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. */
+** 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. */
-extern direction_t getdirection(const struct locale *);
-extern void movement(void);
-extern void run_to(struct unit * u, struct region * to);
-extern struct unit *is_guarded(struct region * r, struct unit * u, unsigned int mask);
-extern int enoughsailors(const struct ship * sh, const struct region * r);
-extern boolean canswim(struct unit *u);
-extern boolean canfly(struct unit *u);
-extern struct unit *get_captain(const struct ship * sh);
-extern void travelthru(const struct unit * u, struct region * r);
-extern struct ship * move_ship(struct ship * sh, struct region * from, struct region * to, struct region_list * route);
-extern int walkingcapacity(const struct unit * u);
-
-extern void follow_unit(struct unit * u);
-
-struct building_type;
+int personcapacity(const struct unit *u);
+direction_t getdirection(const struct locale *);
+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);
+boolean is_guard(const struct unit * u, int mask);
+int enoughsailors(const struct ship * sh, const struct region * r);
+boolean canswim(struct unit *u);
+boolean 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);
boolean buildingtype_exists(const struct region * r, const struct building_type * bt);
struct unit* owner_buildingtyp(const struct region * r, const struct building_type * bt);
diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c
index a1962f057..313e0a3a2 100644
--- a/src/common/kernel/region.c
+++ b/src/common/kernel/region.c
@@ -1472,26 +1472,33 @@ region_set_owner(struct region * r, struct faction * owner, int turn)
}
-void update_owners(region * r)
+faction * update_owners(region * r)
{
+ faction * f = NULL;
if (r->land) {
building * bowner = largestbuilding(r, &is_owner_building, false);
building * blargest = largestbuilding(r, &is_tax_building, false);
if (blargest) {
if (!bowner || bowner->sizesize) {
/* region owners update? */
- faction * f = region_get_owner(r);
unit * u = buildingowner(r, blargest);
+ f = region_get_owner(r);
if (u==NULL) {
- if (f) region_set_owner(r, NULL, turn);
+ if (f) {
+ region_set_owner(r, NULL, turn);
+ f = NULL;
+ }
} else if (u->faction!=f) {
region_set_owner(r, u->faction, turn);
+ f = u->faction;
}
}
} else if (r->land->ownership && r->land->ownership->owner) {
region_set_owner(r, NULL, turn);
+ f = NULL;
}
}
+ return f;
}
void
diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h
index 142f9e058..9ac09cf19 100644
--- a/src/common/kernel/region.h
+++ b/src/common/kernel/region.h
@@ -281,7 +281,7 @@ boolean is_mourning(const region * r, int in_turn);
const struct item_type * r_luxury(struct region * r);
void get_neighbours(const struct region * r, struct region ** list);
-void update_owners(struct region * r);
+struct faction * update_owners(struct region * r);
#ifdef __cplusplus
}
diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c
index 07417f0ae..80ca9e157 100644
--- a/src/common/kernel/reports.c
+++ b/src/common/kernel/reports.c
@@ -581,7 +581,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz
}
}
}
- if (getguard(u)) {
+ if (is_guard(u, GUARD_ALL)!=0) {
bytes = (int)strlcpy(bufp, ", ", size);
if (wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER();
bytes = (int)strlcpy(bufp, LOC(f->locale, "unit_guards"), size);
diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c
index f800f93a0..cd4430847 100644
--- a/src/common/kernel/save.c
+++ b/src/common/kernel/save.c
@@ -1054,8 +1054,14 @@ readregion(struct storage * store, int x, int y)
if (store->version>=REGIONOWNER_VERSION) {
r->land->morale = (short)store->r_int(store);
read_owner(store, &r->land->ownership);
- if (r->land->ownership && r->land->ownership->owner==get_monsters()) {
- update_owners(r);
+ if (r->land->ownership && r->land->ownership->owner) {
+ faction * owner = r->land->ownership->owner;
+ if (owner==get_monsters()) {
+ owner = update_owners(r);
+ }
+ if (owner) {
+ fset(r, RF_GUARDED);
+ }
}
}
}