diff --git a/src/common/attributes/attributes.c b/src/common/attributes/attributes.c
index c53bab14e..08f71f91c 100644
--- a/src/common/attributes/attributes.c
+++ b/src/common/attributes/attributes.c
@@ -38,7 +38,6 @@
# include "option.h"
#endif
#include "moved.h"
-#include "aggressive.h"
#include "variable.h"
/* util includes */
@@ -74,6 +73,5 @@ init_attributes(void)
#ifdef USE_UGROUPS
init_ugroup();
#endif
- init_aggressive();
init_variable();
}
diff --git a/src/common/attributes/attributes.vcproj b/src/common/attributes/attributes.vcproj
index 4271a2097..da9a2afcd 100644
--- a/src/common/attributes/attributes.vcproj
+++ b/src/common/attributes/attributes.vcproj
@@ -173,9 +173,6 @@
-
-
@@ -246,9 +243,6 @@
RelativePath=".\viewrange.h">
-
-
diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c
index 755a527e6..e3845af6a 100644
--- a/src/common/gamecode/creport.c
+++ b/src/common/gamecode/creport.c
@@ -760,12 +760,17 @@ cr_output_unit(FILE * F, const region * r,
}
/* default commands */
fprintf(F, "COMMANDS\n");
+#ifdef LASTORDER
if (u->lastorder) {
fwriteorder(F, u->lastorder, f->locale);
fputc('\n', F);
}
+#endif
for (ord = u->orders; ord; ord = ord->next) {
- if (is_persistent(ord) && ord!=u->lastorder) {
+#ifdef LASTORDER
+ if (ord==u->lastorder) continue;
+#endif
+ if (is_persistent(ord)) {
fwriteorder(F, ord, f->locale);
fputc('\n', F);
}
diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c
index b22090c30..a3e93d8f3 100644
--- a/src/common/gamecode/economy.c
+++ b/src/common/gamecode/economy.c
@@ -1534,21 +1534,21 @@ make_cmd(unit * u, struct order * ord)
if (p == P_ROAD) {
direction_t d;
if(r->planep && fval(r->planep, PFL_NOBUILD)) {
- cmistake(u, u->thisorder, 275, MSG_PRODUCE);
+ cmistake(u, ord, 275, MSG_PRODUCE);
return;
}
d = finddirection(getstrtoken(), u->faction->locale);
if (d!=NODIRECTION) {
if(r->planep && fval(r->planep, PFL_NOBUILD)) {
- cmistake(u, u->thisorder, 94, MSG_PRODUCE);
+ cmistake(u, ord, 94, MSG_PRODUCE);
return;
}
build_road(r, u, m, d);
- } else cmistake(u, u->thisorder, 71, MSG_PRODUCE);
+ } else cmistake(u, ord, 71, MSG_PRODUCE);
return;
} else if (p == P_SHIP) {
if(r->planep && fval(r->planep, PFL_NOBUILD)) {
- cmistake(u, u->thisorder, 276, MSG_PRODUCE);
+ cmistake(u, ord, 276, MSG_PRODUCE);
return;
}
continue_ship(r, u, m);
@@ -1592,19 +1592,19 @@ make_cmd(unit * u, struct order * ord)
if (stype != NOSHIP) {
if(r->planep && fval(r->planep, PFL_NOBUILD)) {
- cmistake(u, u->thisorder, 276, MSG_PRODUCE);
+ cmistake(u, ord, 276, MSG_PRODUCE);
return;
}
- create_ship(r, u, stype, m);
+ create_ship(r, u, stype, m, ord);
return;
}
if (btype != NOBUILDING) {
if(r->planep && fval(r->planep, PFL_NOBUILD)) {
- cmistake(u, u->thisorder, 94, MSG_PRODUCE);
+ cmistake(u, ord, 94, MSG_PRODUCE);
return;
}
- build_building(u, btype, m);
+ build_building(u, btype, m, ord);
return;
}
@@ -1613,7 +1613,7 @@ make_cmd(unit * u, struct order * ord)
return;
}
- cmistake(u, u->thisorder, 125, MSG_PRODUCE);
+ cmistake(u, ord, 125, MSG_PRODUCE);
}
/* ------------------------------------------------------------- */
diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c
index fee34a2d5..7bbd2aa38 100644
--- a/src/common/gamecode/laws.c
+++ b/src/common/gamecode/laws.c
@@ -139,7 +139,9 @@ restart_race(unit *u, const race * rc)
*ordp = ord->next;
ord->next = NULL;
if (u->thisorder == ord) set_order(&u->thisorder, NULL);
+#ifdef LASTORDER
if (u->lastorder == ord) set_order(&u->lastorder, NULL);
+#endif
} else {
ordp = &ord->next;
}
@@ -2662,6 +2664,7 @@ instant_orders(void)
unit * u;
for (u = r->units; u; u = u->next) {
order * ord;
+ freset(u, UFL_MOVED);
for (ord = u->orders; ord; ord = ord->next) {
switch (get_keyword(ord)) {
case K_URSPRUNG:
@@ -3413,86 +3416,48 @@ setdefaults (void)
set_order(&u->thisorder, default_order(u->faction->locale));
continue;
}
-
+#ifdef LASTORDER
/* by default the default long order becomes the new long order. */
- u->thisorder = copy_order(u->lastorder);
-
+ u->thisorder = duplicate_order(u->lastorder);
+#endif
/* check all orders for a potential new long order this round: */
for (ord = u->orders; ord; ord = ord->next) {
- keyword_t keyword = get_keyword(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. */
- 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, NULL);
- 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). */
- init_tokens(ord); /* initialize token-parser */
- skip_token();
- if (getparam(u->faction->locale) == P_TEMP) break;
- /* else fall through */
-
-#if GROWING_TREES
- case K_PFLANZE:
-#endif
- 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_ZUECHTE:
- case K_BIETE:
- case K_PIRACY:
- /* Ü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, ord);
- }
- break;
-
- case K_FOLLOW:
- /* FOLLOW is only a long order if we are following a ship. */
- init_tokens(ord);
- skip_token();
- if (getparam(u->faction->locale) == P_SHIP) {
- set_order(&u->thisorder, ord);
- }
- break;
-
- case K_ROUTE:
- case K_WORK:
- case K_DRIVE:
- case K_MOVE:
- case K_WEREWOLF:
+ 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, ord);
- break;
+ }
+ break;
+ } else {
+ keyword_t keyword = get_keyword(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. */
+ trade = true;
+ break;
- /* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
- * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
- * nicht moeglich ist, Schulden zu machen. */
+ case K_CAST:
+ /* dient dazu, das neben Zaubern kein weiterer Befehl
+ * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */
+ set_order(&u->thisorder, NULL);
+ break;
+
+ case K_WEREWOLF:
+ set_order(&u->thisorder, ord);
+ break;
+
+ /* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
+ * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
+ * nicht moeglich ist, Schulden zu machen. */
+ }
}
}
@@ -3512,21 +3477,19 @@ setdefaults (void)
* die Einheitsnummer ungueltig). Auch Attackiere sollte nie in
* den Default übernommen werden */
+#ifdef LASTORDER
switch (get_keyword(u->thisorder)) {
case K_MOVE:
- case K_BIETE:
case K_ATTACK:
case K_WEREWOLF:
case NOKEYWORD:
+ /* these can never be default orders */
break;
default:
set_order(&u->lastorder, u->thisorder);
- /* Attackiere sollte niemals Default werden */
- if (get_keyword(u->lastorder) == K_ATTACK) {
- set_order(&u->lastorder, default_order(u->faction->locale));
- }
}
+#endif
}
}
}
@@ -3648,6 +3611,7 @@ monthly_healing(void)
}
}
+#ifdef LASTORDER
static void
defaultorders (void)
{
@@ -3675,6 +3639,7 @@ defaultorders (void)
}
}
}
+#endif
/* ************************************************************ */
/* GANZ WICHTIG! ALLE GEÄNDERTEN SPRÜCHE NEU ANZEIGEN */
@@ -3900,8 +3865,10 @@ processorders (void)
monthly_healing();
regeneration_magiepunkte();
+#ifdef LASTORDER
puts(" - Defaults setzen");
defaultorders();
+#endif
puts(" - Unterhaltskosten, Nachfrage, Seuchen, Wachstum, Auswanderung");
demographics();
diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c
index 4170e6043..f007af749 100644
--- a/src/common/gamecode/monster.c
+++ b/src/common/gamecode/monster.c
@@ -32,7 +32,6 @@
/* attributes includes */
#include
#include
-#include
/* spezialmonster */
#include
@@ -74,87 +73,69 @@
static boolean
is_waiting(const unit * u)
{
- if (fval(u, UFL_ISNEW)) return true;
- if (get_keyword(u->lastorder)==K_WAIT) return true;
-
- return false;
+ if (fval(u, UFL_ISNEW|UFL_MOVED)) return true;
+ return false;
}
-static boolean
+static order *
monster_attack(unit * u, const unit * target)
{
char zText[20];
- if (u->region!=target->region) return false;
- if (!cansee(u->faction, u->region, target, 0)) return false;
- if (is_waiting(u)) return false;
+ if (u->region!=target->region) return NULL;
+ if (u->faction==target->faction) return NULL;
+ if (!cansee(u->faction, u->region, target, 0)) return NULL;
+ if (is_waiting(u)) return NULL;
sprintf(zText, "%s %s",
locale_string(u->faction->locale, keywords[K_ATTACK]), unitid(target));
- addlist(&u->orders, parse_order(zText, u->faction->locale));
- return true;
+ return parse_order(zText, u->faction->locale);
}
-void
-taxed_by_monster(unit * u)
-{
- const char * zText = locale_string(u->faction->locale, keywords[K_TAX]);
- addlist(&u->orders, parse_order(zText, u->faction->locale));
-}
-static boolean
+static order *
get_money_for_dragon(region * r, unit * u, int wanted)
{
unit *u2;
int n;
/* attackiere bewachende einheiten */
+ for (u2 = r->units; u2; u2 = u2->next) {
+ if (u2 != u && getguard(u2)&GUARD_TAX) {
+ order * ord = monster_attack(u, u2);
+ if (ord) addlist(&u->orders, ord);
+ }
+ }
- for (u2 = r->units; u2; u2 = u2->next)
- if (u2 != u && getguard(u2)&GUARD_TAX)
- monster_attack(u, u2);
-
- /* treibe steuern bei den bauern ein */
-
- taxed_by_monster(u);
-
- /* falls das genug geld ist, bleibt das monster hier */
-
- if (rmoney(r) >= wanted)
- return true;
-
- /* attackiere so lange die fremden, alteingesessenen einheiten mit geld
- * (einfach die reihenfolge der einheiten), bis das geld da ist. n
- * zaehlt das so erhaltene geld. */
+ /* falls genug geld in der region ist, treiben wir steuern ein. */
+ if (rmoney(r) >= wanted) {
+ /* 5% chance, dass der drache aus einer laune raus attackiert */
+ if (chance(0.95)) return parse_order(keywords[K_TAX], default_locale);
+ }
+ /* falls der drache launisch ist, oder das regionssilber knapp, greift er alle an */
n = 0;
- for (u2 = r->units; u2; u2 = u2->next)
- if (u2->faction != u->faction && get_money(u2)) {
- if (monster_attack(u, u2)) {
- n += get_money(u2);
+ for (u2 = r->units; u2; u2 = u2->next) {
+ if (u2->faction != u->faction && get_money(u2)) {
+ if (getguard(u2) & GUARD_TAX) continue;
+ else {
+ order * ord = monster_attack(u, u2);
+ if (ord) {
+ addlist(&u->orders, ord);
+ n += get_money(u2);
+ }
+ }
+ }
+ }
- if (n > wanted)
- break;
- }
- }
- /* falls die einnahmen erreicht werden, bleibt das monster noch eine
+ /* falls die einnahmen erreicht werden, bleibt das monster noch eine
* runde hier. */
+ if (n + rmoney(r) >= wanted) {
+ return parse_order(keywords[K_TAX], default_locale);
+ }
- if (n + rmoney(r) >= wanted)
- return true;
-
- /* falls das geld, das wir haben, und das der angriffe zum leben
- * reicht, koennen wir uns fortbewegen. deswegen duerfen wir
- * steuereinnahmen nicht beruecksichtigen - wir bewegen uns ja fort. */
-
- if (get_money(u) + n >= MAINTENANCE)
- return false;
-
- /* falls wir auch mit angriffe nicht genug geld zum wandern haben,
- * muessen wir wohl oder uebel hier bleiben. vielleicht wurden ja genug
- * steuern eingetrieben */
-
- return true;
+ /* wenn wir NULL zurückliefern, macht der drache was anderes, z.b. weggehen */
+ return NULL;
}
static int
@@ -314,8 +295,8 @@ treeman_neighbour(region * r)
return NODIRECTION;
}
-static void
-move_monster(region * r, unit * u)
+static order *
+monster_move(region * r, unit * u)
{
direction_t d = NODIRECTION;
@@ -337,11 +318,11 @@ move_monster(region * r, unit * u)
* den ozean */
if (d == NODIRECTION)
- return;
+ return NULL;
sprintf(buf, "%s %s", locale_string(u->faction->locale, keywords[K_MOVE]), locale_string(u->faction->locale, directions[d]));
- addlist(&u->orders, parse_order(buf, u->faction->locale));
+ return parse_order(buf, u->faction->locale);
}
/* Wir machen das mal autoconf-style: */
@@ -412,8 +393,8 @@ set_new_dragon_target(unit * u, region * r, int range)
return NULL;
}
-static boolean
-set_movement_order(unit * u, const region * target, int moves, boolean (*allowed)(const region *, const region *))
+static order *
+make_movement_order(unit * u, const region * target, int moves, boolean (*allowed)(const region *, const region *))
{
region * r = u->region;
region ** plan = path_find(r, target, DRAGON_RANGE*5, allowed);
@@ -421,7 +402,7 @@ set_movement_order(unit * u, const region * target, int moves, boolean (*allowed
char * c;
if (plan==NULL) {
- return false;
+ return NULL;
}
strcpy(buf, locale_string(u->faction->locale, keywords[K_MOVE]));
@@ -437,12 +418,10 @@ set_movement_order(unit * u, const region * target, int moves, boolean (*allowed
c += strlen(c);
}
- set_order(&u->lastorder, parse_order(buf, u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have both increased the refcount */
- return true;
+ return parse_order(buf, u->faction->locale);
}
-static void
+static order *
monster_seeks_target(region *r, unit *u)
{
direction_t d;
@@ -465,7 +444,10 @@ monster_seeks_target(region *r, unit *u)
}
/* TODO: prüfen, ob target überhaupt noch existiert... */
- if(!target) return; /* this is a bug workaround! remove!! */
+ if (!target) {
+ log_error(("Monster '%s' hat kein Ziel!\n", unitname(u)));
+ return NULL; /* this is a bug workaround! remove!! */
+ }
if(r == target->region ) { /* Wir haben ihn! */
if (u->race == new_race[RC_ALP]) {
@@ -474,7 +456,7 @@ monster_seeks_target(region *r, unit *u)
else {
assert(!"Seeker-Monster hat keine Aktion fuer Ziel");
}
- return;
+ return NULL;
}
/* Simpler Ansatz: Nachbarregion mit gerinster Distanz suchen.
@@ -500,9 +482,9 @@ monster_seeks_target(region *r, unit *u)
}
if( d == NODIRECTION )
- return;
+ return NULL;
sprintf(buf, "%s %s", locale_string(u->faction->locale, keywords[K_MOVE]), locale_string(u->faction->locale, directions[d]));
- addlist(&u->orders, parse_order(buf, u->faction->locale));
+ return parse_order(buf, u->faction->locale);
}
unit *
@@ -535,61 +517,18 @@ random_unit(const region * r)
return u;
}
-static boolean
-random_attack_by_monster(const region * r, unit * u)
+static void
+monster_attacks(unit * u)
{
- boolean success = false;
- unit *target;
- int kill, max;
- int tries = 0;
- int attacked = 0;
+ region * r = u->region;
+ unit * u2;
- switch (old_race(u->race)) {
- case RC_FIREDRAGON:
- kill = 25;
- max = 50;
- break;
- case RC_DRAGON:
- kill = 100;
- max = 200;
- break;
- case RC_WYRM:
- kill = 400;
- max = 800;
- break;
- default:
- kill = 1;
- max = 1;
- }
-
- kill *= u->number;
- max *= u->number;
-
- do {
- tries++;
- target = random_unit(r);
- if (target
- && target != u
- && humanoidrace(target->race)
- && !illusionaryrace(target->race)
- && target->number <= max)
- {
- if (monster_attack(u, target)) {
- unit * u2;
- success = true;
- for (u2 = r->units; u2; u2 = u2->next) {
- if (u2->faction->no == MONSTER_FACTION
- && rand() % 100 < 75)
- {
- monster_attack(u2, target);
- }
- }
- attacked += target->number;
- }
- }
- }
- while (attacked < kill && tries < 10);
- return success;
+ for (u2=r->units;u2;u2=u2->next) {
+ if (chance(0.75)) {
+ order * ord = monster_attack(u, u2);
+ if (ord) addlist(&u->orders, ord);
+ }
+ }
}
static void
@@ -741,12 +680,13 @@ random_growl(void)
extern attrib_type at_direction;
-static void
-learn_monster(unit *u)
+static order *
+monster_learn(unit *u)
{
int c = 0;
int n;
skill * sv;
+ const struct locale * lang = u->faction->locale;
/* Monster lernt ein zufälliges Talent aus allen, in denen es schon
* Lerntage hat. */
@@ -755,7 +695,7 @@ learn_monster(unit *u)
if (sv->level>0) ++c;
}
- if(c == 0) return;
+ if(c == 0) return NULL;
n = rand()%c + 1;
c = 0;
@@ -763,14 +703,13 @@ learn_monster(unit *u)
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
if (sv->level>0) {
if (++c == n) {
- sprintf(buf, "%s %s", locale_string(u->faction->locale, keywords[K_STUDY]),
- skillname(sv->id, u->faction->locale));
- set_order(&u->thisorder, parse_order(buf, u->faction->locale));
- free_order(u->thisorder); /* parse_order & set_order have both increased the refcount */
- break;
+ sprintf(buf, "%s %s", locale_string(lang, keywords[K_STUDY]),
+ skillname(sv->id, lang));
+ return parse_order(buf, lang);
}
}
}
+ return NULL;
}
void
@@ -810,6 +749,47 @@ check_overpopulated(unit *u)
}
static void
+recruit_dracoids(unit * dragon, int size)
+{
+ faction * f = dragon->faction;
+ region * r = dragon->region;
+ const struct item_type * weapon = NULL;
+ order * new_order;
+ unit *un = createunit(r, f, size, new_race[RC_DRACOID]);
+
+ name_unit(un);
+ change_money(dragon, -un->number * 50);
+
+ set_level(un, SK_SPEAR, (3 + rand() % 4));
+ set_level(un, SK_SWORD, (3 + rand() % 4));
+ set_level(un, SK_LONGBOW, (2 + rand() % 3));
+
+ switch (rand() % 3) {
+ case 0:
+ weapon = olditemtype[I_LONGBOW];
+ break;
+ case 1:
+ weapon = olditemtype[I_SWORD];
+ break;
+ default:
+ weapon = olditemtype[I_SPEAR];
+ break;
+ }
+ i_change(&un->items, weapon, un->number);
+ if (weapon->rtype->wtype->flags & WTF_MISSILE) un->status = ST_BEHIND;
+ else un->status = ST_FIGHT;
+
+ sprintf(buf, "%s \"%s\"", keywords[K_STUDY], skillname(weapon->rtype->wtype->skill, f->locale));
+ new_order = parse_order(buf, default_locale);
+#ifdef LASTORDER
+ set_order(&un->lastorder, new_order);
+ free_order(new_order);
+#else
+ addlist(&un->orders, new_order);
+#endif
+}
+
+static order *
plan_dragon(unit * u)
{
attrib * ta = a_find(u->attribs, &at_targetregion);
@@ -819,6 +799,7 @@ plan_dragon(unit * u)
int capacity = walkingcapacity(u);
item ** itmp = &u->items;
boolean move = false;
+ order * long_order = NULL;
if (horses > 0) {
change_resource(u, R_HORSE, - min(horses,(u->number*2)));
@@ -853,15 +834,16 @@ plan_dragon(unit * u)
}
}
if (tr!=NULL) {
+ assert(long_order==NULL);
switch(old_race(u->race)) {
case RC_FIREDRAGON:
- set_movement_order(u, tr, 4, allowed_dragon);
+ long_order = make_movement_order(u, tr, 4, allowed_dragon);
break;
case RC_DRAGON:
- set_movement_order(u, tr, 3, allowed_dragon);
+ long_order = make_movement_order(u, tr, 3, allowed_dragon);
break;
case RC_WYRM:
- set_movement_order(u, tr, 1, allowed_dragon);
+ long_order = make_movement_order(u, tr, 1, allowed_dragon);
break;
}
if (rand()%100 < 15) {
@@ -875,49 +857,28 @@ plan_dragon(unit * u)
}
}
} else {
- if (!get_money_for_dragon(u->region, u, income(u))) {
- /* money is gone */
+ /* we have no target. do we like it here, then? */
+ long_order = get_money_for_dragon(u->region, u, income(u));
+ if (long_order==NULL) {
+ /* money is gone, need a new target */
set_new_dragon_target(u, u->region, DRAGON_RANGE);
}
- else if (u->race != new_race[RC_FIREDRAGON] && u->region->terrain!=T_OCEAN
- && !(terrain[rterrain(u->region)].flags & FORBIDDEN_LAND)) {
+ else if (u->race != new_race[RC_FIREDRAGON]) {
+ /* neue dracoiden! */
+ terrain_t t = rterrain(r);
+ if (r->land && !(terrain[t].flags & FORBIDDEN_LAND)) {
int ra = 20 + rand() % 100;
- if (get_money(u) > ra * 50 + 100 && rand() % 100 < 50)
- {
- const struct item_type * weapon = NULL;
- unit *un;
- un = createunit(u->region, findfaction(MONSTER_FACTION), ra, new_race[RC_DRACOID]);
- name_unit(un);
- change_money(u, -un->number * 50);
-
- set_level(un, SK_SPEAR, (3 + rand() % 4));
- set_level(un, SK_SWORD, (3 + rand() % 4));
- set_level(un, SK_LONGBOW, (2 + rand() % 3));
-
- switch (rand() % 3) {
- case 0:
- weapon = olditemtype[I_LONGBOW];
- break;
- case 1:
- weapon = olditemtype[I_SWORD];
- break;
- default:
- weapon = olditemtype[I_SPEAR];
- break;
- }
- i_change(&un->items, weapon, un->number);
- if (weapon->rtype->wtype->flags & WTF_MISSILE) un->status = ST_BEHIND;
- else un->status = ST_FIGHT;
- sprintf(buf, "%s \"%s\"", keywords[K_STUDY], skillname(weapon->rtype->wtype->skill, u->faction->locale));
- set_order(&un->lastorder, parse_order(buf, default_locale));
- }
- if (is_waiting(u)) {
- sprintf(buf, "%s \"%s\"", keywords[K_STUDY], skillname(SK_OBSERVATION, u->faction->locale));
- set_order(&u->thisorder, parse_order(buf, default_locale));
- set_order(&u->lastorder, u->thisorder);
+ if (get_money(u) > ra * 50 + 100 && rand() % 100 < 50) {
+ recruit_dracoids(u, ra);
}
}
+ }
}
+ if (long_order==NULL) {
+ sprintf(buf, "%s \"%s\"", keywords[K_STUDY], skillname(SK_OBSERVATION, u->faction->locale));
+ long_order = parse_order(buf, default_locale);
+ }
+ return long_order;
}
void
@@ -931,30 +892,32 @@ plan_monsters(void)
for (r = regions; r; r = r->next) {
unit *u;
+ double attack_chance = MONSTERATTACK;
+ boolean attacking = false;
+
for (u = r->units; u; u = u->next) {
- boolean is_moving = false;
attrib * ta;
+ order * long_order = NULL;
/* Ab hier nur noch Befehle für NPC-Einheiten. */
if (u->faction->no != MONSTER_FACTION) continue;
+ if (attack_chance>0.0) {
+ if (chance(attack_chance)) attacking = true;
+ attack_chance = 0.0;
+ }
+
if (u->status>ST_BEHIND) u->status = ST_FIGHT; /* all monsters fight */
/* Monster bekommen jede Runde ein paar Tage Wahrnehmung dazu */
produceexp(u, SK_OBSERVATION, u->number);
- /* Haben Drachen ihr Ziel erreicht? */
- ta = a_find(u->attribs, &at_targetregion);
- if (ta) {
- if (u->region == (region*)ta->data.v) {
- a_remove(&u->attribs, ta);
- set_order(&u->lastorder, parse_order(keywords[K_WAIT], u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
- }
- else {
- is_moving = true;
- }
- }
+ /* Befehle müssen jede Runde neu gegeben werden: */
+ free_orders(&u->orders);
+ if (attacking) {
+ monster_attacks(u);
+ }
+ /* units with a plan to kill get ATTACK orders: */
ta = a_find(u->attribs, &at_hate);
if (ta && !is_waiting(u)) {
unit * tu = (unit *)ta->data.v;
@@ -963,62 +926,63 @@ plan_monsters(void)
addlist(&u->orders, parse_order(buf, u->faction->locale));
} else if (tu) {
tu = findunitg(ta->data.i, NULL);
- if (tu) set_movement_order(u, tu->region, 2, allowed_walk);
+ if (tu!=NULL) {
+ long_order = make_movement_order(u, tu->region, 2, allowed_walk);
+ }
}
else a_remove(&u->attribs, ta);
}
- if (!(fval(u, UFL_ISNEW)) && r->terrain != T_OCEAN) { /* Monster bewachen immer */
+ /* All monsters guard the region: */
+ if (!is_waiting(u) && r->land) {
const char * cmd = locale_string(u->faction->locale, keywords[K_GUARD]);
addlist(&u->orders, parse_order(cmd, u->faction->locale));
}
- /* Diese Verkettung ist krank und sollte durch eine 'vernünftige KI'
- * ersetzt werden. */
-
- if( (u->race->flags & RCF_MOVERANDOM)
- && (rand()%100race->flags & RCF_ATTACKRANDOM) && is_moving == false)
- {
- double probability;
- attrib *a = a_find(u->attribs, &at_aggressive);
-
- if (a) {
- probability = a->data.flt;
- } else {
- probability = MONSTERATTACK;
- }
-
- if(chance(probability)) {
- done = random_attack_by_monster(r, u);
- }
+ /* Einheiten mit Bewegungsplan kriegen ein NACH: */
+ if (long_order==NULL) {
+ attrib * ta = a_find(u->attribs, &at_targetregion);
+ if (ta) {
+ if (u->region == (region*)ta->data.v) {
+ a_remove(&u->attribs, ta);
}
- if (!done) {
- if(u->race == new_race[RC_SEASERPENT]) {
- set_order(&u->thisorder, parse_order(keywords[K_PIRACY], default_locale));
- set_order(&u->lastorder, u->thisorder);
- free_order(u->lastorder); /* parse_order & set_order have both increased the refcount */
- } else if(u->race->flags & RCF_LEARN) {
- learn_monster(u);
- }
+ } else if (u->race->flags & RCF_MOVERANDOM) {
+ if (rand()%100race)) {
- case RC_ALP:
- monster_seeks_target(r, u);
- break;
- case RC_FIREDRAGON:
- case RC_DRAGON:
- case RC_WYRM:
- plan_dragon(u);
- break;
+ case RC_SEASERPENT:
+ long_order = parse_order(keywords[K_PIRACY], default_locale);
+ break;
+ case RC_ALP:
+ long_order = monster_seeks_target(r, u);
+ break;
+ case RC_FIREDRAGON:
+ case RC_DRAGON:
+ case RC_WYRM:
+ long_order = plan_dragon(u);
+ break;
+ default:
+ if (u->race->flags & RCF_LEARN) {
+ long_order = monster_learn(u);
+ }
+ break;
}
+ if (long_order) {
+ set_order(&u->thisorder, long_order);
+#ifdef LASTORDER
+ set_order(&u->lastorder, long_order);
+ free_order(new_order); /* parse_order & set_order have both increased the refcount */
+#else
+ addlist(&u->orders, long_order);
+#endif
+ }
+ }
}
}
}
diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c
index 664671b22..ba9baf725 100644
--- a/src/common/gamecode/randenc.c
+++ b/src/common/gamecode/randenc.c
@@ -308,9 +308,9 @@ get_unit(region * r, unit * u)
addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
newunit = createunit(r, u->faction, rand() % 20 + 3, u->faction->race);
+ fset(newunit, UFL_ISNEW|UFL_MOVED);
set_string(&newunit->name, "Dorfbewohner");
set_money(newunit, (rand() % 26 + 10) * newunit->number);
- fset(newunit, UFL_ISNEW);
if (fval(u, UFL_PARTEITARNUNG)) fset(newunit, UFL_PARTEITARNUNG);
switch (rand() % 4) {
case 0:
@@ -576,7 +576,7 @@ chaos(region * r)
break;
}
if (mfac) set_money(u, u->number * (rand() % mfac));
- guard(u, GUARD_ALL);
+ fset(u, UFL_ISNEW|UFL_MOVED);
}
case 2: /* Terrainveränderung */
if (!(terrain[rterrain(r)].flags & FORBIDDEN_LAND)) {
@@ -1101,7 +1101,7 @@ godcurse(void)
}
}
-static void
+static unit *
split_unit(region * r, unit *u)
{
unit *u2 = createunit(r, u->faction, 0, u->race);
@@ -1109,11 +1109,8 @@ split_unit(region * r, unit *u)
set_string(&u2->name, u->name);
set_string(&u2->display, u->display);
- set_order(&u2->thisorder, parse_order(keywords[K_WAIT], u->faction->locale));
- set_order(&u2->lastorder, u2->thisorder);
- free_order(u2->lastorder); /* parse_order & set_order have each increased the refcount */
-
transfermen(u, u2, newsize);
+ return u2;
}
static void
@@ -1126,7 +1123,8 @@ check_split(void)
for(u=r->units;u;u=u->next) {
if(u->faction->no == MONSTER_FACTION) {
if(u->number > u->race->splitsize) {
- split_unit(r, u);
+ unit * u2 = split_unit(r, u);
+ fset(u2, UFL_ISNEW|UFL_MOVED);
}
}
}
@@ -1386,6 +1384,7 @@ randomevents(void)
message * msg;
if (rterrain(r) == T_OCEAN && rand()%10000 < 1) {
u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_SEASERPENT]);
+ fset(u, UFL_ISNEW|UFL_MOVED);
set_level(u, SK_MAGIC, 4);
set_level(u, SK_OBSERVATION, 3);
set_level(u, SK_STEALTH, 2);
@@ -1393,25 +1392,14 @@ randomevents(void)
set_string(&u->name, "Seeschlange");
}
- if ((rterrain(r) == T_GLACIER
- || rterrain(r) == T_SWAMP || rterrain(r) == T_DESERT)
- && rand() % 10000 < (5 + 100 * chaosfactor(r))) {
-
- switch (rand() % 10) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
+ if ((rterrain(r) == T_GLACIER || rterrain(r) == T_SWAMP || rterrain(r) == T_DESERT) && rand() % 10000 < (5 + 100 * chaosfactor(r)))
+ {
+ if (chance(0.80)) {
u = createunit(r, findfaction(MONSTER_FACTION), nrand(60, 20) + 1, new_race[RC_FIREDRAGON]);
- break;
- default:
- u = createunit(r, findfaction(MONSTER_FACTION), nrand(30, 20) + 1, new_race[RC_DRAGON]);
- break;
- }
+ } else {
+ u = createunit(r, findfaction(MONSTER_FACTION), nrand(30, 20) + 1, new_race[RC_DRAGON]);
+ }
+ fset(u, UFL_ISNEW|UFL_MOVED);
set_money(u, u->number * (rand() % 500 + 100));
set_level(u, SK_MAGIC, 4);
@@ -1422,8 +1410,6 @@ randomevents(void)
LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL));
name_unit(u);
- set_order(&u->lastorder, parse_order(keywords[K_WAIT], u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
/* add message to the region */
ADDMSG(&r->msgs,
@@ -1472,6 +1458,7 @@ randomevents(void)
}
u = createunit(r, findfaction(MONSTER_FACTION), undead, rc);
+ fset(u, UFL_ISNEW|UFL_MOVED);
if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rand()%10 < 4) {
set_item(u, I_RUSTY_SWORD, undead);
if (rand()%10 < 3) {
@@ -1490,14 +1477,12 @@ randomevents(void)
u->hp = unit_max_hp(u) * u->number;
deathcounts(r, -undead);
- set_order(&u->lastorder, parse_order(keywords[K_WAIT], u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
- name_unit(u);
+ name_unit(u);
- log_printf("%d %s in %s.\n", u->number,
- LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL));
+ log_printf("%d %s in %s.\n", u->number,
+ LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL));
- {
+ {
message * msg = msg_message("undeadrise", "region", r);
add_message(&r->msgs, msg);
for (u=r->units;u;u=u->next) freset(u->faction, FL_DH);
@@ -1566,9 +1551,7 @@ randomevents(void)
rsettrees(r, trees);
#endif
u = createunit(r, findfaction(MONSTER_FACTION),treemen, new_race[RC_TREEMAN]);
- set_order(&u->lastorder, parse_order(keywords[K_WAIT], u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
- /* guard(u, GUARD_ALL); kein auto-guard! erst in monster.c! */
+ fset(u, UFL_ISNEW|UFL_MOVED);
set_level(u, SK_OBSERVATION, 2);
if (u->number == 1)
diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c
index 37b7ecb0c..fcecb81b1 100644
--- a/src/common/gamecode/report.c
+++ b/src/common/gamecode/report.c
@@ -1676,12 +1676,14 @@ order_template(FILE * F, faction * f)
/* If the lastorder begins with an @ it should have
* been printed in the loop before. */
+#ifdef LASTORDER
if (u->lastorder && !is_persistent(u->lastorder)) {
strcpy(buf, " ");
write_order(u->lastorder, u->faction->locale, buf+2, sizeof(buf)-2);
rps_nowrap(F, buf);
rnl(F);
}
+#endif
}
}
rps_nowrap(F, "");
@@ -3776,7 +3778,7 @@ report_init(void)
add_function("spell", &eval_spell);
register_argtype("string", free, (void*(*)(void*))strdup);
- register_argtype("order", (void(*)(void*))free_order, (void*(*)(void*))copy_order);
+ register_argtype("order", (void(*)(void*))free_order, (void*(*)(void*))duplicate_order);
register_function((pf_generic)view_neighbours, "view_neighbours");
register_function((pf_generic)view_regatta, "view_regatta");
}
diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c
index 1e4938079..6ffcba9c7 100644
--- a/src/common/gamecode/study.c
+++ b/src/common/gamecode/study.c
@@ -241,213 +241,215 @@ static void
teach(unit * u, struct order * ord)
{
region * r = u->region;
- static char order[BUFSIZE];
- int teaching, i, j, count, academy=0;
- unit *u2;
- const char *s;
- skill_t sk;
+ int teaching, i, j, count, academy=0;
+ unit *u2;
+ const char *s;
+ skill_t sk = NOSKILL;
- if ((u->race->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) {
- cmistake(u, u->thisorder, 274, MSG_EVENT);
- return;
- }
+ if ((u->race->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) {
+ cmistake(u, ord, 274, MSG_EVENT);
+ return;
+ }
- if (r->planep && fval(r->planep, PFL_NOTEACH)) {
- cmistake(u, u->thisorder, 273, MSG_EVENT);
- return;
- }
+ if (r->planep && fval(r->planep, PFL_NOTEACH)) {
+ cmistake(u, ord, 273, MSG_EVENT);
+ return;
+ }
- teaching = u->number * 30 * TEACHNUMBER;
+ teaching = u->number * 30 * TEACHNUMBER;
- if ((i = get_effect(u, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */
- i = min(i, u->number * TEACHNUMBER);
- /* Trank wirkt pro Schüler, nicht pro Lehrer */
- teaching -= i * 30;
- change_effect(u, oldpotiontype[P_FOOL], -i);
- j = teaching / 30;
- add_message(&u->faction->msgs, msg_message("teachdumb",
- "teacher amount", u, j));
- }
- if (teaching == 0) return;
+ if ((i = get_effect(u, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */
+ i = min(i, u->number * TEACHNUMBER);
+ /* Trank wirkt pro Schüler, nicht pro Lehrer */
+ teaching -= i * 30;
+ change_effect(u, oldpotiontype[P_FOOL], -i);
+ j = teaching / 30;
+ add_message(&u->faction->msgs, msg_message("teachdumb",
+ "teacher amount", u, j));
+ }
+ if (teaching == 0) return;
- strcpy(order, locale_string(u->faction->locale, keywords[K_TEACH]));
- u2 = 0;
- count = 0;
+ u2 = 0;
+ count = 0;
init_tokens(ord);
skip_token();
#if TEACH_ALL
- if (getparam(u->faction->locale)==P_ANY) {
- unit * student = r->units;
- skill_t teachskill[MAXSKILLS];
- int i = 0;
- do {
- sk = getskill(u->faction->locale);
- teachskill[i++]=sk;
- } while (sk!=NOSKILL);
- while (teaching && student) {
- if (student->faction == u->faction) {
+ if (getparam(u->faction->locale)==P_ANY) {
+ unit * student = r->units;
+ skill_t teachskill[MAXSKILLS];
+ int i = 0;
+ do {
+ sk = getskill(u->faction->locale);
+ teachskill[i++]=sk;
+ } while (sk!=NOSKILL);
+ while (teaching && student) {
+ if (student->faction == u->faction) {
#ifdef NEW_DAEMONHUNGER_RULE
- if (LongHunger(student)) continue;
-#else
- if (fval(student, UFL_HUNGER)) continue;
-#endif
- if (get_keyword(student->thisorder) == K_STUDY) {
- /* Input ist nun von student->thisorder !! */
- init_tokens(student->thisorder);
- skip_token();
- sk = getskill(student->faction->locale);
- if (sk!=NOSKILL && teachskill[0]!=NOSKILL) {
- for (i=0;teachskill[i]!=NOSKILL;++i) if (sk==teachskill[i]) break;
- sk = teachskill[i];
- }
- if (sk != NOSKILL && eff_skill_study(u, sk, r)-TEACHDIFFERENCE > eff_skill_study(student, sk, r)) {
- teaching -= teach_unit(u, student, teaching, sk, true, &academy);
- }
- }
- }
- student = student->next;
- }
-#ifdef TEACH_FRIENDS
- while (teaching && student) {
- if (student->faction != u->faction && alliedunit(u, student->faction, HELP_GUARD)) {
-#ifdef NEW_DAEMONHUNGER_RULE
- if (LongHunger(student)) continue;
+ if (LongHunger(student)) continue;
#else
if (fval(student, UFL_HUNGER)) continue;
#endif
- if (get_keyword(student->thisorder) == K_STUDY) {
- /* Input ist nun von student->thisorder !! */
+ if (get_keyword(student->thisorder) == K_STUDY) {
+ /* Input ist nun von student->thisorder !! */
init_tokens(student->thisorder);
skip_token();
- sk = getskill(student->faction->locale);
- if (sk != NOSKILL && eff_skill_study(u, sk, r)-TEACHDIFFERENCE >= eff_skill(student, sk, r)) {
- teaching -= teach_unit(u, student, teaching, sk, true, &academy);
- }
- }
- }
- student = student->next;
- }
-#endif
- }
- else
-#endif
- for (;;) {
- /* Da später tokens aus (u2->thisorder) verwendet werden,
- * muß hier wieder von vorne gelesen werden. Also merken wir uns, an
- * welcher Stelle wir hier waren...
- * TODO: Optimierung wäre hier wirklich sinnvoll
- *
- * Beispiel count = 1: LEHRE 101 102 103
- *
- * LEHRE und 101 wird gelesen (und ignoriert), und dann wird
- * getunit die einheit 102 zurück liefern. */
-
- init_tokens(u->thisorder);
- skip_token();
- for (j = count; j; j--) getstrtoken();
-
- u2 = getunit(r, u->faction);
-
- /* Falls keine Unit gefunden, abbrechen - außer es gibt überhaupt keine
- * Unit, dann gibt es zusätzlich noch einen Fehler */
-
- if (!u2) {
-
- /* Finde den string, der den Fehler verursacht hat */
-
- init_tokens(u->thisorder);
- skip_token();
- for (j = count; j; j--) getstrtoken();
-
- s = getstrtoken();
-
- /* Falls es keinen String gibt, ist die Liste der Einheiten zuende */
-
- if (!s[0])
- return;
-
- /* Beginne die Fehlermeldung */
-
- strcpy(buf, "Die Einheit '");
-
- if (findparam(s, u->faction->locale) == P_TEMP) {
- /* Für: "Die Einheit 'TEMP ZET' wurde nicht gefunden" oder "Die Einheit
- * 'TEMP' wurde nicht gefunden" */
-
- scat(s);
- s = getstrtoken();
- if (s[0])
- scat(" ");
-
- /* Um nachher weiter einlesen zu koennen */
- count++;
- }
- scat(s);
- scat("' wurde nicht gefunden");
- mistake(u, u->thisorder, buf, MSG_EVENT);
-
- count++;
- continue;
- }
- /* Defaultorder zusammenbauen. TEMP-Einheiten werden automatisch in
- * ihre neuen Nummern übersetzt. */
- strcat(order, " ");
- strcat(order, unitid(u2));
- set_order(&u->lastorder, parse_order(order, u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
-
- /* Wir müssen nun hochzählen, wieviele Einheiten wir schon abgearbeitet
- * haben, damit mit getstrtoken() die richtige Einheit geholt werden kann.
- * Falls u2 ein Alias hat, ist sie neu, und es wurde ein TEMP verwendet, um
- * sie zu beschreiben. */
-
- count++;
- if (ualias(u2))
- count++;
-
- if (get_keyword(u2->thisorder) != K_STUDY) {
- add_message(&u->faction->msgs,
- msg_feedback(u, u->thisorder, "teach_nolearn", "student", u2));
- continue;
- }
- /* Input ist nun von u2->thisorder !! */
- init_tokens(u2->thisorder);
- skip_token();
- sk = getskill(u2->faction->locale);
- if (sk == NOSKILL) {
- add_message(&u->faction->msgs,
- msg_feedback(u, u->thisorder, "teach_nolearn", "student", u2));
- continue;
- }
-
- /* u is teacher, u2 is student */
- if (eff_skill_study(u2, sk, r) > eff_skill_study(u, sk, r)-TEACHDIFFERENCE) {
- add_message(&u->faction->msgs,
- msg_feedback(u, u->thisorder, "teach_asgood", "student", u2));
- continue;
- }
- if (sk == SK_MAGIC) {
- /* ist der Magier schon spezialisiert, so versteht er nur noch
- * Lehrer seines Gebietes */
- if (find_magetype(u2) != 0
- && find_magetype(u) != find_magetype(u2))
- {
- sprintf(buf, "%s versteht unsere Art von Magie nicht", unitname(u2));
- mistake(u, u->thisorder, buf, MSG_EVENT);
- continue;
- }
- }
-
- teaching -= teach_unit(u, u2, teaching, sk, false, &academy);
-
+ sk = getskill(student->faction->locale);
+ if (sk!=NOSKILL && teachskill[0]!=NOSKILL) {
+ for (i=0;teachskill[i]!=NOSKILL;++i) if (sk==teachskill[i]) break;
+ sk = teachskill[i];
}
- if (academy) {
- academy = academy/30;
- learn_skill(u, sk, academy/30.0/TEACHNUMBER);
- }
+ if (sk != NOSKILL && eff_skill_study(u, sk, r)-TEACHDIFFERENCE > eff_skill_study(student, sk, r)) {
+ teaching -= teach_unit(u, student, teaching, sk, true, &academy);
+ }
+ }
+ }
+ student = student->next;
+ }
+#ifdef TEACH_FRIENDS
+ while (teaching && student) {
+ if (student->faction != u->faction && alliedunit(u, student->faction, HELP_GUARD)) {
+#ifdef NEW_DAEMONHUNGER_RULE
+ if (LongHunger(student)) continue;
+#else
+ if (fval(student, UFL_HUNGER)) continue;
+#endif
+ if (get_keyword(student->thisorder) == K_STUDY) {
+ /* Input ist nun von student->thisorder !! */
+ init_tokens(student->thisorder);
+ skip_token();
+ sk = getskill(student->faction->locale);
+ if (sk != NOSKILL && eff_skill_study(u, sk, r)-TEACHDIFFERENCE >= eff_skill(student, sk, r)) {
+ teaching -= teach_unit(u, student, teaching, sk, true, &academy);
+ }
+ }
+ }
+ student = student->next;
+ }
+#endif
+ }
+ else
+#endif
+ {
+ static char zOrder[BUFSIZE];
+ order * new_order;
+
+ strcpy(zOrder, locale_string(u->faction->locale, keywords[K_TEACH]));
+ init_tokens(ord);
+ skip_token();
+ for (;;) {
+
+ u2 = getunit(r, u->faction);
+
+ /* Falls keine Unit gefunden, abbrechen - außer es gibt überhaupt keine
+ * Unit, dann gibt es zusätzlich noch einen Fehler */
+
+ if (!u2) {
+
+ /* Finde den string, der den Fehler verursacht hat */
+ parser_pushstate();
+ init_tokens(ord);
+ skip_token();
+ for (j = count; j; j--) {
+ /* skip over the first 'count' units */
+ getunit(r, u->faction);
+ }
+
+ s = getstrtoken();
+
+ if (!s[0]) {
+ /* Falls es keinen String gibt, ist einfach nur die Liste der Einheiten
+ * zu ende. dann raus hier */
+ parser_popstate();
+ break;
+ }
+
+ /* Beginne die Fehlermeldung */
+
+ strcpy(buf, "Die Einheit '");
+
+ if (findparam(s, u->faction->locale) == P_TEMP) {
+ /* Für: "Die Einheit 'TEMP ZET' wurde nicht gefunden" oder "Die Einheit
+ * 'TEMP' wurde nicht gefunden" */
+
+ scat(s);
+ s = getstrtoken();
+ if (s[0])
+ scat(" ");
+
+ /* count++; -- unnötig/alt? Um nachher weiter einlesen zu koennen */
+
+ }
+ scat(s);
+ scat("' wurde nicht gefunden");
+ mistake(u, ord, buf, MSG_EVENT);
+
+ count++;
+ parser_popstate();
+ continue;
+ }
+ /* Defaultorder zusammenbauen. TEMP-Einheiten werden automatisch in
+ * ihre neuen Nummern übersetzt. */
+ strcat(zOrder, " ");
+ strcat(zOrder, unitid(u2));
+
+ /* Wir müssen nun hochzählen, wieviele Einheiten wir schon abgearbeitet
+ * haben, damit mit getstrtoken() die richtige Einheit geholt werden kann.
+ * Falls u2 ein Alias hat, ist sie neu, und es wurde ein TEMP verwendet, um
+ * sie zu beschreiben. */
+
+ count++;
+
+ if (get_keyword(u2->thisorder) != K_STUDY) {
+ add_message(&u->faction->msgs,
+ msg_feedback(u, ord, "teach_nolearn", "student", u2));
+ continue;
+ }
+ /* Input ist nun von u2->thisorder !! */
+ init_tokens(u2->thisorder);
+ skip_token();
+ sk = getskill(u2->faction->locale);
+ if (sk == NOSKILL) {
+ add_message(&u->faction->msgs,
+ msg_feedback(u, ord, "teach_nolearn", "student", u2));
+ continue;
+ }
+
+ /* u is teacher, u2 is student */
+ if (eff_skill_study(u2, sk, r) > eff_skill_study(u, sk, r)-TEACHDIFFERENCE) {
+ add_message(&u->faction->msgs,
+ msg_feedback(u, ord, "teach_asgood", "student", u2));
+ continue;
+ }
+ if (sk == SK_MAGIC) {
+ /* ist der Magier schon spezialisiert, so versteht er nur noch
+ * Lehrer seines Gebietes */
+ if (find_magetype(u2) != 0
+ && find_magetype(u) != find_magetype(u2))
+ {
+ sprintf(buf, "%s versteht unsere Art von Magie nicht", unitname(u2));
+ mistake(u, ord, buf, MSG_EVENT);
+ continue;
+ }
+ }
+
+ teaching -= teach_unit(u, u2, teaching, sk, false, &academy);
+
+ }
+ new_order = parse_order(zOrder, u->faction->locale);
+#ifdef LASTORDER
+ set_order(&u->lastorder, new_order);
+#else
+ copy_order(ord, new_order);
+#endif
+ free_order(new_order); /* parse_order & set_order have each increased the refcount */
+ }
+ if (academy && sk!=NOSKILL) {
+ academy = academy/30; /* anzahl gelehrter wochen, max. 10 */
+ learn_skill(u, sk, academy/30.0/TEACHNUMBER);
+ }
}
/* ------------------------------------------------------------- */
diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c
index 30dceb7e4..375b29e4c 100644
--- a/src/common/kernel/build.c
+++ b/src/common/kernel/build.c
@@ -795,7 +795,7 @@ maxbuild(const unit * u, const construction * cons)
/** old build routines */
void
-build_building(unit * u, const building_type * btype, int want)
+build_building(unit * u, const building_type * btype, int want, order * ord)
{
region * r = u->region;
boolean newbuilding = false;
@@ -804,9 +804,10 @@ build_building(unit * u, const building_type * btype, int want)
/* einmalige Korrektur */
static char buffer[8 + IDSIZE + 1 + NAMESIZE + 1];
const char *string2;
+ order * new_order;
if (eff_skill(u, SK_BUILDING, r) == 0) {
- cmistake(u, u->thisorder, 101, MSG_PRODUCE);
+ cmistake(u, ord, 101, MSG_PRODUCE);
return;
}
@@ -825,7 +826,7 @@ build_building(unit * u, const building_type * btype, int want)
b = u->building;
} else {
/* keine neue Burg anfangen wenn eine Nummer angegeben war */
- cmistake(u, u->thisorder, 6, MSG_PRODUCE);
+ cmistake(u, ord, 6, MSG_PRODUCE);
return;
}
}
@@ -835,17 +836,17 @@ build_building(unit * u, const building_type * btype, int want)
if (b && fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype)) {
/* only one of these per region */
- cmistake(u, u->thisorder, 93, MSG_PRODUCE);
+ cmistake(u, ord, 93, MSG_PRODUCE);
return;
}
if (besieged(u)) {
/* units under siege can not build */
- cmistake(u, u->thisorder, 60, MSG_PRODUCE);
+ cmistake(u, ord, 60, MSG_PRODUCE);
return;
}
if (btype->flags & BTF_NOBUILD) {
/* special building, cannot be built */
- cmistake(u, u->thisorder, 221, MSG_PRODUCE);
+ cmistake(u, ord, 221, MSG_PRODUCE);
return;
}
@@ -870,7 +871,7 @@ build_building(unit * u, const building_type * btype, int want)
switch (built) {
case ECOMPLETE:
/* the building is already complete */
- cmistake(u, u->thisorder, 4, MSG_PRODUCE);
+ cmistake(u, ord, 4, MSG_PRODUCE);
return;
case ENOMATERIALS: {
/* something missing from the list of materials */
@@ -887,14 +888,14 @@ build_building(unit * u, const building_type * btype, int want)
);
ch = ch+strlen(ch);
}
- ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "build_required",
+ ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "build_required",
"required", buf));
return;
}
case ELOWSKILL:
case ENEEDSKILL:
/* no skill, or not enough skill points to build */
- cmistake(u, u->thisorder, 50, MSG_PRODUCE);
+ cmistake(u, ord, 50, MSG_PRODUCE);
return;
}
@@ -928,8 +929,14 @@ build_building(unit * u, const building_type * btype, int want)
strcpy(buffer, locale_string(u->faction->locale, "defaultorder"));
else
sprintf(buffer, "%s %d %s %s", locale_string(u->faction->locale, keywords[K_MAKE]), want-built, string2, buildingid(b));
- set_order(&u->lastorder, parse_order(buffer, u->faction->locale));
- free_order(u->lastorder);
+
+ new_order = parse_order(buffer, u->faction->locale);
+#ifdef LASTORDER
+ set_order(&u->lastorder, new_order);
+#else
+ copy_order(ord, new_order);
+#endif
+ free_order(new_order);
b->size += built;
update_lighthouse(b);
@@ -976,19 +983,20 @@ build_ship(unit * u, ship * sh, int want)
}
void
-create_ship(region * r, unit * u, const struct ship_type * newtype, int want)
+create_ship(region * r, unit * u, const struct ship_type * newtype, int want, order * ord)
{
static char buffer[IDSIZE + 2 * KEYWORDSIZE + 3];
ship *sh;
int msize;
const construction * cons = newtype->construction;
+ order * new_order;
if (!eff_skill(u, SK_SHIPBUILDING, r)) {
- cmistake(u, u->thisorder, 100, MSG_PRODUCE);
+ cmistake(u, ord, 100, MSG_PRODUCE);
return;
}
if (besieged(u)) {
- cmistake(u, u->thisorder, 60, MSG_PRODUCE);
+ cmistake(u, ord, 60, MSG_PRODUCE);
return;
}
@@ -996,13 +1004,13 @@ create_ship(region * r, unit * u, const struct ship_type * newtype, int want)
if (eff_skill(u, cons->skill, r) < cons->minskill) {
sprintf(buf, "Um %s zu bauen, braucht man ein Talent von "
"mindestens %d.", newtype->name[1], cons->minskill);
- mistake(u, u->thisorder, buf, MSG_PRODUCE);
+ mistake(u, ord, buf, MSG_PRODUCE);
return;
}
msize = maxbuild(u, cons);
if (msize==0) {
- cmistake(u, u->thisorder, 88, MSG_PRODUCE);
+ cmistake(u, ord, 88, MSG_PRODUCE);
return;
}
if (want>0) want = min(want, msize);
@@ -1015,8 +1023,14 @@ create_ship(region * r, unit * u, const struct ship_type * newtype, int want)
fset(u, UFL_OWNER);
sprintf(buffer, "%s %s %s",
locale_string(u->faction->locale, keywords[K_MAKE]), locale_string(u->faction->locale, parameters[P_SHIP]), shipid(sh));
- set_order(&u->lastorder, parse_order(buffer, u->faction->locale));
- free_order(u->lastorder);
+
+ new_order = parse_order(buffer, u->faction->locale);
+#ifdef LASTORDER
+ set_order(&u->lastorder, new_order);
+#else
+ copy_order(ord, new_order);
+#endif
+ free_order(new_order);
build_ship(u, sh, want);
}
diff --git a/src/common/kernel/build.h b/src/common/kernel/build.h
index 7ed067268..1a0e44096 100644
--- a/src/common/kernel/build.h
+++ b/src/common/kernel/build.h
@@ -68,7 +68,7 @@ extern boolean can_contact(const struct region *r, const struct unit *u, const s
void do_siege(void);
void build_road(struct region * r, struct unit * u, int size, direction_t d);
-void create_ship(struct region * r, struct unit * u, const struct ship_type * newtype, int size);
+void create_ship(struct region * r, struct unit * u, const struct ship_type * newtype, int size, struct order * ord);
void continue_ship(struct region * r, struct unit * u, int size);
struct building * getbuilding(const struct region * r);
diff --git a/src/common/kernel/building.h b/src/common/kernel/building.h
index c690d5920..ec5852e2e 100644
--- a/src/common/kernel/building.h
+++ b/src/common/kernel/building.h
@@ -112,7 +112,7 @@ extern const char * buildingtype(const struct building * b, int bsize);
extern const char * buildingname(const struct building * b);
extern int buildingcapacity(const struct building * b);
extern struct building *new_building(const struct building_type * typ, struct region * r, const struct locale * lang);
-void build_building(struct unit * u, const struct building_type * typ, int size);
+void build_building(struct unit * u, const struct building_type * typ, int size, struct order * ord);
/* Alte Gebäudetypen: */
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index 4c1e1b4ae..ce77f7701 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -344,7 +344,6 @@ const char *keywords[MAXKEYWORDS] =
"BANNER",
"ARBEITEN",
"ATTACKIEREN",
- "BIETEN",
"BEKLAUEN",
"BELAGERE",
"BENENNEN",
@@ -398,7 +397,6 @@ const char *keywords[MAXKEYWORDS] =
"MAGIEGEBIET",
"PIRATERIE",
"NEUSTART",
- "WARTEN",
"GRUPPE",
"OPFERE",
"BETEN",
@@ -1259,21 +1257,50 @@ count_maxmigrants(const faction * f)
/* GET STR, I zur Eingabe von Daten liest diese aus dem Buffer, der beim ersten
* Aufruf inititialisiert wird? */
-static const unsigned char *current_token;
+typedef struct parser_state {
+ const unsigned char *current_token;
+ char * current_cmd;
+ struct parser_state * next;
+} parser_state;
+
+static parser_state * state;
void
init_tokens_str(const char * initstr)
{
- current_token = (const unsigned char *)initstr;
+ if (state==NULL) {
+ state = malloc(sizeof(parser_state));
+ state->current_cmd = NULL;
+ }
+ state->current_token = (const unsigned char *)initstr;
}
void
init_tokens(const struct order * ord)
{
- static char * cmd = NULL;
- if (cmd!=NULL) free(cmd);
- cmd = getcommand(ord);
- init_tokens_str(cmd);
+ if (state==NULL) state = malloc(sizeof(parser_state));
+ else if (state->current_cmd!=NULL) free(state->current_cmd);
+ state->current_cmd = getcommand(ord);
+ init_tokens_str(state->current_cmd);
+}
+
+void
+parser_pushstate(void)
+{
+ parser_state * new_state = malloc(sizeof(parser_state));
+ new_state->current_cmd = NULL;
+ new_state->current_token = NULL;
+ new_state->next = state;
+ state = new_state;
+}
+
+void
+parser_popstate(void)
+{
+ parser_state * new_state = state->next;
+ if (state->current_cmd!=NULL) free(state->current_cmd);
+ free(state);
+ state = new_state;
}
void
@@ -1281,23 +1308,23 @@ skip_token(void)
{
char quotechar = 0;
- while (isspace(*current_token)) ++current_token;
- while (*current_token) {
- if (isspace(*current_token) && quotechar==0) {
+ while (isspace(*state->current_token)) ++state->current_token;
+ while (*state->current_token) {
+ if (isspace(*state->current_token) && quotechar==0) {
return;
} else {
- switch(*current_token) {
+ switch(*state->current_token) {
case '"':
case '\'':
- if (*current_token==quotechar) return;
- quotechar = *current_token;
+ if (*state->current_token==quotechar) return;
+ quotechar = *state->current_token;
break;
case ESCAPE_CHAR:
- ++current_token;
+ ++state->current_token;
break;
}
}
- ++current_token;
+ ++state->current_token;
}
}
@@ -1377,13 +1404,13 @@ igetstrtoken(const char * initstr)
init_tokens_str(initstr);
}
- return parse_token((const char**)¤t_token);
+ return parse_token((const char**)&state->current_token);
}
const char *
getstrtoken(void)
{
- return parse_token((const char**)¤t_token);
+ return parse_token((const char**)&state->current_token);
}
int
@@ -1870,12 +1897,17 @@ unit *
create_unit(region * r, faction * f, int number, const struct race *urace, int id, const char * dname, unit *creator)
{
unit * u = calloc(1, sizeof(unit));
+ order * deford = default_order(f->locale);
assert(urace);
assert(f->alive);
u_setfaction(u, f);
set_order(&u->thisorder, NULL);
- set_order(&u->lastorder, default_order(f->locale));
+#ifdef LASTORDER
+ set_order(&u->lastorder, deford);
+#else
+ addlist(&u->orders, deford);
+#endif
u_seteffstealth(u, -1);
u->race = urace;
u->irace = urace;
@@ -2600,7 +2632,10 @@ init_used_faction_ids(void)
void
make_undead_unit(unit * u)
{
+#ifdef LASTORDER
set_order(&u->lastorder, NULL);
+#endif
+ free_orders(&u->orders);
name_unit(u);
fset(u, UFL_ISNEW);
}
diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h
index 4740a52de..524b7c014 100644
--- a/src/common/kernel/eressea.h
+++ b/src/common/kernel/eressea.h
@@ -161,6 +161,7 @@ struct building_type;
#define SAVEALLIANCE_VERSION 317
#define CLAIM_VERSION 318
#define BACTION_VERSION 319 /* building action gets a param string */
+#define NOLASTORDER_VERSION 320 /* do not use lastorder */
#define MIN_VERSION ALLIANCES_VERSION
#define REGIONOWNERS_VERSION 400
@@ -168,8 +169,10 @@ struct building_type;
#ifdef REGIONOWNERS
# define RELEASE_VERSION REGIONOWNERS_VERSION
-#else
+#elif defined(LASTORDER)
# define RELEASE_VERSION BACTION_VERSION
+#else
+# define RELEASE_VERSION NOLASTORDER_VERSION
#endif
#if RESOURCE_CONVERSION
@@ -377,7 +380,6 @@ enum {
K_BANNER,
K_WORK,
K_ATTACK,
- K_BIETE,
K_STEAL,
K_BESIEGE,
K_NAME,
@@ -431,7 +433,6 @@ enum {
K_MAGIEGEBIET,
K_PIRACY,
K_RESTART,
- K_WAIT,
K_GROUP,
K_SACRIFICE,
K_PRAY,
@@ -944,6 +945,8 @@ extern void init_tokens_str(const char * initstr); /* initialize token parsing *
extern void init_tokens(const struct order * ord); /* initialize token parsing */
extern void skip_token(void);
extern const char * parse_token(const char ** str);
+extern void parser_pushstate(void);
+extern void parser_popstate(void);
extern skill_t findskill(const char *s, const struct locale * lang);
diff --git a/src/common/kernel/karma.c b/src/common/kernel/karma.c
index baa1eaffb..ff7e4f8d1 100644
--- a/src/common/kernel/karma.c
+++ b/src/common/kernel/karma.c
@@ -14,6 +14,7 @@
/* TODO: enum auf fst_ umstellen. Pointer auf Display-Routine */
#include
#include "eressea.h"
+
#include "karma.h"
/* kernel includes */
diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c
index 95231cba0..5d5176cd9 100644
--- a/src/common/kernel/magic.c
+++ b/src/common/kernel/magic.c
@@ -2004,7 +2004,7 @@ new_castorder(void *u, unit *u2, spell *sp, region *r, int lev,
corder->force = force;
corder->rt = r;
corder->distance = range;
- corder->order = copy_order(ord);
+ corder->order = duplicate_order(ord);
corder->par = p;
return corder;
diff --git a/src/common/kernel/message.c b/src/common/kernel/message.c
index d77aadef7..58708c7f7 100644
--- a/src/common/kernel/message.c
+++ b/src/common/kernel/message.c
@@ -332,7 +332,7 @@ mistake(const unit * u, struct order * ord, const char *comment, int mtype)
if (u->faction->no != MONSTER_FACTION) {
char * cmt = strdup(comment);
ADDMSG(&u->faction->msgs, msg_message("mistake",
- "command error unit region", copy_order(ord), cmt, u, u->region));
+ "command error unit region", duplicate_order(ord), cmt, u, u->region));
}
}
@@ -345,7 +345,7 @@ cmistake(const unit * u, struct order *ord, int mno, int mtype)
if (u->faction->no == MONSTER_FACTION) return;
sprintf(ebuf, "error%d", mno);
ADDMSG(&u->faction->msgs, msg_message(ebuf,
- "command unit region", copy_order(ord), u, u->region));
+ "command unit region", duplicate_order(ord), u, u->region));
}
extern unsigned int new_hashstring(const char* s);
diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c
index d4042b710..9de0fc0f5 100644
--- a/src/common/kernel/movement.c
+++ b/src/common/kernel/movement.c
@@ -860,7 +860,7 @@ static const char *shortdirections[MAXDIRECTIONS] =
};
static void
-cycle_route(unit *u, int gereist)
+cycle_route(order * ord, unit *u, int gereist)
{
int cm = 0;
char tail[1024];
@@ -869,13 +869,14 @@ cycle_route(unit *u, int gereist)
direction_t d = NODIRECTION;
boolean paused = false;
boolean pause;
+ order * norder;
- if (get_keyword(u->thisorder) != K_ROUTE) return;
+ if (get_keyword(ord) != K_ROUTE) return;
tail[0] = '\0';
strcpy(neworder, locale_string(u->faction->locale, keywords[K_ROUTE]));
- init_tokens(u->thisorder);
+ init_tokens(ord);
skip_token();
for (cm=0;;++cm) {
@@ -909,8 +910,13 @@ cycle_route(unit *u, int gereist)
}
strcat(neworder, tail);
- set_order(&u->lastorder, parse_order(neworder, u->faction->locale));
- free_order(u->lastorder); /* parse_order & set_order have each increased the refcount */
+ norder = parse_order(neworder, u->faction->locale);
+#ifdef LASTORDER
+ set_order(&u->lastorder, norder);
+#else
+ copy_order(ord, norder);
+#endif
+ free_order(norder);
}
static boolean
@@ -1311,7 +1317,7 @@ travel_route(unit * u, region_list * route_begin, region_list * route_end, order
region * next = r;
setguard(u, GUARD_NONE);
- cycle_route(u, steps);
+ cycle_route(ord, u, steps);
if (mode==TRAVEL_RUNNING) {
walkmode = 0;
@@ -1659,7 +1665,7 @@ sail(unit * u, order * ord, boolean move_on_land, region_list **routep)
unit * hafenmeister;
/* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten
* transferiert wurden, kann der aktuelle Befehl gelöscht werden. */
- cycle_route(u, step);
+ cycle_route(ord, u, step);
set_order(&u->thisorder, NULL);
set_coast(sh, last_point, current_point);
diff --git a/src/common/kernel/order.c b/src/common/kernel/order.c
index 93e636614..71ae03442 100644
--- a/src/common/kernel/order.c
+++ b/src/common/kernel/order.c
@@ -26,6 +26,16 @@ static int nlocales = 0;
#undef SHORT_STRINGS
+void
+copy_order(order * dst, const order * src)
+{
+ if (dst->_str) free(dst->_str);
+ dst->_str = strdup(src->_str);
+ dst->_keyword = src->_keyword;
+ dst->_lindex = src->_lindex;
+ dst->_persistent = src->_persistent;
+}
+
keyword_t
get_keyword(const order * ord)
{
@@ -70,7 +80,7 @@ free_order(order * ord)
}
order *
-copy_order(order * ord)
+duplicate_order(order * ord)
{
if (ord!=NULL) ++ord->_refcount;
return ord;
@@ -81,7 +91,7 @@ set_order(struct order ** destp, struct order * src)
{
if (*destp==src) return;
free_order(*destp);
- *destp = copy_order(src);
+ *destp = duplicate_order(src);
}
void
@@ -156,19 +166,82 @@ parse_order(const char * s, const struct locale * lang)
}
boolean
-is_persistent(const order * cmd)
+is_exclusive(const order * ord)
{
- switch (cmd->_keyword) {
+ const struct locale * lang = locale_array[ord->_lindex];
+ param_t param;
+
+ switch (ord->_keyword) {
+ case K_MOVE:
+ case K_WEREWOLF:
+ /* these should not become persistent */
+ 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_ZUECHTE:
+ case K_PIRACY:
+ return true;
+
+#if GROWING_TREES
+ case K_PFLANZE:
+ return true;
+#endif
+
+ 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;
+}
+
+boolean
+is_persistent(const order * ord)
+{
+ boolean persist = ord->_persistent!=0;
+ switch (ord->_keyword) {
+ case K_MOVE:
+ case K_WEREWOLF:
case NOKEYWORD:
+ /* lang, aber niemals persistent! */
return false;
+
case K_KOMMENTAR:
case K_LIEFERE:
return true;
}
-#ifdef AT_PERSISTENT
- if (cmd->_persistent) return true;
-#endif /* Nur kurze Befehle! */
- return false;
+
+ return persist || is_exclusive(ord);
}
char *
diff --git a/src/common/kernel/order.h b/src/common/kernel/order.h
index 4f5194b4e..3e43ad27c 100644
--- a/src/common/kernel/order.h
+++ b/src/common/kernel/order.h
@@ -37,9 +37,10 @@ typedef struct order {
/* constructor */
extern struct order * parse_order(const char * s, const struct locale * lang);
+extern void copy_order(order * dst, const order * src);
/* reference counted copies of orders: */
-extern struct order * copy_order(struct order * ord);
+extern struct order * duplicate_order(struct order * ord);
extern void free_order(struct order * ord);
extern void free_orders(struct order ** olist);
@@ -48,6 +49,7 @@ extern keyword_t get_keyword(const struct order * ord);
extern void set_order(struct order ** destp, struct order * src);
extern char * getcommand(const struct order * ord);
extern boolean is_persistent(const struct order *ord);
+extern boolean is_exclusive(const struct order *ord);
extern char * write_order(const struct order * ord, const struct locale * lang, char * buffer, size_t size);
#ifdef __cplusplus
}
diff --git a/src/common/kernel/pathfinder.c b/src/common/kernel/pathfinder.c
index d73608871..bebb4af51 100644
--- a/src/common/kernel/pathfinder.c
+++ b/src/common/kernel/pathfinder.c
@@ -111,7 +111,7 @@ regions_in_range(struct region * start, int maxdist, boolean (*allowed)(const st
region * rn = rconnect(r, d);
if (rn==NULL) continue;
if (fval(rn, FL_MARK)) continue; /* already been there */
- if (!allowed(r, rn)) continue; /* can't go there */
+ if (allowed && !allowed(r, rn)) continue; /* can't go there */
/* add the region to the list of available ones. */
add_regionlist(&rlist, rn);
diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c
index 711ab7ade..b5c2d72b5 100644
--- a/src/common/kernel/reports.c
+++ b/src/common/kernel/reports.c
@@ -414,6 +414,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode)
}
}
}
+#ifdef LASTORDER
if (!isbattle && u->lastorder) {
char * cmd = getcommand(u->lastorder);
scat(", \"");
@@ -421,6 +422,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode)
scat("\"");
free(cmd);
}
+#endif
}
i = 0;
diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c
index adf274db8..d7414175f 100644
--- a/src/common/kernel/save.c
+++ b/src/common/kernel/save.c
@@ -1101,7 +1101,7 @@ readunit(FILE * F)
}
} else
u->flags = ri(F) & ~UFL_DEBUG;
- /* Kurze persistente Befehle einlesen */
+ /* Persistente Befehle einlesen */
free_orders(&u->orders);
freadstr(F, buf, sizeof(buf));
while (*buf != 0) {
@@ -1109,8 +1109,19 @@ readunit(FILE * F)
if (ord!=NULL) addlist(&u->orders, ord);
freadstr(F, buf, sizeof(buf));
}
- freadstr(F, buf, sizeof(buf));
- u->lastorder = parse_order(buf, u->faction->locale);
+ if (global.data_versionfaction->locale);
+ if (ord!=NULL) {
+#ifdef LASTORDER
+ set_order(&u->lastorder, ord);
+ free_order(ord);
+#else
+ addlist(&u->orders, ord);
+#endif
+ }
+ }
set_order(&u->thisorder, NULL);
assert(u->number >= 0);
@@ -1219,9 +1230,11 @@ writeunit(FILE * F, const unit * u)
/* write an empty string to terminate the list */
fwriteorder(F, NULL, u->faction->locale);
wnl(F);
+#if RELEASE_VERSIONlastorder, u->faction->locale);
wnl(F);
+#endif
assert(u->number >= 0);
assert(u->race);
diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c
index 4aa25a04c..f8046f072 100644
--- a/src/common/kernel/unit.c
+++ b/src/common/kernel/unit.c
@@ -814,7 +814,9 @@ u_setfaction(unit * u, faction * f)
join_group(u, NULL);
free_orders(&u->orders);
set_order(&u->thisorder, NULL);
+#ifdef LASTORDER
set_order(&u->lastorder, NULL);
+#endif
}
if (u->prevF) u->prevF->nextF = u->nextF;
else if (u->faction) {
diff --git a/src/common/kernel/unit.h b/src/common/kernel/unit.h
index 6c15636d8..4a2f200d9 100644
--- a/src/common/kernel/unit.h
+++ b/src/common/kernel/unit.h
@@ -55,9 +55,9 @@ struct skill;
/* Flags, die gespeichert werden sollen: */
#ifndef HEROES
-# define UFL_SAVEMASK (UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL)
+# define UFL_SAVEMASK (UFL_MOVED | UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL)
#else
-# define UFL_SAVEMASK (UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL | UFL_HERO)
+# define UFL_SAVEMASK (UFL_MOVED | UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL | UFL_HERO)
#endif
#ifdef HEROES
@@ -94,7 +94,9 @@ typedef struct unit {
/* orders */
struct order *orders;
struct order * thisorder;
+#ifdef LASTORDER
struct order * lastorder;
+#endif
/* race and illusionary race */
const struct race * race;
diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c
index 95868304d..90a553117 100644
--- a/src/common/modules/arena.c
+++ b/src/common/modules/arena.c
@@ -376,8 +376,10 @@ guardian_faction(plane * pl, int id)
u = createunit(r, f, 1, new_race[RC_GOBLIN]);
set_string(&u->name, "Igjarjuks Auge");
set_item(u, I_RING_OF_INVISIBILITY, 1);
- u->thisorder = calloc(1, sizeof(char));
- u->lastorder = calloc(1, sizeof(char));
+ set_order(&u->thisorder, NULL);
+#ifdef LASTORDER
+ set_order(&u->lastorder, NULL);
+#endif
fset(u, UFL_PARTEITARNUNG);
set_money(u, 1000);
}
diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp
index e262c52dc..fe14d5511 100644
--- a/src/eressea/server.cpp
+++ b/src/eressea/server.cpp
@@ -114,6 +114,7 @@ extern "C" {
extern char * g_resourcedir;
extern boolean nonr;
+ extern boolean nosh;
extern boolean nocr;
extern boolean noreports;
extern boolean nomer;
@@ -471,6 +472,7 @@ usage(const char * prog, const char * arg)
"--debug : schreibt Debug-Ausgaben in die Datei debug\n"
"--nocr : keine CRs\n"
"--nonr : keine Reports\n"
+ "--nosh : keine Mail-Skripte\n"
"--crabsolute : absolute Koordinaten im CR\n"
"--help : help\n", prog);
return -1;
@@ -509,6 +511,7 @@ read_args(int argc, char **argv, lua_State * luaState)
else if (strcmp(argv[i]+2, "xml")==0) xmlfile = argv[++i];
else if (strcmp(argv[i]+2, "dirtyload")==0) dirtyload = true;
else if (strcmp(argv[i]+2, "nonr")==0) nonr = true;
+ else if (strcmp(argv[i]+2, "nosh")==0) nosh = true;
else if (strcmp(argv[i]+2, "lomem")==0) lomem = true;
else if (strcmp(argv[i]+2, "nobattle")==0) nobattle = true;
else if (strcmp(argv[i]+2, "nomonsters")==0) nomonsters = true;