forked from github/server
Applying a patch provided by Solthar: Server will give error when unit is given more than one long order. I just added a test to this.
This commit is contained in:
parent
e7ce28a258
commit
d3a7d22253
|
@ -3800,7 +3800,7 @@
|
||||||
<arg name="command" type="order"/>
|
<arg name="command" type="order"/>
|
||||||
</type>
|
</type>
|
||||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude kann nur einmal pro Runde erweitert werden."</text>
|
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude kann nur einmal pro Runde erweitert werden."</text>
|
||||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - Thhe building can be expanded only once per turn."</text>
|
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building can be expanded only once per turn."</text>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message name="error317" section="events">
|
<message name="error317" section="events">
|
||||||
|
@ -6460,7 +6460,7 @@
|
||||||
<arg name="command" type="order"/>
|
<arg name="command" type="order"/>
|
||||||
</type>
|
</type>
|
||||||
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren langen Befehle ausführen."</text>
|
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren langen Befehle ausführen."</text>
|
||||||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is exhausted from battle."</text>
|
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot execute more long orders."</text>
|
||||||
</message>
|
</message>
|
||||||
<message name="error51" section="errors">
|
<message name="error51" section="errors">
|
||||||
<type>
|
<type>
|
||||||
|
|
|
@ -771,7 +771,6 @@ end
|
||||||
|
|
||||||
local function find_in_report(f, pattern, extension)
|
local function find_in_report(f, pattern, extension)
|
||||||
extension = extension or "nr"
|
extension = extension or "nr"
|
||||||
write_report(f)
|
|
||||||
local filename = config.basepath .. "/reports/" .. get_turn() .. "-" .. itoa36(f.id) .. "." .. extension
|
local filename = config.basepath .. "/reports/" .. get_turn() .. "-" .. itoa36(f.id) .. "." .. extension
|
||||||
local report = io.open(filename, 'rt');
|
local report = io.open(filename, 'rt');
|
||||||
t = report:read("*all")
|
t = report:read("*all")
|
||||||
|
@ -782,19 +781,13 @@ local function find_in_report(f, pattern, extension)
|
||||||
return start~=nil
|
return start~=nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local function assert_in_report(f, pattern, extension)
|
|
||||||
assert_not_equal(nil, find_in_report(f, pattern, extension))
|
|
||||||
end
|
|
||||||
local function assert_not_in_report(f, pattern, extension)
|
|
||||||
assert_equal(nil, find_in_report(f, pattern, extension))
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_coordinates_no_plane()
|
function test_coordinates_no_plane()
|
||||||
local r = region.create(0, 0, "mountain")
|
local r = region.create(0, 0, "mountain")
|
||||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||||
local u = unit.create(f, r, 1)
|
local u = unit.create(f, r, 1)
|
||||||
init_reports()
|
init_reports()
|
||||||
assert_in_report(f, r.name .. " %(0,0%), Berg")
|
write_report(f)
|
||||||
|
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_coordinates_named_plane()
|
function test_coordinates_named_plane()
|
||||||
|
@ -803,7 +796,8 @@ function test_coordinates_named_plane()
|
||||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||||
local u = unit.create(f, r, 1)
|
local u = unit.create(f, r, 1)
|
||||||
init_reports()
|
init_reports()
|
||||||
assert_in_report(f, r.name .. " %(0,0,Hell%), Berg")
|
write_report(f)
|
||||||
|
assert_true(find_in_report(f, r.name .. " %(0,0,Hell%), Berg"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_coordinates_unnamed_plane()
|
function test_coordinates_unnamed_plane()
|
||||||
|
@ -812,7 +806,8 @@ function test_coordinates_unnamed_plane()
|
||||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||||
local u = unit.create(f, r, 1)
|
local u = unit.create(f, r, 1)
|
||||||
init_reports()
|
init_reports()
|
||||||
assert_in_report(f, r.name .. " %(0,0%), Berg")
|
write_report(f)
|
||||||
|
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_coordinates_noname_plane()
|
function test_coordinates_noname_plane()
|
||||||
|
@ -821,7 +816,8 @@ function test_coordinates_noname_plane()
|
||||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||||
local u = unit.create(f, r, 1)
|
local u = unit.create(f, r, 1)
|
||||||
init_reports()
|
init_reports()
|
||||||
assert_in_report(f, r.name .. " %(0,0%), Berg")
|
write_report(f)
|
||||||
|
assert_true(find_in_report(f, r.name .. " %(0,0%), Berg"))
|
||||||
end
|
end
|
||||||
|
|
||||||
module( "parser", package.seeall, lunit.testcase )
|
module( "parser", package.seeall, lunit.testcase )
|
||||||
|
@ -864,5 +860,28 @@ function test_bug_1814()
|
||||||
read_orders(filename)
|
read_orders(filename)
|
||||||
process_orders()
|
process_orders()
|
||||||
init_reports()
|
init_reports()
|
||||||
|
write_report(f)
|
||||||
assert_false(find_in_report(f, "Der Befehl wurde nicht erkannt", "cr"))
|
assert_false(find_in_report(f, "Der Befehl wurde nicht erkannt", "cr"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function test_bug_1679()
|
||||||
|
-- see http://bugs.eressea.de/view.php?id=1679
|
||||||
|
local r = region.create(0, 0, "mountain")
|
||||||
|
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||||
|
local u = unit.create(f, r, 1)
|
||||||
|
local filename = "1814.txt"
|
||||||
|
|
||||||
|
local file = io.open(filename, "w+")
|
||||||
|
file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n')
|
||||||
|
file:write('EINHEIT ' .. itoa36(u.id) .. "\n")
|
||||||
|
file:write("NACH W\n")
|
||||||
|
file:write("ARBEITEN\n")
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
read_orders(filename)
|
||||||
|
process_orders()
|
||||||
|
init_reports()
|
||||||
|
write_report(f)
|
||||||
|
assert_true(find_in_report(f, "Die Einheit kann keine weiteren langen Befehle", "cr"))
|
||||||
|
assert_true(find_in_report(f, "entdeckt, dass es keinen Weg nach Westen gibt"))
|
||||||
|
end
|
||||||
|
|
|
@ -3349,7 +3349,9 @@ 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
|
||||||
cmistake(u, u->thisorder, 52, MSG_PRODUCE);
|
cmistake(u, u->thisorder, 52, MSG_PRODUCE);
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3335,6 +3335,48 @@ 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 (get_keyword(ord) == NOKEYWORD) {
|
||||||
|
cmistake(u, ord, 22, MSG_EVENT);
|
||||||
|
} else if (is_long(ord)) {
|
||||||
|
keyword_t longorder = get_keyword(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;
|
||||||
|
case K_WEREWOLF:
|
||||||
|
/* don't know what WEREWOLF does... */
|
||||||
|
default:
|
||||||
|
cmistake(u, ord, 52, MSG_EVENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
otherorder = longorder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setdefaults(unit *u)
|
setdefaults(unit *u)
|
||||||
{
|
{
|
||||||
|
@ -3346,9 +3388,14 @@ setdefaults(unit *u)
|
||||||
if (hunger) {
|
if (hunger) {
|
||||||
/* Hungernde Einheiten führen NUR den default-Befehl aus */
|
/* Hungernde Einheiten führen NUR den default-Befehl aus */
|
||||||
set_order(&u->thisorder, default_order(u->faction->locale));
|
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 (get_keyword(ord) == NOKEYWORD)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (u->old_orders && is_repeated(ord)) {
|
if (u->old_orders && is_repeated(ord)) {
|
||||||
/* 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);
|
||||||
|
@ -3371,9 +3418,6 @@ setdefaults(unit *u)
|
||||||
* werden. Da Handel erst nach anderen langen Befehlen kommt,
|
* werden. Da Handel erst nach anderen langen Befehlen kommt,
|
||||||
* muß das vorher abgefangen werden. Wir merken uns also
|
* muß das vorher abgefangen werden. Wir merken uns also
|
||||||
* hier, ob die Einheit handelt. */
|
* hier, ob die Einheit handelt. */
|
||||||
case NOKEYWORD:
|
|
||||||
cmistake(u, ord, 22, MSG_EVENT);
|
|
||||||
break;
|
|
||||||
case K_BUY:
|
case K_BUY:
|
||||||
case K_SELL:
|
case K_SELL:
|
||||||
/* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
|
/* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
|
||||||
|
@ -3872,7 +3916,8 @@ process(void)
|
||||||
porder = punit;
|
porder = punit;
|
||||||
while (porder && porder->priority==prio && porder->type==PR_ORDER) {
|
while (porder && porder->priority==prio && porder->type==PR_ORDER) {
|
||||||
order ** ordp = &u->orders;
|
order ** ordp = &u->orders;
|
||||||
if (porder->flags & PROC_THISORDER) ordp = &u->thisorder;
|
if (porder->flags & PROC_THISORDER)
|
||||||
|
ordp = &u->thisorder;
|
||||||
while (*ordp) {
|
while (*ordp) {
|
||||||
order * ord = *ordp;
|
order * ord = *ordp;
|
||||||
if (get_keyword(ord) == porder->data.per_order.kword) {
|
if (get_keyword(ord) == porder->data.per_order.kword) {
|
||||||
|
@ -3885,7 +3930,9 @@ process(void)
|
||||||
cmistake(u, ord, 224, MSG_MAGIC);
|
cmistake(u, ord, 224, MSG_MAGIC);
|
||||||
ord = NULL;
|
ord = NULL;
|
||||||
} else if (fval(u, UFL_LONGACTION)) {
|
} else if (fval(u, UFL_LONGACTION)) {
|
||||||
|
/* this message was already given in laws.setdefaults
|
||||||
cmistake(u, ord, 52, MSG_PRODUCE);
|
cmistake(u, ord, 52, MSG_PRODUCE);
|
||||||
|
*/
|
||||||
ord = NULL;
|
ord = NULL;
|
||||||
} else if (fval(r->terrain, SEA_REGION) && u->race != new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) {
|
} else if (fval(r->terrain, SEA_REGION) && u->race != new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) {
|
||||||
/* error message disabled by popular demand */
|
/* error message disabled by popular demand */
|
||||||
|
|
|
@ -361,6 +361,14 @@ parse_order(const char * s, const struct locale * lang)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the order qualifies as "repeated". An order is repeated if it will overwrite the
|
||||||
|
* old default order. K_BUY is in this category, but not K_MOVE.
|
||||||
|
*
|
||||||
|
* \param ord An order.
|
||||||
|
* \return true if the order is long
|
||||||
|
* \sa is_exclusive(), is_repeated(), is_persistent()
|
||||||
|
*/
|
||||||
boolean
|
boolean
|
||||||
is_repeated(const order * ord)
|
is_repeated(const order * ord)
|
||||||
{
|
{
|
||||||
|
@ -420,6 +428,14 @@ is_repeated(const order * ord)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the order qualifies as "exclusive". An order is exclusive if it makes all other
|
||||||
|
* long orders illegal. K_MOVE is in this category, but not K_BUY.
|
||||||
|
*
|
||||||
|
* \param ord An order.
|
||||||
|
* \return true if the order is long
|
||||||
|
* \sa is_exclusive(), is_repeated(), is_persistent()
|
||||||
|
*/
|
||||||
boolean
|
boolean
|
||||||
is_exclusive(const order * ord)
|
is_exclusive(const order * ord)
|
||||||
{
|
{
|
||||||
|
@ -479,6 +495,84 @@ is_exclusive(const order * ord)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the order qualifies as "long". An order is long if it excludes most other long
|
||||||
|
* orders.
|
||||||
|
*
|
||||||
|
* \param ord An order.
|
||||||
|
* \return true if the order is long
|
||||||
|
* \sa is_exclusive(), is_repeated(), is_persistent()
|
||||||
|
*/
|
||||||
|
boolean
|
||||||
|
is_long(const order * ord)
|
||||||
|
{
|
||||||
|
keyword_t kwd = ORD_KEYWORD(ord);
|
||||||
|
const struct locale * lang = ORD_LOCALE(ord);
|
||||||
|
param_t param;
|
||||||
|
|
||||||
|
switch (kwd) {
|
||||||
|
case K_CAST:
|
||||||
|
case K_BUY:
|
||||||
|
case K_SELL:
|
||||||
|
case K_MOVE:
|
||||||
|
case K_WEREWOLF:
|
||||||
|
case K_ROUTE:
|
||||||
|
case K_DRIVE:
|
||||||
|
case K_WORK:
|
||||||
|
case K_BESIEGE:
|
||||||
|
case K_ENTERTAIN:
|
||||||
|
case K_TAX:
|
||||||
|
case K_RESEARCH:
|
||||||
|
case K_SPY:
|
||||||
|
case K_STEAL:
|
||||||
|
case K_SABOTAGE:
|
||||||
|
case K_STUDY:
|
||||||
|
case K_TEACH:
|
||||||
|
case K_BREED:
|
||||||
|
case K_PIRACY:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case K_PLANT:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case K_FOLLOW:
|
||||||
|
/* FOLLOW is only a long order if we are following a ship. */
|
||||||
|
parser_pushstate();
|
||||||
|
init_tokens(ord);
|
||||||
|
skip_token();
|
||||||
|
param = getparam(lang);
|
||||||
|
parser_popstate();
|
||||||
|
|
||||||
|
if (param == P_SHIP) return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_MAKE:
|
||||||
|
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
|
||||||
|
* Arten von MACHE zaehlen aber als neue defaults und werden
|
||||||
|
* behandelt wie die anderen (deswegen kein break nach case
|
||||||
|
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
|
||||||
|
* abgespeichert). */
|
||||||
|
parser_pushstate();
|
||||||
|
init_tokens(ord); /* initialize token-parser */
|
||||||
|
skip_token();
|
||||||
|
param = getparam(lang);
|
||||||
|
parser_popstate();
|
||||||
|
|
||||||
|
if (param != P_TEMP) return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the order qualifies as "persistent". An order is persistent if it will be
|
||||||
|
* included in the template orders. @-orders, comments and most long orders are in this category,
|
||||||
|
* but not K_MOVE.
|
||||||
|
*
|
||||||
|
* \param ord An order.
|
||||||
|
* \return true if the order is persistent
|
||||||
|
* \sa is_exclusive(), is_repeated(), is_persistent()
|
||||||
|
*/
|
||||||
boolean
|
boolean
|
||||||
is_persistent(const order * ord)
|
is_persistent(const order * ord)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@ extern char * getcommand(const order * ord);
|
||||||
extern boolean is_persistent(const order *ord);
|
extern boolean is_persistent(const order *ord);
|
||||||
extern boolean is_exclusive(const order *ord);
|
extern boolean is_exclusive(const order *ord);
|
||||||
extern boolean is_repeated(const order * ord);
|
extern boolean is_repeated(const order * ord);
|
||||||
|
extern boolean is_long(const order *ord);
|
||||||
|
|
||||||
extern char * write_order(const order * ord, char * buffer, size_t size);
|
extern char * write_order(const order * ord, char * buffer, size_t size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue