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); + } } } }