repair update_long_order and K_DESTROY handling according to discussion in https://bugs.eressea.de/view.php?id=2080

This commit is contained in:
Enno Rehling 2015-08-04 22:47:55 +02:00
parent 00d8994918
commit 4d061d8592
14 changed files with 109 additions and 164 deletions

View File

@ -2830,17 +2830,6 @@
<text locale="de">"$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."</text> <text locale="de">"$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."</text>
<text locale="en">"$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."</text> <text locale="en">"$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."</text>
</message> </message>
<message name="manufacture" section="production">
<type>
<arg name="unit" type="unit"/>
<arg name="region" type="region"/>
<arg name="amount" type="int"/>
<arg name="wanted" type="int"/>
<arg name="resource" type="resource"/>
</type>
<text locale="de">"$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."</text>
<text locale="en">"$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."</text>
</message>
<message name="buildbuilding" section="production"> <message name="buildbuilding" section="production">
<type> <type>
<arg name="unit" type="unit"/> <arg name="unit" type="unit"/>

View File

@ -1,7 +1,5 @@
local pkg = {} local pkg = {}
print("loading jsreport module")
function pkg.init() function pkg.init()
eressea.settings.set("feature.jsreport.enable", "1") eressea.settings.set("feature.jsreport.enable", "1")
end end

View File

@ -3232,7 +3232,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack)
} }
/* Illusionen und Zauber kaempfen nicht */ /* Illusionen und Zauber kaempfen nicht */
if (fval(u_race(u), RCF_ILLUSIONARY) || idle(u->faction) || u->number == 0) { if (fval(u_race(u), RCF_ILLUSIONARY) || u->number == 0) {
return NULL; return NULL;
} }
if (s1 == NULL) { if (s1 == NULL) {

View File

@ -929,7 +929,8 @@ static void cr_output_unit(FILE * F, const region * r, const faction * f,
} }
} }
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (u->old_orders && is_repeated(ord)) keyword_t kwd = getkeyword(ord);
if (u->old_orders && is_repeated(kwd))
continue; /* unit has defaults */ continue; /* unit has defaults */
if (is_persistent(ord)) { if (is_persistent(ord)) {
fwriteorder(F, ord, f->locale, true); fwriteorder(F, ord, f->locale, true);

View File

@ -563,7 +563,7 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
return; return;
} }
} }
if (!playerrace(rc) || idle(u->faction)) { if (!playerrace(rc)) {
cmistake(u, ord, 139, MSG_EVENT); cmistake(u, ord, 139, MSG_EVENT);
return; return;
} }
@ -979,27 +979,14 @@ void economics(region * r)
remove_empty_units_in_region(r); remove_empty_units_in_region(r);
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
order *ord; order *ord = u->thisorder;
bool destroyed = false;
if (u->number > 0) {
for (ord = u->orders; ord; ord = ord->next) {
keyword_t kwd = getkeyword(ord); keyword_t kwd = getkeyword(ord);
if (kwd == K_DESTROY) { if (kwd == K_DESTROY) {
if (!destroyed) { if (destroy_cmd(u, ord) == 0) {
if (destroy_cmd(u, ord) != 0)
ord = NULL;
destroyed = true;
}
}
if (u->orders == NULL) {
break;
}
}
}
if (destroyed) {
fset(u, UFL_LONGACTION | UFL_NOTMOVING); fset(u, UFL_LONGACTION | UFL_NOTMOVING);
} }
} }
}
} }
@ -1051,7 +1038,7 @@ static void manufacture(unit * u, const item_type * itype, int want)
i_change(&u->items, itype, n); i_change(&u->items, itype, n);
if (want == INT_MAX) if (want == INT_MAX)
want = n; want = n;
ADDMSG(&u->faction->msgs, msg_message("manufacture", ADDMSG(&u->faction->msgs, msg_message("produce",
"unit region amount wanted resource", u, u->region, n, want, "unit region amount wanted resource", u, u->region, n, want,
itype->rtype)); itype->rtype));
} }
@ -1466,7 +1453,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
i_change(&u->items, ptype->itype, built); i_change(&u->items, ptype->itype, built);
if (want == INT_MAX) if (want == INT_MAX)
want = built; want = built;
ADDMSG(&u->faction->msgs, msg_message("manufacture", ADDMSG(&u->faction->msgs, msg_message("produce",
"unit region amount wanted resource", u, u->region, built, want, "unit region amount wanted resource", u, u->region, built, want,
ptype->itype->rtype)); ptype->itype->rtype));
break; break;
@ -3216,7 +3203,7 @@ void produce(struct region *r)
continue; continue;
if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) {
/* this message was already given in laws.setdefaults /* this message was already given in laws.c:update_long_order
cmistake(u, u->thisorder, 52, MSG_PRODUCE); cmistake(u, u->thisorder, 52, MSG_PRODUCE);
*/ */
continue; continue;

View File

@ -151,11 +151,11 @@ int destroy_cmd(unit * u, struct order *ord)
int n = INT_MAX; int n = INT_MAX;
if (u->number < 1) if (u->number < 1)
return 0; return 1;
if (fval(u, UFL_LONGACTION)) { if (fval(u, UFL_LONGACTION)) {
cmistake(u, ord, 52, MSG_PRODUCE); cmistake(u, ord, 52, MSG_PRODUCE);
return 0; return 52;
} }
init_order(ord); init_order(ord);
@ -183,11 +183,11 @@ int destroy_cmd(unit * u, struct order *ord)
if (u != building_owner(b)) { if (u != building_owner(b)) {
cmistake(u, ord, 138, MSG_PRODUCE); cmistake(u, ord, 138, MSG_PRODUCE);
return 0; return 138;
} }
if (fval(b->type, BTF_INDESTRUCTIBLE)) { if (fval(b->type, BTF_INDESTRUCTIBLE)) {
cmistake(u, ord, 138, MSG_PRODUCE); cmistake(u, ord, 138, MSG_PRODUCE);
return 0; return 138;
} }
if (n >= b->size) { if (n >= b->size) {
/* destroy completly */ /* destroy completly */
@ -213,11 +213,11 @@ int destroy_cmd(unit * u, struct order *ord)
if (u != ship_owner(sh)) { if (u != ship_owner(sh)) {
cmistake(u, ord, 138, MSG_PRODUCE); cmistake(u, ord, 138, MSG_PRODUCE);
return 0; return 138;
} }
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
cmistake(u, ord, 14, MSG_EVENT); cmistake(u, ord, 14, MSG_EVENT);
return 0; return 14;
} }
if (n >= (sh->size * 100) / sh->type->construction->maxsize) { if (n >= (sh->size * 100) / sh->type->construction->maxsize) {
@ -242,11 +242,11 @@ int destroy_cmd(unit * u, struct order *ord)
} }
else { else {
cmistake(u, ord, 138, MSG_PRODUCE); cmistake(u, ord, 138, MSG_PRODUCE);
return 0; return 138;
} }
if (con) { if (con) {
/* TODO: Nicht an ZERSTÖRE mit Punktangabe angepaßt! */ /* TODO: Nicht an ZERSTÖRE mit Punktangabe angepasst! */
int c; int c;
for (c = 0; con->materials[c].number; ++c) { for (c = 0; con->materials[c].number; ++c) {
const requirement *rq = con->materials + c; const requirement *rq = con->materials + c;

View File

@ -906,11 +906,6 @@ int newcontainerid(void)
return random_no; return random_no;
} }
bool idle(faction * f)
{
return (bool)(f ? false : true);
}
int maxworkingpeasants(const struct region *r) int maxworkingpeasants(const struct region *r)
{ {
int size = production(r); int size = production(r);

View File

@ -179,7 +179,6 @@ extern "C" {
bool has_limited_skills(const struct unit *u); bool has_limited_skills(const struct unit *u);
const struct race *findrace(const char *, const struct locale *); const struct race *findrace(const char *, const struct locale *);
bool idle(struct faction *f);
bool unit_has_cursed_item(const struct unit *u); bool unit_has_cursed_item(const struct unit *u);
/* grammatik-flags: */ /* grammatik-flags: */

View File

@ -389,9 +389,8 @@ order *parse_order(const char *s, const struct locale * lang)
* \return true if the order is long * \return true if the order is long
* \sa is_exclusive(), is_repeated(), is_persistent() * \sa is_exclusive(), is_repeated(), is_persistent()
*/ */
bool is_repeated(const order * ord) bool is_repeated(keyword_t kwd)
{ {
keyword_t kwd = ORD_KEYWORD(ord);
switch (kwd) { switch (kwd) {
case K_CAST: case K_CAST:
case K_BUY: case K_BUY:
@ -468,10 +467,8 @@ bool is_exclusive(const order * ord)
* \return true if the order is long * \return true if the order is long
* \sa is_exclusive(), is_repeated(), is_persistent() * \sa is_exclusive(), is_repeated(), is_persistent()
*/ */
bool is_long(const order * ord) bool is_long(keyword_t kwd)
{ {
keyword_t kwd = ORD_KEYWORD(ord);
switch (kwd) { switch (kwd) {
case K_CAST: case K_CAST:
case K_BUY: case K_BUY:
@ -522,7 +519,7 @@ bool is_persistent(const order * ord)
case K_KOMMENTAR: case K_KOMMENTAR:
return true; return true;
default: default:
return ord->_persistent || is_repeated(ord); return ord->_persistent || is_repeated(kwd);
} }
} }

View File

@ -55,8 +55,8 @@ extern "C" {
char* get_command(const order *ord, char *buffer, size_t size); char* get_command(const order *ord, char *buffer, size_t size);
bool is_persistent(const order * ord); bool is_persistent(const order * ord);
bool is_exclusive(const order * ord); bool is_exclusive(const order * ord);
bool is_repeated(const order * ord); bool is_repeated(keyword_t kwd);
bool is_long(const order * ord); bool is_long(keyword_t kwd);
char *write_order(const order * ord, char *buffer, size_t size); char *write_order(const order * ord, char *buffer, size_t size);
keyword_t init_order(const struct order *ord); keyword_t init_order(const struct order *ord);

View File

@ -139,7 +139,8 @@ static unit *unitorders(FILE * F, int enc, struct faction *f)
ordp = &u->old_orders; ordp = &u->old_orders;
while (*ordp) { while (*ordp) {
order *ord = *ordp; order *ord = *ordp;
if (!is_repeated(ord)) { keyword_t kwd = getkeyword(ord);
if (!is_repeated(kwd)) {
*ordp = ord->next; *ordp = ord->next;
ord->next = NULL; ord->next = NULL;
free_order(ord); free_order(ord);
@ -777,7 +778,8 @@ void write_unit(struct gamedata *data, const unit * u)
} }
} }
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (u->old_orders && is_repeated(ord)) keyword_t kwd = getkeyword(ord);
if (u->old_orders && is_repeated(kwd))
continue; /* has new defaults */ continue; /* has new defaults */
if (is_persistent(ord)) { if (is_persistent(ord)) {
if (++p < MAXPERSISTENT) { if (++p < MAXPERSISTENT) {

View File

@ -3407,126 +3407,101 @@ void new_units(void)
} }
} }
/** Checks for two long orders and issues a warning if necessary.
*/
void check_long_orders(unit * u)
{
order *ord;
keyword_t otherorder = MAXKEYWORDS;
for (ord = u->orders; ord; ord = ord->next) {
if (getkeyword(ord) == NOKEYWORD) {
cmistake(u, ord, 22, MSG_EVENT);
}
else if (is_long(ord)) {
keyword_t longorder = getkeyword(ord);
if (otherorder != MAXKEYWORDS) {
switch (longorder) {
case K_CAST:
if (otherorder != longorder) {
cmistake(u, ord, 52, MSG_EVENT);
}
break;
case K_BUY:
if (otherorder == K_SELL) {
otherorder = K_BUY;
}
else {
cmistake(u, ord, 52, MSG_EVENT);
}
break;
case K_SELL:
if (otherorder != K_SELL && otherorder != K_BUY) {
cmistake(u, ord, 52, MSG_EVENT);
}
break;
default:
cmistake(u, ord, 52, MSG_EVENT);
}
}
else {
otherorder = longorder;
}
}
}
}
void update_long_order(unit * u) void update_long_order(unit * u)
{ {
order *ord; order *ord;
bool trade = false; bool exclusive = true;
keyword_t thiskwd = NOKEYWORD;
bool hunger = LongHunger(u); bool hunger = LongHunger(u);
freset(u, UFL_MOVED); freset(u, UFL_MOVED);
freset(u, UFL_LONGACTION); freset(u, UFL_LONGACTION);
if (hunger) {
/* Hungernde Einheiten führen NUR den default-Befehl aus */
set_order(&u->thisorder, default_order(u->faction->locale));
}
else {
check_long_orders(u);
}
/* check all orders for a potential new long order this round: */ /* check all orders for a potential new long order this round: */
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (getkeyword(ord) == NOKEYWORD) keyword_t kwd = getkeyword(ord);
continue; if (kwd == NOKEYWORD) continue;
if (u->old_orders && is_repeated(ord)) { if (u->old_orders && is_repeated(kwd)) {
/* this new order will replace the old defaults */ /* this new order will replace the old defaults */
free_orders(&u->old_orders); free_orders(&u->old_orders);
if (hunger)
break;
} }
if (hunger)
continue;
if (is_exclusive(ord)) { // hungry units do not get long orders:
/* Über dieser Zeile nur Befehle, die auch eine idle Faction machen darf */ if (hunger) {
if (idle(u->faction)) { if (u->old_orders) {
set_order(&u->thisorder, default_order(u->faction->locale)); // keep looking for repeated orders that might clear the old_orders
} continue;
else {
set_order(&u->thisorder, copy_order(ord));
} }
break; break;
} }
else {
keyword_t keyword = getkeyword(ord); if (is_long(kwd)) {
switch (keyword) { if (thiskwd == NOKEYWORD) {
// we have found the (first) long order
// some long orders can have multiple instances:
switch (kwd) {
/* Wenn gehandelt wird, darf kein langer Befehl ausgeführt /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt
* werden. Da Handel erst nach anderen langen Befehlen kommt, * werden. Da Handel erst nach anderen langen Befehlen kommt,
* muss das vorher abgefangen werden. Wir merken uns also * muss das vorher abgefangen werden. Wir merken uns also
* hier, ob die Einheit handelt. */ * hier, ob die Einheit handelt. */
case K_BUY: case K_BUY:
case K_SELL: case K_SELL:
/* Wenn die Einheit handelt, muss der Default-Befehl gelöscht
* werden.
* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
* mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
* nicht moeglich ist, Schulden zu machen. */
trade = true;
break;
case K_CAST: case K_CAST:
/* dient dazu, das neben Zaubern kein weiterer Befehl // non-exclusive orders can be used with others. BUY can be paired with SELL,
* ausgeführt werden kann, Zaubern ist ein kurzer Befehl */ // CAST with other CAST orders. compatibility is checked once the second
set_order(&u->thisorder, copy_order(ord)); // long order is analyzed (below).
exclusive = false;
break; break;
default: default:
set_order(&u->thisorder, copy_order(ord));
break;
}
thiskwd = kwd;
}
else {
// we have found a second long order. this is okay for some, but not all commands.
// u->thisorder is already set, and should not have to be updated.
switch (kwd) {
case K_CAST:
if (thiskwd != K_CAST) {
cmistake(u, ord, 52, MSG_EVENT);
}
break;
case K_SELL:
if (thiskwd != K_SELL && thiskwd != K_BUY) {
cmistake(u, ord, 52, MSG_EVENT);
}
break;
case K_BUY:
if (thiskwd != K_SELL) {
cmistake(u, ord, 52, MSG_EVENT);
}
else {
thiskwd = K_BUY;
}
break;
default:
#ifdef TODO // TODO: decide https://bugs.eressea.de/view.php?id=2080#c6011
if (kwd < thiskwd) {
/* swap thisorder for the new one */
order *tmp = ord;
ord = u->thisorder;
u->thisorder = tmp;
}
#endif
cmistake(u, ord, 52, MSG_EVENT);
break; break;
} }
} }
} }
if (hunger) {
return;
} }
/* Wenn die Einheit handelt, muss der Default-Befehl gelöscht if (hunger) {
* werden. */ // Hungernde Einheiten führen NUR den default-Befehl aus
set_order(&u->thisorder, default_order(u->faction->locale));
if (trade) { } else if (!exclusive) {
/* fset(u, UFL_LONGACTION|UFL_NOTMOVING); */ // Wenn die Einheit handelt oder zaubert, muss der Default-Befehl gelöscht werden.
set_order(&u->thisorder, NULL); set_order(&u->thisorder, NULL);
} }
} }
@ -3696,6 +3671,7 @@ void defaultorders(void)
free_order(ord); free_order(ord);
if (!neworders) { if (!neworders) {
/* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */ /* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */
// TODO: why only is_exclusive, not is_long? what about CAST, BUY, SELL?
remove_exclusive(&u->orders); remove_exclusive(&u->orders);
remove_exclusive(&u->old_orders); remove_exclusive(&u->old_orders);
neworders = true; neworders = true;

View File

@ -1471,14 +1471,12 @@ report_template(const char *filename, report_context * ctx, const char *charset)
newline(out); newline(out);
newline(out); newline(out);
sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f), sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f), f->passw);
LOC(f->locale, "enterpasswd"));
rps_nowrap(out, buf); rps_nowrap(out, buf);
newline(out); newline(out);
newline(out); newline(out);
sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost, sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost,
ECHECK_VERSION); ECHECK_VERSION);
/* -v3.4: ECheck Version 3.4.x */
rps_nowrap(out, buf); rps_nowrap(out, buf);
newline(out); newline(out);
@ -1575,7 +1573,8 @@ report_template(const char *filename, report_context * ctx, const char *charset)
newline(out); newline(out);
} }
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (u->old_orders && is_repeated(ord)) keyword_t kwd = getkeyword(ord);
if (u->old_orders && is_repeated(kwd))
continue; /* unit has defaults */ continue; /* unit has defaults */
if (is_persistent(ord)) { if (is_persistent(ord)) {
strcpy(buf, " "); strcpy(buf, " ");

View File

@ -793,7 +793,8 @@ size_t size)
bool printed = 0; bool printed = 0;
order *ord;; order *ord;;
for (ord = u->old_orders; ord; ord = ord->next) { for (ord = u->old_orders; ord; ord = ord->next) {
if (is_repeated(ord)) { keyword_t kwd = getkeyword(ord);
if (is_repeated(kwd)) {
if (printed < ORDERS_IN_NR) { if (printed < ORDERS_IN_NR) {
bytes = buforder(bufp, size, ord, printed++); bytes = buforder(bufp, size, ord, printed++);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
@ -805,7 +806,8 @@ size_t size)
} }
if (printed < ORDERS_IN_NR) if (printed < ORDERS_IN_NR)
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (is_repeated(ord)) { keyword_t kwd = getkeyword(ord);
if (is_repeated(kwd)) {
if (printed < ORDERS_IN_NR) { if (printed < ORDERS_IN_NR) {
bytes = buforder(bufp, size, ord, printed++); bytes = buforder(bufp, size, ord, printed++);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)