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"/>
|
||||
</type>
|
||||
<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 name="error317" section="events">
|
||||
|
@ -6460,7 +6460,7 @@
|
|||
<arg name="command" type="order"/>
|
||||
</type>
|
||||
<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 name="error51" section="errors">
|
||||
<type>
|
||||
|
|
|
@ -771,7 +771,6 @@ end
|
|||
|
||||
local function find_in_report(f, pattern, extension)
|
||||
extension = extension or "nr"
|
||||
write_report(f)
|
||||
local filename = config.basepath .. "/reports/" .. get_turn() .. "-" .. itoa36(f.id) .. "." .. extension
|
||||
local report = io.open(filename, 'rt');
|
||||
t = report:read("*all")
|
||||
|
@ -782,19 +781,13 @@ local function find_in_report(f, pattern, extension)
|
|||
return start~=nil
|
||||
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()
|
||||
local r = region.create(0, 0, "mountain")
|
||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
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
|
||||
|
||||
function test_coordinates_named_plane()
|
||||
|
@ -803,7 +796,8 @@ function test_coordinates_named_plane()
|
|||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
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
|
||||
|
||||
function test_coordinates_unnamed_plane()
|
||||
|
@ -812,7 +806,8 @@ function test_coordinates_unnamed_plane()
|
|||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
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
|
||||
|
||||
function test_coordinates_noname_plane()
|
||||
|
@ -821,7 +816,8 @@ function test_coordinates_noname_plane()
|
|||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 1)
|
||||
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
|
||||
|
||||
module( "parser", package.seeall, lunit.testcase )
|
||||
|
@ -864,5 +860,28 @@ function test_bug_1814()
|
|||
read_orders(filename)
|
||||
process_orders()
|
||||
init_reports()
|
||||
write_report(f)
|
||||
assert_false(find_in_report(f, "Der Befehl wurde nicht erkannt", "cr"))
|
||||
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;
|
||||
|
||||
if (fval(u, UFL_LONGACTION) && u->thisorder==NULL) {
|
||||
/* this message was already given in laws.setdefaults
|
||||
cmistake(u, u->thisorder, 52, MSG_PRODUCE);
|
||||
*/
|
||||
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
|
||||
setdefaults(unit *u)
|
||||
{
|
||||
|
@ -3346,9 +3388,14 @@ setdefaults(unit *u)
|
|||
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: */
|
||||
for (ord = u->orders; ord; ord = ord->next) {
|
||||
if (get_keyword(ord) == NOKEYWORD)
|
||||
continue;
|
||||
|
||||
if (u->old_orders && is_repeated(ord)) {
|
||||
/* this new order will replace the old defaults */
|
||||
free_orders(&u->old_orders);
|
||||
|
@ -3371,9 +3418,6 @@ setdefaults(unit *u)
|
|||
* werden. Da Handel erst nach anderen langen Befehlen kommt,
|
||||
* muß das vorher abgefangen werden. Wir merken uns also
|
||||
* hier, ob die Einheit handelt. */
|
||||
case NOKEYWORD:
|
||||
cmistake(u, ord, 22, MSG_EVENT);
|
||||
break;
|
||||
case K_BUY:
|
||||
case K_SELL:
|
||||
/* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
|
||||
|
@ -3872,7 +3916,8 @@ process(void)
|
|||
porder = punit;
|
||||
while (porder && porder->priority==prio && porder->type==PR_ORDER) {
|
||||
order ** ordp = &u->orders;
|
||||
if (porder->flags & PROC_THISORDER) ordp = &u->thisorder;
|
||||
if (porder->flags & PROC_THISORDER)
|
||||
ordp = &u->thisorder;
|
||||
while (*ordp) {
|
||||
order * ord = *ordp;
|
||||
if (get_keyword(ord) == porder->data.per_order.kword) {
|
||||
|
@ -3885,7 +3930,9 @@ process(void)
|
|||
cmistake(u, ord, 224, MSG_MAGIC);
|
||||
ord = NULL;
|
||||
} else if (fval(u, UFL_LONGACTION)) {
|
||||
/* this message was already given in laws.setdefaults
|
||||
cmistake(u, ord, 52, MSG_PRODUCE);
|
||||
*/
|
||||
ord = NULL;
|
||||
} else if (fval(r->terrain, SEA_REGION) && u->race != new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) {
|
||||
/* error message disabled by popular demand */
|
||||
|
|
|
@ -361,6 +361,14 @@ parse_order(const char * s, const struct locale * lang)
|
|||
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
|
||||
is_repeated(const order * ord)
|
||||
{
|
||||
|
@ -420,6 +428,14 @@ is_repeated(const order * ord)
|
|||
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
|
||||
is_exclusive(const order * ord)
|
||||
{
|
||||
|
@ -479,6 +495,84 @@ is_exclusive(const order * ord)
|
|||
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
|
||||
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_exclusive(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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue