diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c
index 1a9adb66c..66ec89ef2 100644
--- a/src/common/gamecode/creport.c
+++ b/src/common/gamecode/creport.c
@@ -677,101 +677,108 @@ cr_output_unit(FILE * F, const region * r,
fprintf(F, "%d;belagert\n", b->no);
/* additional information for own units */
- if (u->faction == f || omniscient(f)) {
- order * ord;
- const char *c;
- int i;
- const attrib * a;
+ if (u->faction == f || omniscient(f)) {
+ order * ord;
+ const char *c;
+ char * cmd;
+ int i;
+ const attrib * a;
- a = a_find(u->attribs, &at_follow);
- if (a) {
- unit * u = (unit*)a->data.v;
- if (u) fprintf(F, "%d;folgt\n", u->no);
- }
- i = ualias(u);
- if (i>0)
- fprintf(F, "%d;temp\n", i);
- else if (i<0)
- fprintf(F, "%d;alias\n", -i);
- i = get_money(u);
- fprintf(F, "%d;Kampfstatus\n", u->status);
- if(fval(u, UFL_NOAID)) {
- fputs("1;unaided\n", F);
- }
- i = u_geteffstealth(u);
- if (i >= 0)
- fprintf(F, "%d;Tarnung\n", i);
- c = uprivate(u);
- if (c)
- fprintf(F, "\"%s\";privat\n", c);
- c = hp_status(u);
- if (c && *c && (u->faction == f || omniscient(f)))
- fprintf(F, "\"%s\";hp\n", add_translation(c, locale_string(u->faction->locale, c)));
- if (fval(u, UFL_HUNGER) && (u->faction == f))
- fputs("1;hunger\n", F);
- if (is_mage(u)) {
- fprintf(F, "%d;Aura\n", get_spellpoints(u));
- fprintf(F, "%d;Auramax\n", max_spellpoints(u->region,u));
- }
+ a = a_find(u->attribs, &at_follow);
+ if (a) {
+ unit * u = (unit*)a->data.v;
+ if (u) fprintf(F, "%d;folgt\n", u->no);
+ }
+ i = ualias(u);
+ if (i>0)
+ fprintf(F, "%d;temp\n", i);
+ else if (i<0)
+ fprintf(F, "%d;alias\n", -i);
+ i = get_money(u);
+ fprintf(F, "%d;Kampfstatus\n", u->status);
+ if(fval(u, UFL_NOAID)) {
+ fputs("1;unaided\n", F);
+ }
+ i = u_geteffstealth(u);
+ if (i >= 0)
+ fprintf(F, "%d;Tarnung\n", i);
+ c = uprivate(u);
+ if (c)
+ fprintf(F, "\"%s\";privat\n", c);
+ c = hp_status(u);
+ if (c && *c && (u->faction == f || omniscient(f)))
+ fprintf(F, "\"%s\";hp\n", add_translation(c, locale_string(u->faction->locale, c)));
+ if (fval(u, UFL_HUNGER) && (u->faction == f))
+ fputs("1;hunger\n", F);
+ if (is_mage(u)) {
+ fprintf(F, "%d;Aura\n", get_spellpoints(u));
+ fprintf(F, "%d;Auramax\n", max_spellpoints(u->region,u));
+ }
- /* default commands */
- fprintf(F, "COMMANDS\n");
- if (u->lastorder) fprintf(F, "\"%s\"\n", getcommand(u->lastorder));
- for (ord = u->orders; ord; ord = ord->next) {
- if (is_persistent(ord) && ord!=u->lastorder) {
- fprintf(F, "\"%s\"\n", getcommand(ord));
- }
- }
+ /* default commands */
+ fprintf(F, "COMMANDS\n");
+ if (u->lastorder) {
+ cmd = getcommand(u->lastorder);
+ fprintf(F, "\"%s\"\n", cmd);
+ free(cmd);
+ }
+ for (ord = u->orders; ord; ord = ord->next) {
+ if (is_persistent(ord) && ord!=u->lastorder) {
+ cmd = getcommand(ord);
+ fprintf(F, "\"%s\"\n", cmd);
+ free(cmd);
+ }
+ }
- /* talents */
- pr = 0;
+ /* talents */
+ pr = 0;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
- if (sv->level>0) {
+ if (sv->level>0) {
skill_t sk = sv->id;
- int esk = eff_skill(u, sk, r);
- if (!pr) {
- pr = 1;
- fprintf(F, "TALENTE\n");
- }
- fprintf(F, "%d %d;%s\n", u->number*level_days(sv->level), esk,
- add_translation(skillname(sk, NULL), skillname(sk, f->locale)));
- }
- }
- /* spells */
- if (is_mage(u)) {
- sc_mage * mage = get_mage(u);
- spell_ptr *spt = mage->spellptr;
- if (spt) {
- spell *sp;
- int i;
- int t = effskill(u, SK_MAGIC);
- fprintf(F, "SPRUECHE\n");
- for (;spt; spt = spt->next) {
- sp = find_spellbyid(spt->spellid);
- if (sp) {
- const char * name = sp->sname;
- if (sp->level > t) continue;
- if (sp->info==NULL) {
- name = add_translation(mkname("spell", name), spell_name(sp, f->locale));
- }
- fprintf(F, "\"%s\"\n", name);
- }
- }
- for (i=0;i!=MAXCOMBATSPELLS;++i) {
- sp = find_spellbyid(mage->combatspell[i]);
- if (sp) {
- const char * name = sp->sname;
- if (sp->info==NULL) {
- name = add_translation(mkname("spell", name), spell_name(sp, f->locale));
- }
- fprintf(F, "KAMPFZAUBER %d\n", i);
- fprintf(F, "\"%s\";name\n", name);
- fprintf(F, "%d;level\n", mage->combatspelllevel[i]);
- }
- }
- }
- }
- }
+ int esk = eff_skill(u, sk, r);
+ if (!pr) {
+ pr = 1;
+ fprintf(F, "TALENTE\n");
+ }
+ fprintf(F, "%d %d;%s\n", u->number*level_days(sv->level), esk,
+ add_translation(skillname(sk, NULL), skillname(sk, f->locale)));
+ }
+ }
+ /* spells */
+ if (is_mage(u)) {
+ sc_mage * mage = get_mage(u);
+ spell_ptr *spt = mage->spellptr;
+ if (spt) {
+ spell *sp;
+ int i;
+ int t = effskill(u, SK_MAGIC);
+ fprintf(F, "SPRUECHE\n");
+ for (;spt; spt = spt->next) {
+ sp = find_spellbyid(spt->spellid);
+ if (sp) {
+ const char * name = sp->sname;
+ if (sp->level > t) continue;
+ if (sp->info==NULL) {
+ name = add_translation(mkname("spell", name), spell_name(sp, f->locale));
+ }
+ fprintf(F, "\"%s\"\n", name);
+ }
+ }
+ for (i=0;i!=MAXCOMBATSPELLS;++i) {
+ sp = find_spellbyid(mage->combatspell[i]);
+ if (sp) {
+ const char * name = sp->sname;
+ if (sp->info==NULL) {
+ name = add_translation(mkname("spell", name), spell_name(sp, f->locale));
+ }
+ fprintf(F, "KAMPFZAUBER %d\n", i);
+ fprintf(F, "\"%s\";name\n", name);
+ fprintf(F, "%d;level\n", mage->combatspelllevel[i]);
+ }
+ }
+ }
+ }
+ }
/* items */
pr = 0;
if (f == u->faction || omniscient(u->faction)) {
diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c
index 756aa7694..d45937d80 100644
--- a/src/common/gamecode/monster.c
+++ b/src/common/gamecode/monster.c
@@ -740,72 +740,6 @@ random_growl(void)
extern attrib_type at_direction;
-static void
-make_ponnuki(void)
-{
- int ponn = atoi36("ponn");
- unit * u = ufindhash(ponn);
- region * r = findregion(-67,-5);
- if (u || !r) return;
- u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_ILLUSION]);
- u->irace = new_race[RC_GOBLIN];
- set_string(&u->name, "Ponnuki");
- set_string(&u->display, "Go, Ponnuki, Go.");
- uunhash(u);
- u->no = ponn;
- uhash(u);
-
- /* 'andere' ponnukis mit eigener nummer */
- ponn = atoi36("255x");
- do {
- u = ufindhash(ponn);
- if (!u) break;
- uunhash(u);
- u->no = newunitid();
- uhash(u);
- } while (u);
-}
-
-static void ponnuki(unit * u)
-{
- const char* joke[] = {
- "Ein Bummerang ist, wenn man ihn wegwirft und er kommt nicht wieder, dann war's keiner.",
-
- "Ein Riese und ein Zwerg sitzen an der Bar und trinken Bier. Der Zwerg spuckt - tftftf - dem Riesen ins Bier.\n"
- "Riese: Hör auf, oder ich reiß Dir ein Ohr ab!\n"
- "Zwerg: Mir egal, bei uns Zwergen wachsen die Ohren nach! - tftftf\n"
- "Riese: Wenn Du nicht sofort aufhörst, reiße ich Dir ein Bein aus!\n"
- "Zwerg: Na und, bei uns Zwergen wachsen Beine nach - tftftf\n"
- "Riese: Jetzt reichts aber wirklich! Schluß, oder ich reiße Dir den\n"
- "Schniedel aus.\n"
- "Zwerg: Probier's doch, wir Zwerge haben gar keinen Schniedel - tftftf\n"
- "Riese (verblüfft): So, und wie pinkelt Ihr dann???\n"
- "Zwerg: tftftf",
-
- "Ein Ingenieur und ein Mathematiker sitzen zusammen in einem Vortrag über Kulza-Klein Theorie, die sich mit\n"
- "11, 12 und sogar höheren Dimensionen beschäftig. Der Mathematiker geniesst die Vorlesung, während der\n"
- "Ingenieur immer mehr verwirrt aussieht. Als der Vortrag zu ende ist, hat der Ingenieur schreckliche\n"
- "Kopfschmerzen davon.\n"
- "\n"
- "Ingenieur: Wie kannst du nur diesen schrecklichen, abgehobenen Vortrag verstehen?\n"
- "Mathematiker: Ich stelle mir das ganze einfach vor.\n"
- "Ingenieur: Wie kannst du dir einen 11-dimensionalen Raum vorstellen???\n"
- "Mathematiker: Nun, ich stelle mir einen n-dimensionalen Raum vor und lasse dann n gegen 11 gehen..",
-
- "Merke: Mit Schwabenwitzen soll man ganz sparsam sein.",
-
- "F: Was bekommt man, wenn man Katzen und Elfen kreuzt?\nA: Elfen ohne Rheuma.",
-
- "F: Was bekommt man, wenn man Insekten und Katzen kreuzt?\nA: Tiger, die Crisan benutzen.",
-
- NULL };
- int jokes = 0;
-
- while(joke[jokes]) jokes++;
- if (jokes) addmessage(u->region, 0, joke[rand() % jokes], MSG_MESSAGE, ML_IMPORTANT);
-
-}
-
static void
learn_monster(unit *u)
{
@@ -981,13 +915,10 @@ void
plan_monsters(void)
{
region *r;
- faction *f;
unit *u;
attrib *ta;
- u = findunitg(atoi36("ponn"), NULL);
- if (!u) make_ponnuki();
- f = findfaction(MONSTER_FACTION);
+ faction *f = findfaction(MONSTER_FACTION);
if (!f)
return;
@@ -1065,10 +996,6 @@ plan_monsters(void)
/* Ab hier noch nicht generalisierte Spezialbehandlungen. */
switch (old_race(u->race)) {
- case RC_ILLUSION:
- if (u->no==atoi36("ponn")) ponnuki(u);
- break;
- /* Alp */
case RC_ALP:
monster_seeks_target(r, u);
break;
diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c
index 0bc5c2883..01ac07d9e 100644
--- a/src/common/gamecode/randenc.c
+++ b/src/common/gamecode/randenc.c
@@ -960,7 +960,7 @@ move_iceberg(region *r)
}
}
-void
+static void
move_icebergs(void)
{
region *r;
@@ -987,6 +987,7 @@ create_icebergs(void)
region *rc;
unit *u;
+ freset(r, RF_DH);
for (dir=0; dir < MAXDIRECTIONS; dir++) {
rc = rconnect(r, dir);
if (rc && rterrain(rc) == T_OCEAN) {
@@ -1009,7 +1010,7 @@ create_icebergs(void)
}
}
-void
+static void
godcurse(void)
{
region *r;
@@ -1076,6 +1077,88 @@ check_split(void)
}
}
+/** handles the "orcish" curse that makes units grow like old orks
+ * This would probably be better handled in an age-function for the curse,
+ * but it's now being called by randomevents()
+ */
+static void
+orc_growth(void)
+{
+ region * r;
+ for (r = regions; r; r = r->next) {
+ unit *u;
+ for (u = r->units; u; u = u->next) {
+ curse *c = get_curse(u->attribs, ct_find("orcish"));
+ if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) {
+ int n;
+ int increase = 0;
+ int num = get_cursedmen(u, c);
+ int prob = curse_geteffect(c);
+
+ for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
+ if (rand() % 100 < prob) {
+ ++increase;
+ }
+ }
+ if (increase) {
+ set_number(u, u->number + increase);
+
+ u->hp += unit_max_hp(u) * increase;
+ ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
+ "unit amount race", u, increase, u->race));
+ }
+ }
+ }
+ }
+}
+
+/** Talente von Dämonen verschieben sich.
+ */
+static void
+demon_skillchanges(void)
+{
+ region * r;
+
+ for (r = regions; r; r = r->next) {
+ unit * u;
+ for (u = r->units; u; u = u->next) {
+ if (u->race == new_race[RC_DAEMON]) {
+ skill * sv = u->skills;
+ while (sv!=u->skills+u->skill_size) {
+ if (sv->level>0 && rand() % 100 < 25) {
+ int weeks = 1+rand()%3;
+ if (rand() % 100 < 40) {
+ reduce_skill(u, sv, weeks);
+ } else {
+ while (weeks--) learn_skill(u, sv->id, 1.0);
+ }
+ if (sv->old>sv->level) {
+ log_printf("%s dropped from %u to %u:%u in %s\n",
+ unitname(u), sv->old, sv->level,
+ sv->weeks, skillname(sv->id, NULL));
+ }
+ }
+ ++sv;
+ }
+ }
+ }
+ }
+}
+
+/** Eisberge entstehen und bewegen sich.
+ * Einheiten die im Wasser landen, ertrinken.
+ */
+static void
+icebergs(void)
+{
+ region * r;
+ create_icebergs();
+ move_icebergs();
+ for (r=regions; r; r=r->next) {
+ drown(r);
+ }
+}
+
void
randomevents(void)
{
@@ -1084,67 +1167,10 @@ randomevents(void)
building *b, *b2;
unit *u;
- /* Eiseberge */
- for (r=regions; r; r=r->next) freset(r, RF_DH);
- create_icebergs();
- move_icebergs();
-
- godcurse();
-
- for (r=regions; r; r=r->next) {
- drown(r);
- }
-
- for (r = regions; r; r = r->next) {
- for (u = r->units; u; u = u->next) {
- curse *c = get_curse(u->attribs, ct_find("orcish"));
- if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) {
- int n;
- int increase = 0;
- int num = get_cursedmen(u, c);
- int prob = curse_geteffect(c);
-
- for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
- if (rand() % 100 < prob) {
- ++increase;
- }
- }
- if (increase) {
- set_number(u, u->number + increase);
-
- u->hp += unit_max_hp(u) * increase;
- ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
- "unit amount race", u, increase, u->race));
- }
- }
- }
- }
-
- /* Talentverschiebung: Talente von Dämonen verschieben sich */
-
- for (r = regions; r; r = r->next) {
- for (u = r->units; u; u = u->next) {
- if (u->race == new_race[RC_DAEMON]) {
- skill * sv = u->skills;
- while (sv!=u->skills+u->skill_size) {
- if (sv->level>0 && rand() % 100 < 25) {
- int weeks = 1+rand()%3;
- if (rand() % 100 < 40) {
- reduce_skill(u, sv, weeks);
- } else {
- while (weeks--) learn_skill(u, sv->id, 1.0);
- }
- if (sv->old>sv->level) {
- log_printf("%s dropped from %u to %u:%u in %s\n",
- unitname(u), sv->old, sv->level,
- sv->weeks, skillname(sv->id, NULL));
- }
- }
- ++sv;
- }
- }
- }
- }
+ icebergs();
+ godcurse();
+ orc_growth();
+ demon_skillchanges();
#if RACE_ADJUSTMENTS == 0
/* Orks vermehren sich */
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index 197ecaed2..3716a8a54 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -1218,7 +1218,10 @@ init_tokens_str(const char * initstr)
void
init_tokens(const struct order * ord)
{
- init_tokens_str(getcommand(ord));
+ static char * cmd = NULL;
+ if (cmd!=NULL) free(cmd);
+ cmd = getcommand(ord);
+ init_tokens_str(cmd);
}
void
diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h
index 8e9c337d8..a99189669 100644
--- a/src/common/kernel/eressea.h
+++ b/src/common/kernel/eressea.h
@@ -378,7 +378,7 @@ typedef struct ursprung {
/* ----------------- Befehle ----------------------------------- */
-typedef int keyword_t;
+typedef unsigned char keyword_t;
enum {
K_KOMMENTAR,
K_BANNER,
diff --git a/src/common/kernel/kernel.vcproj b/src/common/kernel/kernel.vcproj
index e42c1bd96..b9ca32427 100644
--- a/src/common/kernel/kernel.vcproj
+++ b/src/common/kernel/kernel.vcproj
@@ -233,9 +233,6 @@
-
-
@@ -354,9 +351,6 @@
-
-
diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c
index 76704bfcc..a4a917d23 100644
--- a/src/common/kernel/magic.c
+++ b/src/common/kernel/magic.c
@@ -1859,7 +1859,7 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
par = calloc(1, sizeof(spellparameter));
/* Temporären Puffer initialisieren */
- tbuf = strdup(getcommand(ord));
+ tbuf = getcommand(ord);
/* Tokens zählen */
token = strtok(tbuf, " ");
@@ -1867,6 +1867,7 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
par->length++;
token = strtok(NULL, " ");
}
+ free(tbuf);
/* length sollte nun nur noch die Anzahl der für den Zauber relevanten
* Elemente enthalten */
par->length -= skip; /* Anzahl der Elemente ('temp 123' sind zwei!) */
@@ -1877,7 +1878,6 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
/* Fehler: Ziel vergessen */
cmistake(u, ord, 203, MSG_MAGIC);
/* Aufräumen */
- free(tbuf);
free(par);
return 0;
}
@@ -1886,7 +1886,7 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
par->param = calloc(par->length, sizeof(spllprm *));
/* Tokens zuweisen */
- strcpy(tbuf, getcommand(ord));
+ tbuf = getcommand(ord);
token = strtok (tbuf, " ");
while(token && syntax[c] != 0) {
if (i > skip) {
@@ -2216,6 +2216,7 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
i++;
token = strtok(NULL, " ");
}
+ free(tbuf);
/* im Endeffekt waren es nur l parameter */
par->length = l;
@@ -2226,14 +2227,10 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, struct order *
/* Syntax Error. */
cmistake(u, ord, 209, MSG_MAGIC);
/* Aufräumen */
- free(tbuf);
free_spellparameter(par);
return 0;
}
- /* Aufräumen */
- free(tbuf);
-
return par;
}
diff --git a/src/common/kernel/order.c b/src/common/kernel/order.c
index 56d34bd9a..48f61527c 100644
--- a/src/common/kernel/order.c
+++ b/src/common/kernel/order.c
@@ -21,6 +21,11 @@
#include
#include
+static const struct locale * locale_array[16];
+static int nlocales = 0;
+
+#undef SHORT_STRINGS
+
keyword_t
get_keyword(const order * ord)
{
@@ -30,17 +35,35 @@ get_keyword(const order * ord)
return ord->_keyword;
}
-const char *
+char *
getcommand(const order * ord)
{
- return ord->_str;
+ char sbuffer[DISPLAYSIZE*2];
+ char * str = sbuffer;
+
+ assert(ord->_lindex_persistent) *str++ = '@';
+#ifdef SHORT_STRINGS
+ if (ord->_keyword!=NOKEYWORD) {
+ const struct locale * lang = locale_array[ord->_lindex];
+
+ strcpy(str, LOC(lang, keywords[ord->_keyword]));
+ str += strlen(str);
+ if (ord->_str) {
+ *str++ = ' ';
+ *str = 0;
+ }
+ }
+#endif
+ strcpy(str, ord->_str);
+ return strdup(sbuffer);
}
void
free_order(order * ord)
{
if (ord!=NULL && --ord->_refcount==0) {
- free(ord->_str);
+ if (ord->_str!=NULL) free(ord->_str);
free(ord);
}
}
@@ -73,37 +96,69 @@ free_orders(order ** olist)
order *
parse_order(const char * s, const struct locale * lang)
{
- while (isspace(*s)) ++s;
+ while (isspace(*(unsigned char*)s)) ++s;
if (*s==0) return NULL;
else {
- order * ord = (order*)malloc(sizeof(order));
- ord->_str = strdup(s);
- ord->_keyword = findkeyword(parse_token(&s), lang);
- ord->_refcount = 1;
- ord->next = NULL;
- return ord;
+ const char * sptr;
+ order * ord = (order*)malloc(sizeof(order));
+ int i;
+
+ for (i=0;i!=nlocales;++i) {
+ if (locale_array[i]==lang) break;
+ }
+ if (i==nlocales) locale_array[nlocales++] = lang;
+ ord->_lindex = (unsigned char)i;
+ ord->_str = NULL;
+ ord->_persistent = 0;
+ ord->_refcount = 1;
+ ord->next = NULL;
+
+#ifdef AT_PERSISTENT
+ if (*s=='@') {
+ ord->_persistent = 1;
+#ifdef SHORT_STRINGS
+ ++s;
+#endif
+ }
+#endif
+ sptr = s;
+ ord->_keyword = findkeyword(parse_token(&sptr), lang);
+#ifdef SHORT_STRINGS
+ if (ord->_keyword==NOKEYWORD) {
+ ord->_str = strdup(s);
+ } else {
+ while (isspace(*(unsigned char*)sptr)) ++sptr;
+ if (*sptr) {
+ ord->_str = strdup(sptr);
+ }
+ }
+#else
+ ord->_str = strdup(s);
+#endif
+ return ord;
}
}
boolean
is_persistent(const order * cmd)
{
-#ifdef AT_PERSISTENT
- if (cmd->_str[0] == '@') return true;
-#endif /* Nur kurze Befehle! */
switch (cmd->_keyword) {
- case K_KOMMENTAR:
- case K_LIEFERE:
- return true;
- break;
+ case NOKEYWORD:
+ return false;
+ case K_KOMMENTAR:
+ case K_LIEFERE:
+ return true;
}
+#ifdef AT_PERSISTENT
+ if (cmd->_persistent) return true;
+#endif /* Nur kurze Befehle! */
return false;
}
char *
-write_order(const order * cmd, const struct locale * lang, char * buffer, size_t size)
+write_order(const order * ord, const struct locale * lang, char * buffer, size_t size)
{
- if (cmd==0) {
+ if (ord==0 || ord->_keyword==NOKEYWORD) {
buffer[0]=0;
} else {
#ifndef NDEBUG
diff --git a/src/common/kernel/order.h b/src/common/kernel/order.h
index 8aca84dc9..4f5194b4e 100644
--- a/src/common/kernel/order.h
+++ b/src/common/kernel/order.h
@@ -30,7 +30,9 @@ typedef struct order {
/* do not access this data: */
char * _str;
keyword_t _keyword;
- int _refcount;
+ int _lindex : 7;
+ int _persistent : 1;
+ int _refcount : 16;
} order;
/* constructor */
@@ -44,7 +46,7 @@ extern void free_orders(struct order ** olist);
/* access functions for orders */
extern keyword_t get_keyword(const struct order * ord);
extern void set_order(struct order ** destp, struct order * src);
-extern const char * getcommand(const struct order * ord);
+extern char * getcommand(const struct order * ord);
extern boolean is_persistent(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/orders.c b/src/common/kernel/orders.c
deleted file mode 100644
index f81da4cce..000000000
--- a/src/common/kernel/orders.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* vi: set ts=2:
- *
- *
- * Eressea PB(E)M host Copyright (C) 1998-2003
- * Christian Schlittchen (corwin@amber.kn-bremen.de)
- * Katja Zedel (katze@felidae.kn-bremen.de)
- * Henning Peters (faroul@beyond.kn-bremen.de)
- * Enno Rehling (enno@eressea-pbem.de)
- * Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
- *
- * This program may not be used, modified or distributed without
- * prior permission by the authors of Eressea.
- */
-
-#include
-#include "eressea.h"
-#include "orders.h"
-
diff --git a/src/common/kernel/orders.h b/src/common/kernel/orders.h
deleted file mode 100644
index ae2eba9d3..000000000
--- a/src/common/kernel/orders.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* vi: set ts=2:
- *
- *
- * Eressea PB(E)M host Copyright (C) 1998-2003
- * Christian Schlittchen (corwin@amber.kn-bremen.de)
- * Katja Zedel (katze@felidae.kn-bremen.de)
- * Henning Peters (faroul@beyond.kn-bremen.de)
- * Enno Rehling (enno@eressea-pbem.de)
- * Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
- *
- * This program may not be used, modified or distributed without
- * prior permission by the authors of Eressea.
- */
-
-#ifndef ORDERS_H
-#define ORDERS_H
-
-#endif
diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c
index 417ddd3fd..c10664e72 100644
--- a/src/common/kernel/reports.c
+++ b/src/common/kernel/reports.c
@@ -407,9 +407,11 @@ bufunit(const faction * f, const unit * u, int indent, int mode)
}
}
if (!isbattle && u->lastorder) {
+ char * cmd = getcommand(u->lastorder);
scat(", \"");
- scat(getcommand(u->lastorder));
+ scat(cmd);
scat("\"");
+ free(cmd);
}
}
i = 0;
diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c
index 75c3c52ff..bba8a2ccb 100644
--- a/src/common/kernel/save.c
+++ b/src/common/kernel/save.c
@@ -1095,12 +1095,13 @@ readunit(FILE * F)
free_orders(&u->orders);
rs(F, buf);
while(*buf != 0) {
- addlist(&u->orders, parse_order(buf, u->faction->locale));
+ order * ord = parse_order(buf, u->faction->locale);
+ if (ord!=NULL) addlist(&u->orders, ord);
rs(F, buf);
}
- rs(F, buf);
- u->lastorder = parse_order(buf, u->faction->locale);
- set_order(&u->thisorder, NULL);
+ rs(F, buf);
+ u->lastorder = parse_order(buf, u->faction->locale);
+ set_order(&u->thisorder, NULL);
assert(u->number >= 0);
assert(u->race);
@@ -1200,7 +1201,8 @@ writeunit(FILE * F, const unit * u)
wi(F, u->flags & UFL_SAVEMASK);
wnl(F);
for (ord = u->orders; ord; ord=ord->next) {
- if (is_persistent(ord)) writeorder(ord, u->faction->locale, F);
+ if (is_persistent(ord) && get_keyword(ord)!=NOKEYWORD) {
+ writeorder(ord, u->faction->locale, F);
}
ws(F, ""); /* Abschluß der persistenten Befehle */
writeorder(u->lastorder, u->faction->locale, F);
diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c
index a9656e2f4..a63242c0f 100644
--- a/src/common/kernel/unit.c
+++ b/src/common/kernel/unit.c
@@ -807,15 +807,15 @@ u_setfaction(unit * u, faction * f)
{
int cnt = u->number;
if (u->faction==f) return;
- if (u->faction) {
- set_number(u, 0);
- --u->faction->no_units;
- join_group(u, NULL);
- free_orders(&u->orders);
- set_order(&u->thisorder, NULL);
- set_order(&u->lastorder, NULL);
- }
- if (u->prevF) u->prevF->nextF = u->nextF;
+ if (u->faction) {
+ set_number(u, 0);
+ --u->faction->no_units;
+ join_group(u, NULL);
+ free_orders(&u->orders);
+ set_order(&u->thisorder, NULL);
+ set_order(&u->lastorder, NULL);
+ }
+ if (u->prevF) u->prevF->nextF = u->nextF;
else if (u->faction) {
assert(u->faction->units==u);
u->faction->units = u->nextF;
diff --git a/src/common/util/command.c b/src/common/util/command.c
index 1aedd3cab..16fb6dae0 100644
--- a/src/common/util/command.c
+++ b/src/common/util/command.c
@@ -87,10 +87,12 @@ do_command_i(const struct tnode * keys, void * u, const char * str, struct order
}
}
-extern const char * getcommand(struct order * ord);
+extern char * getcommand(struct order * ord);
void
do_command(const struct tnode * keys, void * u, struct order * ord)
{
- do_command_i(keys, u, getcommand(ord), ord);
+ char * cmd = getcommand(ord);
+ do_command_i(keys, u, cmd, ord);
+ free(cmd);
}
diff --git a/src/eressea/lua/alliance.cpp b/src/eressea/lua/alliance.cpp
index 7b715ac74..c792e36f3 100644
--- a/src/eressea/lua/alliance.cpp
+++ b/src/eressea/lua/alliance.cpp
@@ -22,10 +22,10 @@ public:
static faction * value(faction_list * node) { return node->data; }
};
-static eressea::list
+static eressea::list
alliance_factions(const alliance& al)
{
- return eressea::list(al.members);
+ return eressea::list(al.members);
}
static alliance *
@@ -34,9 +34,9 @@ add_alliance(int id, const char * name)
return makealliance(id, name);
}
-static eressea::list
+static eressea::list
get_alliances(void) {
- return eressea::list(alliances);
+ return eressea::list(alliances);
}
void
diff --git a/src/eressea/lua/eressea.cpp b/src/eressea/lua/eressea.cpp
index f27ea4b3b..7d0d0838d 100644
--- a/src/eressea/lua/eressea.cpp
+++ b/src/eressea/lua/eressea.cpp
@@ -146,6 +146,13 @@ race_setscript(const char * rcname, const functor& f)
}
}
+#ifdef LUABIND_NO_EXCEPTIONS
+static void
+error_callback(lua_State * L)
+{
+}
+#endif
+
void
bind_eressea(lua_State * L)
{
@@ -177,4 +184,7 @@ bind_eressea(lua_State * L)
/* planes not really implemented */
def("get_plane_id", &find_plane_id)
];
+#ifdef LUABIND_NO_EXCEPTIONS
+ luabind::set_error_callback(error_callback);
+#endif
}
diff --git a/src/eressea/lua/faction.cpp b/src/eressea/lua/faction.cpp
index f3c86c4b2..993a4a854 100644
--- a/src/eressea/lua/faction.cpp
+++ b/src/eressea/lua/faction.cpp
@@ -32,9 +32,9 @@ add_faction(const char * email, const char * racename, const char * lang)
return f;
}
-static eressea::list
+static eressea::list
get_factions(void) {
- return eressea::list(factions);
+ return eressea::list(factions);
}
class factionunit {
@@ -43,10 +43,10 @@ public:
static unit * value(unit * node) { return node; }
};
-static eressea::list
+static eressea::list
faction_units(const faction& f)
{
- return eressea::list(f.units);
+ return eressea::list(f.units);
}
#ifdef ALLIANCES
diff --git a/src/eressea/lua/list.h b/src/eressea/lua/list.h
index 39c61a457..1951d8330 100644
--- a/src/eressea/lua/list.h
+++ b/src/eressea/lua/list.h
@@ -6,8 +6,8 @@ namespace eressea {
template
class listnode {
public:
- static N * next(N * node) { return node->next; }
- static T * value(N * node) { return node; }
+ static N next(N& node) { return node->next; }
+ static T value(N& node) { return node; }
};
template >
@@ -15,8 +15,8 @@ namespace eressea {
public:
class iterator {
public:
- iterator(N * index) : m_index(index) {}
- T * operator*() { return nodetype::value(m_index); }
+ iterator(const N& index) : m_index(index) {}
+ T operator*() { return nodetype::value(m_index); }
bool operator==(const iterator& iter) {
return iter.m_index==m_index;
}
@@ -25,15 +25,15 @@ namespace eressea {
return *this;
}
private:
- N * m_index;
+ N m_index;
};
typedef iterator const_iterator;
- list(N * clist) : m_clist(clist) {}
+ list(const N& clist) : m_clist(clist) {}
iterator begin() const { return iterator(m_clist); }
iterator end() const { return iterator(NULL); }
public:
- N * m_clist;
+ N m_clist;
};
};
diff --git a/src/eressea/lua/region.cpp b/src/eressea/lua/region.cpp
index 419d7daba..5c7833f5b 100644
--- a/src/eressea/lua/region.cpp
+++ b/src/eressea/lua/region.cpp
@@ -17,24 +17,24 @@
#include
using namespace luabind;
-static eressea::list
+static eressea::list
get_regions(void) {
- return eressea::list(regions);
+ return eressea::list(regions);
}
-static eressea::list
+static eressea::list
region_units(const region& r) {
- return eressea::list(r.units);
+ return eressea::list(r.units);
}
-static eressea::list
+static eressea::list
region_buildings(const region& r) {
- return eressea::list(r.buildings);
+ return eressea::list(r.buildings);
}
-static eressea::list
+static eressea::list
region_ships(const region& r) {
- return eressea::list(r.ships);
+ return eressea::list(r.ships);
}
static void
diff --git a/src/eressea/lua/unit.cpp b/src/eressea/lua/unit.cpp
index 5641b3808..e9cb941ee 100644
--- a/src/eressea/lua/unit.cpp
+++ b/src/eressea/lua/unit.cpp
@@ -26,6 +26,7 @@
#include
#include
+#include
using namespace luabind;
class bind_spell_ptr {
@@ -34,12 +35,12 @@ public:
static spell * value(spell_ptr * node) { return find_spellbyid(node->spellid); }
};
-static eressea::list
+static eressea::list
unit_spells(const unit& u) {
sc_mage * mage = get_mage(&u);
- if (mage==NULL) return eressea::list(NULL);
+ if (mage==NULL) return eressea::list(NULL);
spell_ptr * splist = mage->spellptr;
- return eressea::list(splist);
+ return eressea::list(splist);
}
class bind_spell_list {
@@ -48,10 +49,26 @@ public:
static spell * value(spell_list * node) { return node->data; }
};
-static eressea::list
+static eressea::list
unit_familiarspells(const unit& u) {
spell_list * spells = familiarspells(u.race);
- return eressea::list(spells);
+ return eressea::list(spells);
+}
+
+class bind_orders {
+public:
+ static order * next(order * node) { return node->next; }
+ static std::string value(order * node) {
+ char * cmd = getcommand(node);
+ std::string s(cmd);
+ free(cmd);
+ return s;
+ }
+};
+
+static eressea::list
+unit_orders(const unit& u) {
+ return eressea::list(u.orders);
}
static unit *
@@ -211,6 +228,23 @@ unit_getregion(const unit& u)
return u.region;
}
+static int
+unit_getid(const unit& u)
+{
+ return u.no;
+}
+
+static void
+unit_setid(unit& u, int id)
+{
+ unit * nu = findunit(id);
+ if (nu==NULL) {
+ uunhash(&u);
+ u.no = id;
+ uhash(&u);
+ }
+}
+
static const char *
unit_getname(const unit& u)
{
@@ -223,6 +257,18 @@ unit_setname(unit& u, const char * name)
set_string(&u.name, name);
}
+static const char *
+unit_getinfo(const unit& u)
+{
+ return u.display;
+}
+
+static void
+unit_setinfo(unit& u, const char * info)
+{
+ set_string(&u.display, info);
+}
+
static std::ostream&
operator<<(std::ostream& stream, unit& u)
{
@@ -319,15 +365,21 @@ bind_unit(lua_State * L)
def("add_unit", &add_unit),
class_("unit")
- .property("name", &unit_getname, &unit_setname)
.def(tostring(self))
.def(self == unit())
+ .property("name", &unit_getname, &unit_setname)
+ .property("info", &unit_getinfo, &unit_setinfo)
+ .property("id", &unit_getid, &unit_setid)
.def_readonly("faction", &unit::faction)
- .def_readonly("id", &unit::no)
.def_readwrite("hp", &unit::hp)
.def_readwrite("status", &unit::status)
+
+ // orders:
.def("add_order", &unit_addorder)
.def("clear_orders", &unit_clearorders)
+ .property("orders", &unit_orders, return_stl_iterator)
+
+ // items:
.def("get_item", &unit_getitem)
.def("add_item", &unit_additem)
.def("get_skill", &unit_getskill)
diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp
index 9e0c63bae..4386961c6 100644
--- a/src/eressea/server.cpp
+++ b/src/eressea/server.cpp
@@ -142,6 +142,7 @@ static int nowrite = 0;
static boolean g_writemap = false;
static boolean opt_reportonly = false;
static const char * luafile = "default.lua";
+static const char * script_path = NULL;
struct settings global = {
"Eressea", /* gamename */
@@ -272,6 +273,7 @@ lua_init(void)
luaopen_math(luaState);
luaopen_string(luaState);
luaopen_io(luaState);
+ luaopen_table(luaState);
luabind::open(luaState);
bind_eressea(luaState);
bind_spell(luaState);
@@ -590,7 +592,7 @@ read_args(int argc, char **argv, lua_State * luaState)
}
break;
case 'l':
- log_open(argv[++i]);
+ script_path = argv[++i];
break;
case 'w':
g_writemap = true;
@@ -605,6 +607,7 @@ read_args(int argc, char **argv, lua_State * luaState)
/* add some more variables to the lua globals */
setLuaString(luaState, "datapath", datapath());
+ setLuaString(luaState, "scriptpath", script_path);
setLuaString(luaState, "basepath", basepath());
setLuaString(luaState, "reportpath", reportpath());
setLuaString(luaState, "resourcepath", resourcepath());
@@ -663,8 +666,25 @@ main(int argc, char *argv[])
// run the main script
if (luafile==NULL) lua_console(luaState);
- else lua_dofile(luaState, luafile);
-
+ else {
+ try {
+ if (script_path) {
+ sprintf(buf, "%s/%s", script_path, luafile);
+ lua_dofile(luaState, buf);
+ }
+ else lua_dofile(luaState, luafile);
+ }
+ catch (luabind::error& e) {
+ lua_State* L = e.state();
+ const char* error = lua_tostring(L, -1);
+ log_error((error));
+ lua_pop(L, 1);
+ std::terminate();
+ // L will now point to the destructed
+ // lua state and be invalid
+ /* ... */
+ }
+ }
#ifdef CLEANUP_CODE
game_done();
#endif
diff --git a/src/scripts/eressea.lua b/src/scripts/eressea.lua
new file mode 100644
index 000000000..73353403c
--- /dev/null
+++ b/src/scripts/eressea.lua
@@ -0,0 +1,78 @@
+function write_emails()
+ local locales = { "de", "en" }
+ local files = {}
+ local key
+ for key in locales do
+ local locale = locales[key]
+ files[locale] = io.open(basepath .. "/emails." .. locale, "w")
+ end
+
+ local faction
+ for faction in factions() do
+ -- print(faction.id .. " - " .. faction.locale)
+ files[faction.locale]:write(faction.email .. "\n")
+ end
+
+ for key in files do
+ files[key]:close()
+ end
+end
+
+function process(orders)
+ file = "" .. get_turn()
+ if read_game(file)~=0 then
+ print("could not read game")
+ return -1
+ end
+
+ -- initialize starting equipment for new players
+ -- probably not necessary, since mapper sets new players, not server
+ add_equipment("conquesttoken", 1);
+ add_equipment("wood", 30);
+ add_equipment("stone", 30);
+ add_equipment("money", 2000 + get_turn() * 10);
+
+ -- initialize other scripts
+ local magrathea = get_region(-67, -5)
+ if magrathea~=nil and init_ponnuki~=nil then
+ init_ponnuki(magrathea)
+ return
+ end
+
+ -- run the turn:
+ read_orders(orders)
+ plan_monsters()
+ process_orders()
+
+ write_passwords()
+ write_reports()
+
+ write_emails()
+
+ file = "" .. get_turn()
+ if write_game(file)~=0 then
+ print("could not write game")
+ return -1
+ end
+end
+
+
+--
+-- main body of script
+--
+
+scripts= { "ponnuki.lua" }
+
+-- orderfile: contains the name of the orders.
+if orderfile==nil then
+ print "you must specify an orderfile"
+else
+ for index in scripts do
+ local script = scriptpath .. scripts[index]
+ if pcall(dofile, script)==0 then
+ print("Could not load " .. script)
+ end
+ end
+ process(orderfile)
+end
+
diff --git a/src/scripts/ponnuki.lua b/src/scripts/ponnuki.lua
new file mode 100644
index 000000000..5a47e15f2
--- /dev/null
+++ b/src/scripts/ponnuki.lua
@@ -0,0 +1,34 @@
+function ponnuki_brain(u)
+ jokes = {
+ "Ein Bummerang ist, wenn man ihn wegwirft und er kommt nicht wieder, dann war's keiner.",
+
+ "Merke: Mit Schwabenwitzen soll man ganz sparsam sein.",
+
+ "Was bekommt man, wenn man Katzen und Elfen kreuzt? Elfen ohne Rheuma.",
+
+ "Was bekommt man, wenn man Insekten und Katzen kreuzt? Tiger, die Crisan benutzen."
+ }
+ local i = math.random(table.getn(jokes))
+ u.region:add_notice(jokes[i])
+ local d = math.random(6)
+ r = u.region:next(d-1)
+ u:clear_orders()
+ directions = { "NW", "NO", "O", "SO", "SW", "W" }
+ u:add_order("NACH " .. directions[d])
+end
+
+function init_ponnuki(home)
+ local f = get_faction(0)
+ local u = get_unit(atoi36("ponn"))
+ if u == nil then
+ u = add_unit(f, home)
+ u.id = atoi36("ponn")
+ u.name = "Ponnuki"
+ u.info = "Go, Ponnuki, Go!"
+ u.race = "illusion"
+ u:set_racename("Ritter von Go")
+ end
+ if u.faction==f then
+ u:set_brain(ponnuki_brain)
+ end
+end
diff --git a/src/scripts/samples.lua b/src/scripts/samples.lua
index 493a87c71..839bb5814 100644
--- a/src/scripts/samples.lua
+++ b/src/scripts/samples.lua
@@ -130,12 +130,26 @@ function test_write()
end
function move_north(u)
+ for order in u.orders do
+ print(order)
+ end
u:clear_orders()
u:add_order("NACH NORDEN")
end
function test_monsters()
read_game("23")
+
+ -- magrathea = get_region(-67, -5)
+ local magrathea = get_region(0, 0)
+ if magrathea ~= nil then
+ if pcall(dofile, scriptpath .. "/ponnuki.lua") then
+ init_ponnuki(magrathea)
+ else
+ print("could not open ponnuki")
+ end
+ end
+
set_brain("braineater", move_north)
plan_monsters()
process_orders()