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:
Enno Rehling 2010-11-11 20:11:19 -08:00
parent e7ce28a258
commit d3a7d22253
6 changed files with 181 additions and 18 deletions

View File

@ -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>

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)
{

View File

@ -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);