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()