diff --git a/res/core/messages.xml b/res/core/messages.xml
index 4e78fc094..237ab8c7a 100644
--- a/res/core/messages.xml
+++ b/res/core/messages.xml
@@ -2830,17 +2830,6 @@
"$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."
"$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."
-
-
-
-
-
-
-
-
- "$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."
- "$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."
-
diff --git a/scripts/eressea/jsreport.lua b/scripts/eressea/jsreport.lua
index 442b27d5f..0351efd12 100644
--- a/scripts/eressea/jsreport.lua
+++ b/scripts/eressea/jsreport.lua
@@ -1,7 +1,5 @@
local pkg = {}
-print("loading jsreport module")
-
function pkg.init()
eressea.settings.set("feature.jsreport.enable", "1")
end
diff --git a/scripts/tests/e3/rules.lua b/scripts/tests/e3/rules.lua
index 0e9d52147..902a91741 100644
--- a/scripts/tests/e3/rules.lua
+++ b/scripts/tests/e3/rules.lua
@@ -460,7 +460,6 @@ function test_canoe_passes_through_land()
u1:add_order("NACH O O O")
process_orders()
assert_equal(land, u2.region, "canoe did not stop at coast")
- u1:add_order("NACH O O O")
process_orders()
assert_equal(dst, sh.region, "canoe could not leave coast")
assert_equal(dst, u1.region, "canoe could not leave coast")
diff --git a/scripts/tests/e3/spells.lua b/scripts/tests/e3/spells.lua
index c4f0aadaf..f99e4687b 100644
--- a/scripts/tests/e3/spells.lua
+++ b/scripts/tests/e3/spells.lua
@@ -58,7 +58,6 @@ function test_magic()
u:add_spell("protective_runes")
u:add_spell("analyze_magic")
u:clear_orders()
- u:add_order("ZAUBERE \"Runen des Schutzes\" BURG " .. itoa36(b.id));
u.building = b
u:add_order("ZAUBERE \"Magie analysieren\" BURG " .. itoa36(b.id));
process_orders()
diff --git a/src/battle.c b/src/battle.c
index 4719da5b7..d45cf02e7 100644
--- a/src/battle.c
+++ b/src/battle.c
@@ -3232,7 +3232,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack)
}
/* 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;
}
if (s1 == NULL) {
diff --git a/src/creport.c b/src/creport.c
index 38e63e299..fefd7934e 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -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) {
- if (u->old_orders && is_repeated(ord))
+ keyword_t kwd = getkeyword(ord);
+ if (u->old_orders && is_repeated(kwd))
continue; /* unit has defaults */
if (is_persistent(ord)) {
fwriteorder(F, ord, f->locale, true);
diff --git a/src/economy.c b/src/economy.c
index 23ccb3fde..8cf46845b 100644
--- a/src/economy.c
+++ b/src/economy.c
@@ -563,7 +563,7 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
return;
}
}
- if (!playerrace(rc) || idle(u->faction)) {
+ if (!playerrace(rc)) {
cmistake(u, ord, 139, MSG_EVENT);
return;
}
@@ -979,26 +979,13 @@ void economics(region * r)
remove_empty_units_in_region(r);
for (u = r->units; u; u = u->next) {
- order *ord;
- bool destroyed = false;
- if (u->number > 0) {
- for (ord = u->orders; ord; ord = ord->next) {
- keyword_t kwd = getkeyword(ord);
- if (kwd == K_DESTROY) {
- if (!destroyed) {
- if (destroy_cmd(u, ord) != 0)
- ord = NULL;
- destroyed = true;
- }
- }
- if (u->orders == NULL) {
- break;
- }
+ order *ord = u->thisorder;
+ keyword_t kwd = getkeyword(ord);
+ if (kwd == K_DESTROY) {
+ if (destroy_cmd(u, ord) == 0) {
+ fset(u, UFL_LONGACTION | UFL_NOTMOVING);
}
}
- if (destroyed) {
- 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);
if (want == INT_MAX)
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,
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);
if (want == INT_MAX)
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,
ptype->itype->rtype));
break;
@@ -3216,7 +3203,7 @@ void produce(struct region *r)
continue;
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);
*/
continue;
diff --git a/src/kernel/build.c b/src/kernel/build.c
index fcb116741..37006e968 100644
--- a/src/kernel/build.c
+++ b/src/kernel/build.c
@@ -151,11 +151,11 @@ int destroy_cmd(unit * u, struct order *ord)
int n = INT_MAX;
if (u->number < 1)
- return 0;
+ return 1;
if (fval(u, UFL_LONGACTION)) {
cmistake(u, ord, 52, MSG_PRODUCE);
- return 0;
+ return 52;
}
init_order(ord);
@@ -183,11 +183,11 @@ int destroy_cmd(unit * u, struct order *ord)
if (u != building_owner(b)) {
cmistake(u, ord, 138, MSG_PRODUCE);
- return 0;
+ return 138;
}
if (fval(b->type, BTF_INDESTRUCTIBLE)) {
cmistake(u, ord, 138, MSG_PRODUCE);
- return 0;
+ return 138;
}
if (n >= b->size) {
/* destroy completly */
@@ -213,11 +213,11 @@ int destroy_cmd(unit * u, struct order *ord)
if (u != ship_owner(sh)) {
cmistake(u, ord, 138, MSG_PRODUCE);
- return 0;
+ return 138;
}
if (fval(r->terrain, SEA_REGION)) {
cmistake(u, ord, 14, MSG_EVENT);
- return 0;
+ return 14;
}
if (n >= (sh->size * 100) / sh->type->construction->maxsize) {
@@ -242,11 +242,11 @@ int destroy_cmd(unit * u, struct order *ord)
}
else {
cmistake(u, ord, 138, MSG_PRODUCE);
- return 0;
+ return 138;
}
if (con) {
- /* TODO: Nicht an ZERSTÖRE mit Punktangabe angepaßt! */
+ /* TODO: Nicht an ZERSTÖRE mit Punktangabe angepasst! */
int c;
for (c = 0; con->materials[c].number; ++c) {
const requirement *rq = con->materials + c;
diff --git a/src/kernel/config.c b/src/kernel/config.c
index ee8a2638c..9c26ad85a 100644
--- a/src/kernel/config.c
+++ b/src/kernel/config.c
@@ -530,7 +530,9 @@ int alliedunit(const unit * u, const faction * f2, int mode)
ally *sf;
int automode;
- assert(u && u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */
+ assert(u);
+ assert(f2);
+ assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */
if (u->faction == f2)
return mode;
if (u->faction != NULL && f2 != NULL) {
@@ -904,11 +906,6 @@ int newcontainerid(void)
return random_no;
}
-bool idle(faction * f)
-{
- return (bool)(f ? false : true);
-}
-
int maxworkingpeasants(const struct region *r)
{
int size = production(r);
@@ -922,6 +919,10 @@ static const char * parameter_key(int i)
return parameters[i];
}
+void init_parameters(struct locale *lang) {
+ init_translations(lang, UT_PARAMS, parameter_key, MAXPARAMS);
+}
+
void init_terrains_translation(const struct locale *lang) {
void **tokens;
@@ -1012,7 +1013,7 @@ void init_locale(struct locale *lang)
if (name) addtoken(tokens, name, var);
}
- init_translations(lang, UT_PARAMS, parameter_key, MAXPARAMS);
+ init_parameters(lang);
init_options_translation(lang);
init_terrains_translation(lang);
@@ -1684,6 +1685,11 @@ void kernel_init(void)
}
static order * defaults[MAXLOCALES];
+keyword_t default_keyword = NOKEYWORD;
+
+void set_default_order(int kwd) {
+ default_keyword = (keyword_t)kwd;
+}
order *default_order(const struct locale *lang)
{
@@ -1691,6 +1697,11 @@ order *default_order(const struct locale *lang)
int i = locale_index(lang);
order *result = 0;
assert(i < MAXLOCALES);
+
+ if (default_keyword!=NOKEYWORD) {
+ return create_order(default_keyword, lang, 0);
+ }
+
result = defaults[i];
if (!result && usedefault) {
const char * str = LOC(lang, "defaultorder");
diff --git a/src/kernel/config.h b/src/kernel/config.h
index 4ca76871c..056de8f84 100644
--- a/src/kernel/config.h
+++ b/src/kernel/config.h
@@ -179,7 +179,6 @@ extern "C" {
bool has_limited_skills(const struct unit *u);
const struct race *findrace(const char *, const struct locale *);
- bool idle(struct faction *f);
bool unit_has_cursed_item(const struct unit *u);
/* grammatik-flags: */
@@ -287,8 +286,12 @@ extern "C" {
int AllianceAuto(void); /* flags that allied factions get automatically */
int AllianceRestricted(void); /* flags restricted to allied factions */
int HelpMask(void); /* flags restricted to allied factions */
+
struct order *default_order(const struct locale *lang);
+ void set_default_order(int kwd);
+
int entertainmoney(const struct region *r);
+ void init_parameters(struct locale *lang);
void free_gamedata(void);
diff --git a/src/kernel/messages.c b/src/kernel/messages.c
index e0efdd04b..28625ff85 100644
--- a/src/kernel/messages.c
+++ b/src/kernel/messages.c
@@ -285,8 +285,9 @@ extern unsigned int new_hashstring(const char *s);
void free_messagelist(message_list * msgs)
{
- struct mlist **mlistptr = &msgs->begin;
- while (*mlistptr) {
+ struct mlist **mlistptr;
+ assert(msgs && msgs->begin);
+ for (mlistptr = &msgs->begin; *mlistptr;) {
struct mlist *ml = *mlistptr;
*mlistptr = ml->next;
msg_release(ml->msg);
diff --git a/src/kernel/order.c b/src/kernel/order.c
index 20cce5853..008bfe0fe 100644
--- a/src/kernel/order.c
+++ b/src/kernel/order.c
@@ -252,6 +252,19 @@ static order_data *create_data(keyword_t kwd, const char *sptr, int lindex)
return data;
}
+static void free_localedata(int lindex) {
+ int i;
+ for (i = 0; i != MAXKEYWORDS; ++i) {
+ release_data(locale_array[lindex]->short_orders[i]);
+ locale_array[lindex]->short_orders[i] = 0;
+ }
+ for (i = 0; i != MAXSKILLS; ++i) {
+ release_data(locale_array[lindex]->study_orders[i]);
+ locale_array[lindex]->study_orders[i] = 0;
+ }
+ locale_array[lindex]->lang = 0;
+}
+
static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent,
const struct locale *lang)
{
@@ -276,7 +289,12 @@ static order *create_order_i(keyword_t kwd, const char *sptr, bool persistent,
lindex = locale_index(lang);
assert(lindex < MAXLOCALES);
- locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data));
+ if (!locale_array[lindex]) {
+ locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data));
+ }
+ else if (locale_array[lindex]->lang != lang) {
+ free_localedata(lindex);
+ }
locale_array[lindex]->lang = lang;
ord = (order *)malloc(sizeof(order));
@@ -292,13 +310,13 @@ order *create_order(keyword_t kwd, const struct locale * lang,
const char *params, ...)
{
char zBuffer[DISPLAYSIZE];
- assert(lang);
if (params) {
char *bufp = zBuffer;
int bytes;
size_t size = sizeof(zBuffer) - 1;
va_list marker;
+ assert(lang);
va_start(marker, params);
while (*params) {
if (*params == '%') {
@@ -389,9 +407,8 @@ order *parse_order(const char *s, const struct locale * lang)
* \return true if the order is long
* \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) {
case K_CAST:
case K_BUY:
@@ -468,10 +485,8 @@ bool is_exclusive(const order * ord)
* \return true if the order is long
* \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) {
case K_CAST:
case K_BUY:
@@ -522,7 +537,7 @@ bool is_persistent(const order * ord)
case K_KOMMENTAR:
return true;
default:
- return ord->_persistent || is_repeated(ord);
+ return ord->_persistent || is_repeated(kwd);
}
}
diff --git a/src/kernel/order.h b/src/kernel/order.h
index 27c61681c..75d741e42 100644
--- a/src/kernel/order.h
+++ b/src/kernel/order.h
@@ -55,8 +55,8 @@ extern "C" {
char* get_command(const order *ord, char *buffer, size_t size);
bool is_persistent(const order * ord);
bool is_exclusive(const order * ord);
- bool is_repeated(const order * ord);
- bool is_long(const order * ord);
+ bool is_repeated(keyword_t kwd);
+ bool is_long(keyword_t kwd);
char *write_order(const order * ord, char *buffer, size_t size);
keyword_t init_order(const struct order *ord);
diff --git a/src/kernel/save.c b/src/kernel/save.c
index d997c3216..1d610d013 100644
--- a/src/kernel/save.c
+++ b/src/kernel/save.c
@@ -139,7 +139,8 @@ static unit *unitorders(FILE * F, int enc, struct faction *f)
ordp = &u->old_orders;
while (*ordp) {
order *ord = *ordp;
- if (!is_repeated(ord)) {
+ keyword_t kwd = getkeyword(ord);
+ if (!is_repeated(kwd)) {
*ordp = ord->next;
ord->next = NULL;
free_order(ord);
@@ -233,7 +234,7 @@ static faction *factionorders(void)
f->no, pass));
return 0;
}
- /* Die Partei hat sich zumindest gemeldet, so daß sie noch
+ /* Die Partei hat sich zumindest gemeldet, so dass sie noch
* nicht als untätig gilt */
/* TODO: +1 ist ein Workaround, weil cturn erst in process_orders
@@ -309,8 +310,8 @@ int readorders(const char *filename)
* Partei, eine neue Einheit oder das File-Ende. Das switch() wird erneut
* durchlaufen, und die entsprechende Funktion aufgerufen. Man darf buf
* auf alle Fälle nicht überschreiben! Bei allen anderen Einträgen hier
- * muß buf erneut gefüllt werden, da die betreffende Information in nur
- * einer Zeile steht, und nun die nächste gelesen werden muß. */
+ * muss buf erneut gefüllt werden, da die betreffende Information in nur
+ * einer Zeile steht, und nun die nächste gelesen werden muss. */
case P_NEXT:
f = NULL;
@@ -777,7 +778,8 @@ void write_unit(struct gamedata *data, const unit * u)
}
}
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 */
if (is_persistent(ord)) {
if (++p < MAXPERSISTENT) {
@@ -1603,7 +1605,6 @@ int readgame(const char *filename, bool backup)
while (--p >= 0) {
unit *u = read_unit(&gdata);
- sc_mage *mage;
if (gdata.version < JSON_REPORT_VERSION) {
if (u->_name && fval(u->faction, FFL_NPC)) {
@@ -1618,21 +1619,6 @@ int readgame(const char *filename, bool backup)
up = &u->next;
update_interval(u->faction, u->region);
- mage = get_mage(u);
- if (mage) {
- faction *f = u->faction;
- int skl = effskill(u, SK_MAGIC);
- if (!fval(f, FFL_NPC) && f->magiegebiet == M_GRAY) {
- log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]);
- f->magiegebiet = mage->magietyp;
- }
- if (f->max_spelllevel < skl) {
- f->max_spelllevel = skl;
- }
- if (mage->spellcount < 0) {
- mage->spellcount = 0;
- }
- }
}
}
log_printf(stdout, "\n");
@@ -1656,6 +1642,7 @@ int readgame(const char *filename, bool backup)
for (f = factions; f; f = f->next) {
if (f->flags & FFL_NPC) {
f->alive = 1;
+ f->magiegebiet = M_GRAY;
if (f->no == 0) {
int no = 666;
while (findfaction(no))
@@ -1666,8 +1653,23 @@ int readgame(const char *filename, bool backup)
}
else {
for (u = f->units; u; u = u->nextF) {
+ sc_mage *mage = get_mage(u);
+ if (mage) {
+ faction *f = u->faction;
+ int skl = effskill(u, SK_MAGIC);
+ if (f->magiegebiet == M_GRAY) {
+ log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]);
+ f->magiegebiet = mage->magietyp;
+ }
+ if (f->max_spelllevel < skl) {
+ f->max_spelllevel = skl;
+ }
+ if (mage->spellcount < 0) {
+ mage->spellcount = 0;
+ }
+ }
if (u->number > 0) {
- f->alive = 1;
+ f->alive = true;
break;
}
}
diff --git a/src/kernel/unit.c b/src/kernel/unit.c
index a43ae2153..85e558fd2 100644
--- a/src/kernel/unit.c
+++ b/src/kernel/unit.c
@@ -1274,25 +1274,10 @@ static int item_modification(const unit * u, skill_t sk, int val)
return val;
}
-static int update_gbdream(const unit * u, int bonus, curse *c, const curse_type *gbdream_ct, int sign){
- if (curse_active(c) && c->type == gbdream_ct) {
- double effect = curse_geteffect(c);
- unit *mage = c->magician;
- /* wir suchen jeweils den groessten Bonus und den groestsen Malus */
- if (sign * effect > sign * bonus) {
- if (mage == NULL || mage->number == 0
- || (sign>0?alliedunit(mage, u->faction, HELP_GUARD):!alliedunit(mage, u->faction, HELP_GUARD))) {
- bonus = (int)effect;
- }
- }
- }
- return bonus;
-}
-
-int att_modification(const unit * u, skill_t sk)
+static int att_modification(const unit * u, skill_t sk)
{
double result = 0;
- static bool init = false;
+ static bool init = false; // TODO: static variables are bad global state
static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct;
curse *c;
@@ -1321,15 +1306,21 @@ int att_modification(const unit * u, skill_t sk)
/* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der
* jeweils erste vom Typ C_GBDREAM zurueckgegen wird, wir aber alle
* durchsuchen und aufaddieren muessen */
- if (u->region) {
+ if (gbdream_ct && u->region) {
int bonus = 0, malus = 0;
attrib *a = a_find(u->region->attribs, &at_curse);
while (a && a->type == &at_curse) {
curse *c = (curse *)a->data.v;
- bonus = update_gbdream(u, bonus, c, gbdream_ct, 1);
- malus = update_gbdream(u, malus, c, gbdream_ct, -1);
-
+ if (curse_active(c) && c->type == gbdream_ct) {
+ int effect = curse_geteffect_int(c);
+ bool allied = alliedunit(c->magician, u->faction, HELP_GUARD);
+ if (allied) {
+ if (effect > bonus) bonus = effect;
+ } else {
+ if (effect < malus) malus = effect;
+ }
+ }
a = a->next;
}
result = result + bonus + malus;
diff --git a/src/laws.c b/src/laws.c
index 6a18dc84e..3f68294fb 100755
--- a/src/laws.c
+++ b/src/laws.c
@@ -183,7 +183,7 @@ static void live(region * r)
reduce_skill(u, sb, weeks);
ADDMSG(&u->faction->msgs, msg_message("dumbeffect",
"unit weeks skill", u, weeks, (skill_t)sb->id));
- } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */
+ } /* sonst Glück gehabt: wer nix weiss, kann nix vergessen... */
change_effect(u, oldpotiontype[P_FOOL], -effect);
}
age_unit(r, u);
@@ -402,7 +402,7 @@ static void migrate(region * r)
* wer fragt das? Die Baumwanderung war abhängig von der
* Auswertungsreihenfolge der regionen,
* das hatte ich geändert. jemand hat es wieder gelöscht, toll.
- * ich habe es wieder aktiviert, muß getestet werden.
+ * ich habe es wieder aktiviert, muss getestet werden.
*/
*hp = m->next;
m->next = free_migrants;
@@ -442,7 +442,7 @@ static void horses(region * r)
/* Pferde wandern in Nachbarregionen.
* Falls die Nachbarregion noch berechnet
- * werden muß, wird eine migration-Struktur gebildet,
+ * werden muss, wird eine migration-Struktur gebildet,
* die dann erst in die Berechnung der Nachbarstruktur einfließt.
*/
@@ -632,7 +632,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
a->data.sa[0] = (short)rtrees(r, 0);
a->data.sa[1] = (short)rtrees(r, 1);
}
- /* wir haben 6 Wochen zum wachsen, jeder Same/Sproß hat 18% Chance
+ /* wir haben 6 Wochen zum wachsen, jeder Same/Spross hat 18% Chance
* zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */
growth = 1800;
@@ -1347,10 +1347,12 @@ int ally_cmd(unit * u, struct order *ord)
s = gettoken(token, sizeof(token));
- if (s && !s[0])
+ if (!s || !s[0]) {
keyword = P_ANY;
- else
+ }
+ else {
keyword = findparam(s, u->faction->locale);
+ }
sfp = &u->faction->allies;
if (fval(u, UFL_GROUP)) {
@@ -1990,7 +1992,7 @@ int mail_cmd(unit * u, struct order *ord)
s = gettoken(token, sizeof(token));
/* Falls kein Parameter, ist das eine Einheitsnummer;
- * das Füllwort "AN" muß wegfallen, da gültige Nummer! */
+ * das Füllwort "AN" muss wegfallen, da gültige Nummer! */
do {
cont = 0;
@@ -3407,126 +3409,101 @@ void new_units(void)
}
}
-/** Checks for two long orders and issues a warning if necessary.
- */
-void check_long_orders(unit * u)
+void update_long_order(unit * u)
{
order *ord;
- keyword_t otherorder = MAXKEYWORDS;
+ bool exclusive = true;
+ keyword_t thiskwd = NOKEYWORD;
+ bool hunger = LongHunger(u);
+ freset(u, UFL_MOVED);
+ freset(u, UFL_LONGACTION);
+
+ /* check all orders for a potential new long order this round: */
for (ord = u->orders; ord; ord = ord->next) {
- if (getkeyword(ord) == NOKEYWORD) {
- cmistake(u, ord, 22, MSG_EVENT);
+ keyword_t kwd = getkeyword(ord);
+ if (kwd == NOKEYWORD) continue;
+
+ if (u->old_orders && is_repeated(kwd)) {
+ /* this new order will replace the old defaults */
+ free_orders(&u->old_orders);
}
- else if (is_long(ord)) {
- keyword_t longorder = getkeyword(ord);
- if (otherorder != MAXKEYWORDS) {
- switch (longorder) {
+
+ // hungry units do not get long orders:
+ if (hunger) {
+ if (u->old_orders) {
+ // keep looking for repeated orders that might clear the old_orders
+ continue;
+ }
+ break;
+ }
+
+ if (is_long(kwd)) {
+ 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
+ * werden. Da Handel erst nach anderen langen Befehlen kommt,
+ * muss das vorher abgefangen werden. Wir merken uns also
+ * hier, ob die Einheit handelt. */
+ case K_BUY:
+ case K_SELL:
case K_CAST:
- if (otherorder != longorder) {
+ // non-exclusive orders can be used with others. BUY can be paired with SELL,
+ // CAST with other CAST orders. compatibility is checked once the second
+ // long order is analyzed (below).
+ exclusive = false;
+ break;
+
+ 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 (otherorder == K_SELL) {
- otherorder = K_BUY;
+ if (thiskwd != K_SELL) {
+ cmistake(u, ord, 52, MSG_EVENT);
+ }
+ else {
+ thiskwd = K_BUY;
+ }
+ break;
+ default:
+ // TODO: decide https://bugs.eressea.de/view.php?id=2080#c6011
+ if (kwd > thiskwd) {
+ // swap out thisorder for the new one
+ cmistake(u, u->thisorder, 52, MSG_EVENT);
+ set_order(&u->thisorder, copy_order(ord));
}
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)
-{
- order *ord;
- bool trade = false;
- bool hunger = LongHunger(u);
-
- freset(u, UFL_MOVED);
- freset(u, UFL_LONGACTION);
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));
- }
- 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 (getkeyword(ord) == NOKEYWORD)
- continue;
-
- if (u->old_orders && is_repeated(ord)) {
- /* this new order will replace the old defaults */
- free_orders(&u->old_orders);
- if (hunger)
- break;
- }
- if (hunger)
- continue;
-
- if (is_exclusive(ord)) {
- /* Ãœber dieser Zeile nur Befehle, die auch eine idle Faction machen darf */
- if (idle(u->faction)) {
- set_order(&u->thisorder, default_order(u->faction->locale));
- }
- else {
- set_order(&u->thisorder, copy_order(ord));
- }
- break;
- }
- else {
- keyword_t keyword = getkeyword(ord);
- switch (keyword) {
- /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt
- * werden. Da Handel erst nach anderen langen Befehlen kommt,
- * muß das vorher abgefangen werden. Wir merken uns also
- * hier, ob die Einheit handelt. */
- case K_BUY:
- case K_SELL:
- /* Wenn die Einheit handelt, muß 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:
- /* dient dazu, das neben Zaubern kein weiterer Befehl
- * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */
- set_order(&u->thisorder, copy_order(ord));
- break;
-
- default:
- break;
- }
- }
- }
-
- if (hunger) {
- return;
- }
- /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht
- * werden. */
-
- if (trade) {
- /* fset(u, UFL_LONGACTION|UFL_NOTMOVING); */
+ } else if (!exclusive) {
+ // Wenn die Einheit handelt oder zaubert, muss der Default-Befehl gelöscht werden.
set_order(&u->thisorder, NULL);
}
}
@@ -3696,6 +3673,7 @@ void defaultorders(void)
free_order(ord);
if (!neworders) {
/* 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->old_orders);
neworders = true;
diff --git a/src/laws.test.c b/src/laws.test.c
index b5429e1aa..0c4881c85 100644
--- a/src/laws.test.c
+++ b/src/laws.test.c
@@ -1,6 +1,7 @@
#include
#include "laws.h"
#include "battle.h"
+#include "monster.h"
#include
#include
@@ -768,9 +769,225 @@ static void test_luck_message(CuTest *tc) {
test_cleanup();
}
+static void test_long_order_normal(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ order *ord;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ fset(u, UFL_MOVED);
+ fset(u, UFL_LONGACTION);
+ u->faction->locale = get_or_create_locale("de");
+ ord = create_order(K_MOVE, u->faction->locale, 0);
+ unit_addorder(u, ord);
+ update_long_order(u);
+ CuAssertPtrEquals(tc, ord->data, u->thisorder->data);
+ CuAssertIntEquals(tc, 0, fval(u, UFL_MOVED));
+ CuAssertIntEquals(tc, 0, fval(u, UFL_LONGACTION));
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ CuAssertPtrEquals(tc, 0, u->old_orders);
+ test_cleanup();
+}
+
+static void test_long_order_none(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrEquals(tc, 0, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ test_cleanup();
+}
+
+static void test_long_order_cast(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_CAST, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_CAST, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ test_cleanup();
+}
+
+static void test_long_order_buy_sell(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_BUY, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_SELL, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_SELL, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ test_cleanup();
+}
+
+static void test_long_order_multi_long(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_MOVE, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_DESTROY, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrNotNull(tc, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg));
+ test_cleanup();
+}
+
+static void test_long_order_multi_buy(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_BUY, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_BUY, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg));
+ test_cleanup();
+}
+
+static void test_long_order_multi_sell(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_SELL, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_BUY, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_SELL, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ test_cleanup();
+}
+
+static void test_long_order_buy_cast(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_BUY, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_CAST, u->faction->locale, 0));
+ update_long_order(u);
+ CuAssertPtrEquals(tc, 0, u->thisorder);
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertStrEquals(tc, "error52", test_get_messagetype(u->faction->msgs->begin->msg));
+ test_cleanup();
+}
+
+static void test_long_order_hungry(CuTest *tc) {
+ // TODO: write more tests
+ unit *u;
+ test_cleanup();
+ set_param(&global.parameters, "hunger.long", "1");
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ fset(u, UFL_HUNGER);
+ u->faction->locale = get_or_create_locale("de");
+ unit_addorder(u, create_order(K_MOVE, u->faction->locale, 0));
+ unit_addorder(u, create_order(K_DESTROY, u->faction->locale, 0));
+ set_default_order(K_WORK);
+ update_long_order(u);
+ CuAssertIntEquals(tc, K_WORK, getkeyword(u->thisorder));
+ CuAssertPtrNotNull(tc, u->orders);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ set_default_order(NOKEYWORD);
+ test_cleanup();
+}
+
+static void test_ally_cmd_errors(CuTest *tc) {
+ unit *u;
+ int fid;
+ order *ord;
+
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = get_or_create_locale("de");
+ fid = u->faction->no + 1;
+ CuAssertPtrEquals(tc, 0, findfaction(fid));
+
+ ord = create_order(K_ALLY, u->faction->locale, itoa36(fid));
+ ally_cmd(u, ord);
+ CuAssertStrEquals(tc, "error66", test_get_messagetype(u->faction->msgs->begin->msg));
+ free_order(ord);
+
+ test_cleanup();
+}
+
+static void test_ally_cmd(CuTest *tc) {
+ unit *u;
+ faction * f;
+ order *ord;
+ struct locale *lang;
+
+ test_cleanup();
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ f = test_create_faction(0);
+ u->faction->locale = lang = get_or_create_locale("de");
+ locale_setstring(lang, parameters[P_NOT], "NICHT");
+ locale_setstring(lang, parameters[P_GUARD], "BEWACHE");
+ init_parameters(lang);
+
+ ord = create_order(K_ALLY, lang, "%s", itoa36(f->no));
+ ally_cmd(u, ord);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ CuAssertIntEquals(tc, HELP_ALL, alliedfaction(0, u->faction, f, HELP_ALL));
+ free_order(ord);
+
+ ord = create_order(K_ALLY, lang, "%s NICHT", itoa36(f->no));
+ ally_cmd(u, ord);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ CuAssertIntEquals(tc, 0, alliedfaction(0, u->faction, f, HELP_ALL));
+ free_order(ord);
+
+ ord = create_order(K_ALLY, lang, "%s BEWACHE", itoa36(f->no));
+ ally_cmd(u, ord);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ CuAssertIntEquals(tc, HELP_GUARD, alliedfaction(0, u->faction, f, HELP_ALL));
+ free_order(ord);
+
+ ord = create_order(K_ALLY, lang, "%s BEWACHE NICHT", itoa36(f->no));
+ ally_cmd(u, ord);
+ CuAssertPtrEquals(tc, 0, u->faction->msgs);
+ CuAssertIntEquals(tc, 0, alliedfaction(0, u->faction, f, HELP_ALL));
+ free_order(ord);
+
+ test_cleanup();
+}
+
CuSuite *get_laws_suite(void)
{
CuSuite *suite = CuSuiteNew();
+ SUITE_ADD_TEST(suite, test_ally_cmd);
+ SUITE_ADD_TEST(suite, test_ally_cmd_errors);
+ SUITE_ADD_TEST(suite, test_long_order_normal);
+ SUITE_ADD_TEST(suite, test_long_order_none);
+ SUITE_ADD_TEST(suite, test_long_order_cast);
+ SUITE_ADD_TEST(suite, test_long_order_buy_sell);
+ SUITE_ADD_TEST(suite, test_long_order_multi_long);
+ SUITE_ADD_TEST(suite, test_long_order_multi_buy);
+ SUITE_ADD_TEST(suite, test_long_order_multi_sell);
+ SUITE_ADD_TEST(suite, test_long_order_buy_cast);
+ SUITE_ADD_TEST(suite, test_long_order_hungry);
SUITE_ADD_TEST(suite, test_new_building_can_be_renamed);
SUITE_ADD_TEST(suite, test_rename_building);
SUITE_ADD_TEST(suite, test_rename_building_twice);
diff --git a/src/magic.c b/src/magic.c
index 943c59db2..075880020 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -777,7 +777,7 @@ int spellcost(unit * u, const spell * sp)
int count = countspells(u, 0);
const resource_type *r_aura = get_resourcetype(R_AURA);
- for (k = 0; sp->components[k].type; k++) {
+ for (k = 0; sp->components && sp->components[k].type; k++) {
if (sp->components[k].type == r_aura) {
aura = sp->components[k].amount;
}
@@ -798,7 +798,7 @@ static int spl_costtyp(const spell * sp)
int k;
int costtyp = SPC_FIX;
- for (k = 0; sp->components[k].type; k++) {
+ for (k = 0; sp->components && sp->components[k].type; k++) {
if (costtyp == SPC_LINEAR)
return SPC_LINEAR;
@@ -827,7 +827,7 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range)
int k, maxlevel, needplevel;
int costtyp = SPC_FIX;
- for (k = 0; sp->components[k].type; k++) {
+ for (k = 0; sp->components && sp->components[k].type; k++) {
if (cast_level == 0)
return 0;
@@ -894,7 +894,7 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range)
int resuse;
assert(cast_level > 0);
- for (k = 0; sp->components[k].type; k++) {
+ for (k = 0; sp->components && sp->components[k].type; k++) {
if (sp->components[k].type == r_aura) {
resuse = spellcost(u, sp) * range;
}
@@ -954,7 +954,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
return false;
}
- for (k = 0; sp->components[k].type; ++k) {
+ for (k = 0; sp->components && sp->components[k].type; ++k) {
if (sp->components[k].amount > 0) {
const resource_type *rtype = sp->components[k].type;
int itemhave;
@@ -2768,15 +2768,13 @@ void magic(void)
continue;
}
- if (u->thisorder != NULL) {
- for (ord = u->orders; ord; ord = ord->next) {
- if (getkeyword(ord) == K_CAST) {
- castorder *co = cast_cmd(u, ord);
- fset(u, UFL_LONGACTION | UFL_NOTMOVING);
- if (co) {
- const spell *sp = co->sp;
- add_castorder(&spellranks[sp->rank], co);
- }
+ for (ord = u->orders; ord; ord = ord->next) {
+ if (getkeyword(ord) == K_CAST) {
+ castorder *co = cast_cmd(u, ord);
+ fset(u, UFL_LONGACTION | UFL_NOTMOVING);
+ if (co) {
+ const spell *sp = co->sp;
+ add_castorder(&spellranks[sp->rank], co);
}
}
}
diff --git a/src/magic.test.c b/src/magic.test.c
index 9a01d5d4e..600f724ca 100644
--- a/src/magic.test.c
+++ b/src/magic.test.c
@@ -3,6 +3,7 @@
#include "magic.h"
#include
+#include
#include
#include
#include
@@ -382,9 +383,45 @@ void test_hasspell(CuTest * tc)
test_cleanup();
}
+static quicklist * casts;
+
+static int cast_fireball(struct castorder * co) {
+ ql_push(&casts, co);
+ return 0;
+}
+
+void test_multi_cast(CuTest *tc) {
+ unit *u;
+ spell *sp;
+ struct locale * lang;
+
+ test_cleanup();
+ sp = create_spell("fireball", 0);
+ sp->cast = cast_fireball;
+ CuAssertPtrEquals(tc, sp, find_spell("fireball"));
+
+ u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
+ u->faction->locale = lang = get_or_create_locale("de");
+ locale_setstring(lang, mkname("spell", sp->sname), "Feuerball");
+ CuAssertStrEquals(tc, "Feuerball", spell_name(sp, lang));
+ set_level(u, SK_MAGIC, 10);
+ unit_add_spell(u, 0, sp, 1);
+ CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang));
+
+ unit_addorder(u, create_order(K_CAST, u->faction->locale, "Feuerball"));
+ unit_addorder(u, create_order(K_CAST, u->faction->locale, "Feuerball"));
+ CuAssertPtrEquals(tc, casts, 0);
+ magic();
+ CuAssertPtrNotNull(tc, casts);
+ CuAssertIntEquals(tc, 2, ql_length(casts));
+ ql_free(casts);
+ test_cleanup();
+}
+
CuSuite *get_magic_suite(void)
{
CuSuite *suite = CuSuiteNew();
+ SUITE_ADD_TEST(suite, test_multi_cast);
SUITE_ADD_TEST(suite, test_updatespells);
SUITE_ADD_TEST(suite, test_spellbooks);
SUITE_ADD_TEST(suite, test_pay_spell);
diff --git a/src/move.c b/src/move.c
index f29dd08ce..a9ed36b3e 100644
--- a/src/move.c
+++ b/src/move.c
@@ -366,7 +366,7 @@ static int canwalk(unit * u)
return E_CANWALK_TOOMANYCARTS;
/* Es muß nicht zwingend an den Wagen liegen, aber egal... (man
* könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als
- * Fracht draufpaßt) */
+ * Fracht draufpasst) */
return E_CANWALK_TOOHEAVY;
}
diff --git a/src/report.c b/src/report.c
index 0b591b5ed..3d57ee4c2 100644
--- a/src/report.c
+++ b/src/report.c
@@ -1471,14 +1471,12 @@ report_template(const char *filename, report_context * ctx, const char *charset)
newline(out);
newline(out);
- sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f),
- LOC(f->locale, "enterpasswd"));
+ sprintf(buf, "%s %s \"%s\"", LOC(f->locale, "ERESSEA"), factionid(f), f->passw);
rps_nowrap(out, buf);
newline(out);
newline(out);
sprintf(buf, "; ECHECK -l -w4 -r%d -v%s", f->race->recruitcost,
ECHECK_VERSION);
- /* -v3.4: ECheck Version 3.4.x */
rps_nowrap(out, buf);
newline(out);
@@ -1575,7 +1573,8 @@ report_template(const char *filename, report_context * ctx, const char *charset)
newline(out);
}
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 */
if (is_persistent(ord)) {
strcpy(buf, " ");
diff --git a/src/reports.c b/src/reports.c
index 128815f71..88b11e31d 100644
--- a/src/reports.c
+++ b/src/reports.c
@@ -793,7 +793,8 @@ size_t size)
bool printed = 0;
order *ord;;
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) {
bytes = buforder(bufp, size, ord, printed++);
if (wrptr(&bufp, &size, bytes) != 0)
@@ -805,7 +806,8 @@ size_t size)
}
if (printed < ORDERS_IN_NR)
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) {
bytes = buforder(bufp, size, ord, printed++);
if (wrptr(&bufp, &size, bytes) != 0)
diff --git a/src/spells.test.c b/src/spells.test.c
index ff67dd58d..5ecb8bd88 100644
--- a/src/spells.test.c
+++ b/src/spells.test.c
@@ -20,13 +20,10 @@
#include
-static struct castorder *test_create_castorder(castorder *order, unit *u, const char *name, int level, float force, int range) {
+static void test_create_castorder(castorder *order, unit *u, int level, float force, int range) {
struct locale * lang;
- spell *sp;
-
lang = get_or_create_locale("en");
- sp = create_spell(name, 0);
- return order = create_castorder(order, u, NULL, sp, u->region, level, force, range, create_order(K_CAST, lang, ""), NULL);
+ create_castorder(order, u, NULL, NULL, u->region, level, force, range, create_order(K_CAST, lang, ""), NULL);
}
static void test_dreams(CuTest *tc) {
@@ -39,12 +36,12 @@ static void test_dreams(CuTest *tc) {
test_cleanup();
test_create_world();
r=findregion(0, 0);
- f1 = test_create_faction(test_create_race("human"));
- f2 = test_create_faction(test_create_race("human"));
+ f1 = test_create_faction(0);
+ f2 = test_create_faction(0);
u1 = test_create_unit(f1, r);
u2 = test_create_unit(f2, r);
- test_create_castorder(&order, u1, "goodreams", 10, 10., 0);
+ test_create_castorder(&order, u1, 10, 10., 0);
level = sp_gooddreams(&order);
CuAssertIntEquals(tc, 10, level);
@@ -57,7 +54,7 @@ static void test_dreams(CuTest *tc) {
CuAssertIntEquals(tc, 1, get_modifier(u1, SK_MELEE, 11, r, false));
CuAssertIntEquals(tc, 0, get_modifier(u2, SK_MELEE, 11, r, false));
- test_create_castorder(&order, u1, "baddreams", 10, 10., 0);
+ test_create_castorder(&order, u1, 10, 10., 0);
level = sp_baddreams(&order);
CuAssertIntEquals(tc, 10, level);
diff --git a/src/sqlite.c b/src/sqlite.c
index c19aa6903..fd46c4f1f 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -123,9 +123,9 @@ static void update_faction(sqlite3 *db, const faction *f) {
"INSERT INTO faction_data (faction_id, code, name, email, lang, turn)"
" VALUES (?, ?, ?, ?, ?, ?)";
sqlite3_stmt *stmt = 0;
+ strcpy(code, itoa36(f->no));
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, f->subscription);
- strcpy(code, itoa36(f->no));
sqlite3_bind_text(stmt, 2, code, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, f->name, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, f->email, -1, SQLITE_STATIC);
diff --git a/src/util/strings.c b/src/util/strings.c
index 3f3d7dc36..b3801d52f 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -43,6 +43,7 @@ char *set_string(char **s, const char *neu)
unsigned int hashstring(const char *s)
{
unsigned int key = 0;
+ assert(s);
while (*s) {
key = key * 37 + *s++;
}
diff --git a/src/util/translation.c b/src/util/translation.c
index d73074294..16d3e684f 100644
--- a/src/util/translation.c
+++ b/src/util/translation.c
@@ -31,7 +31,7 @@
typedef struct opstack {
variant *begin;
variant *top;
- int size;
+ unsigned int size;
} opstack;
variant opstack_pop(opstack ** stackp)
@@ -53,10 +53,16 @@ void opstack_push(opstack ** stackp, variant data)
stack->top = stack->begin;
*stackp = stack;
}
- if (stack->top - stack->begin == stack->size) {
+ if (stack->top == stack->begin + stack->size) {
size_t pos = stack->top - stack->begin;
+ void *tmp;
stack->size += stack->size;
- stack->begin = realloc(stack->begin, sizeof(variant) * stack->size);
+ tmp = realloc(stack->begin, sizeof(variant) * stack->size);
+ if (!tmp) {
+ log_error("realloc out of memory");
+ abort();
+ }
+ stack->begin = (variant *)tmp;
stack->top = stack->begin + pos;
}
*stack->top++ = data;
@@ -66,7 +72,7 @@ void opstack_push(opstack ** stackp, variant data)
** static buffer malloc
**/
-#define BBUFSIZE 128*1024
+#define BBUFSIZE 0x20000
static struct {
char *begin;
char *end;
@@ -79,7 +85,7 @@ char *balloc(size_t size)
static int init = 0; /* STATIC_XCALL: used across calls */
if (!init) {
init = 1;
- buffer.current = buffer.begin = malloc(BBUFSIZE);
+ buffer.current = buffer.begin = malloc(BBUFSIZE * sizeof(char));
buffer.end = buffer.begin + BBUFSIZE;
}
if (buffer.current + size > buffer.end) {
@@ -269,7 +275,7 @@ static const char *parse_string(opstack ** stack, const char *in,
}
else {
int ch = (unsigned char)(*ic);
- int bytes;
+ size_t bytes;
switch (ch) {
case '\\':
@@ -285,8 +291,8 @@ static const char *parse_string(opstack ** stack, const char *in,
if (ic == NULL)
return NULL;
c = (char *)opop_v(stack);
- bytes = (int)(c ? strlcpy(oc, c, size) : 0);
- if (bytes < (int)size)
+ bytes = (c ? strlcpy(oc, c, size) : 0);
+ if (bytes < size)
oc += bytes;
else
oc += size;
@@ -363,7 +369,7 @@ static const char *parse(opstack ** stack, const char *inn,
const char *translate(const char *format, const void *userdata,
const char *vars, variant args[])
{
- int i = 0;
+ unsigned int i = 0;
const char *ic = vars;
char symbol[32];
char *oc = symbol;