diff --git a/src/eressea.c b/src/eressea.c index 4900693a3..f62c601a6 100755 --- a/src/eressea.c +++ b/src/eressea.c @@ -31,51 +31,51 @@ void game_done(void) { #ifdef CLEANUP_CODE - /* Diese Routine enfernt allen allokierten Speicher wieder. Das ist nur - * zum Debugging interessant, wenn man Leak Detection hat, und nach - * nicht freigegebenem Speicher sucht, der nicht bis zum Ende benötigt - * wird (temporäre Hilsstrukturen) */ + /* Diese Routine enfernt allen allokierten Speicher wieder. Das ist nur + * zum Debugging interessant, wenn man Leak Detection hat, und nach + * nicht freigegebenem Speicher sucht, der nicht bis zum Ende benötigt + * wird (temporäre Hilsstrukturen) */ - free_game(); + free_game(); - creport_cleanup(); + creport_cleanup(); #ifdef REPORT_FORMAT_NR - report_cleanup(); + report_cleanup(); #endif - calendar_cleanup(); + calendar_cleanup(); #endif - kernel_done(); + kernel_done(); } void game_init(void) { kernel_init(); - register_triggers(); - register_xmas(); + register_triggers(); + register_xmas(); - register_nr(); - register_cr(); + register_nr(); + register_cr(); - register_names(); - register_resources(); - register_buildings(); - register_itemfunctions(); + register_names(); + register_resources(); + register_buildings(); + register_itemfunctions(); #if DUNGEON_MODULE - register_dungeon(); + register_dungeon(); #endif #if MUSEUM_MODULE - register_museum(); + register_museum(); #endif #if ARENA_MODULE - register_arena(); + register_arena(); #endif - register_wormholes(); + register_wormholes(); - register_itemtypes(); + register_itemtypes(); #ifdef USE_LIBXML2 - register_xmlreader(); + register_xmlreader(); #endif - register_attributes(); - register_gmcmd(); + register_attributes(); + register_gmcmd(); } diff --git a/src/laws.c b/src/laws.c index 98b8fc2d0..2ba980337 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -116,312 +116,316 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. static int RemoveNMRNewbie(void) { - static int value = -1; - static int gamecookie = -1; + static int value = -1; + static int gamecookie = -1; - if (value < 0 || gamecookie != global.cookie) { - value = get_param_int(global.parameters, "nmr.removenewbie", 0); - gamecookie = global.cookie; - } - return value; + if (value < 0 || gamecookie != global.cookie) { + value = get_param_int(global.parameters, "nmr.removenewbie", 0); + gamecookie = global.cookie; + } + return value; } static void checkorders(void) { - faction *f; + faction *f; - log_info(" - Warne spaete Spieler..."); - for (f = factions; f; f = f->next) - if (!is_monsters(f) && turn - f->lastorders == NMRTimeout() - 1) - ADDMSG(&f->msgs, msg_message("turnreminder", "")); + log_info(" - Warne spaete Spieler..."); + for (f = factions; f; f = f->next) + if (!is_monsters(f) && turn - f->lastorders == NMRTimeout() - 1) + ADDMSG(&f->msgs, msg_message("turnreminder", "")); } static bool help_money(const unit * u) { - if (u_race(u)->ec_flags & GIVEITEM) - return true; - return false; + if (u_race(u)->ec_flags & GIVEITEM) + return true; + return false; } static void help_feed(unit * donor, unit * u, int *need_p) { - int need = *need_p; - int give = get_money(donor) - lifestyle(donor); - give = _min(need, give); + int need = *need_p; + int give = get_money(donor) - lifestyle(donor); + give = _min(need, give); - if (give > 0) { - change_money(donor, -give); - change_money(u, give); - need -= give; - add_spende(donor->faction, u->faction, give, donor->region); - } - *need_p = need; + if (give > 0) { + change_money(donor, -give); + change_money(u, give); + need -= give; + add_spende(donor->faction, u->faction, give, donor->region); + } + *need_p = need; } enum { - FOOD_FROM_PEASANTS = 1, - FOOD_FROM_OWNER = 2, - FOOD_IS_FREE = 4 + FOOD_FROM_PEASANTS = 1, + FOOD_FROM_OWNER = 2, + FOOD_IS_FREE = 4 }; void get_food(region * r) { - plane *pl = rplane(r); - unit *u; - int peasantfood = rpeasants(r) * 10; - static int food_rules = -1; - static int gamecookie = -1; + plane *pl = rplane(r); + unit *u; + int peasantfood = rpeasants(r) * 10; + static int food_rules = -1; + static int gamecookie = -1; - if (food_rules < 0 || gamecookie != global.cookie) { - gamecookie = global.cookie; - food_rules = get_param_int(global.parameters, "rules.economy.food", 0); - } - - if (food_rules & FOOD_IS_FREE) { - return; - } - /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber - * wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise - * jede Einheit genug Silber für ihren Unterhalt hat. */ - - for (u = r->units; u; u = u->next) { - int need = lifestyle(u); - - /* Erstmal zurücksetzen */ - freset(u, UFL_HUNGER); - - if (u->ship && (u->ship->flags & SF_FISHING)) { - unit *v; - int c = 2; - for (v = u; c > 0 && v; v = v->next) { - if (v->ship == u->ship) { - int get = 0; - if (v->number <= c) { - get = lifestyle(v); - } else { - get = lifestyle(v) * c / v->number; - } - if (get) { - change_money(v, get); - } - } - c -= v->number; - } - u->ship->flags -= SF_FISHING; + if (food_rules < 0 || gamecookie != global.cookie) { + gamecookie = global.cookie; + food_rules = get_param_int(global.parameters, "rules.economy.food", 0); } - if (food_rules & FOOD_FROM_PEASANTS) { - faction *owner = region_get_owner(r); - /* if the region is owned, and the owner is nice, then we'll get - * food from the peasants - should not be used with WORK */ - if (owner != NULL && (get_alliance(owner, u->faction) & HELP_MONEY)) { - int rm = rmoney(r); - int use = _min(rm, need); - rsetmoney(r, rm - use); - need -= use; - } + if (food_rules & FOOD_IS_FREE) { + return; } + /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber + * wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise + * jede Einheit genug Silber für ihren Unterhalt hat. */ - need -= get_money(u); - if (need > 0) { - unit *v; + for (u = r->units; u; u = u->next) { + int need = lifestyle(u); - for (v = r->units; need && v; v = v->next) { - if (v->faction == u->faction && help_money(v)) { - int give = get_money(v) - lifestyle(v); - give = _min(need, give); - if (give > 0) { - change_money(v, -give); - change_money(u, give); - need -= give; - } - } - } - } - } + /* Erstmal zurücksetzen */ + freset(u, UFL_HUNGER); - /* 2. Versorgung durch Fremde. Das Silber alliierter Einheiten wird - * entsprechend verteilt. */ - for (u = r->units; u; u = u->next) { - int need = lifestyle(u); - faction *f = u->faction; - - need -= _max(0, get_money(u)); - - if (need > 0) { - unit *v; - - if (food_rules & FOOD_FROM_OWNER) { - /* the owner of the region is the first faction to help out when you're hungry */ - faction *owner = region_get_owner(r); - if (owner && owner != u->faction) { - for (v = r->units; v; v = v->next) { - if (v->faction == owner && alliedunit(v, f, HELP_MONEY) - && help_money(v)) { - help_feed(v, u, &need); - break; + if (u->ship && (u->ship->flags & SF_FISHING)) { + unit *v; + int c = 2; + for (v = u; c > 0 && v; v = v->next) { + if (v->ship == u->ship) { + int get = 0; + if (v->number <= c) { + get = lifestyle(v); + } + else { + get = lifestyle(v) * c / v->number; + } + if (get) { + change_money(v, get); + } + } + c -= v->number; } - } + u->ship->flags -= SF_FISHING; } - } - for (v = r->units; need && v; v = v->next) { - if (v->faction != f && alliedunit(v, f, HELP_MONEY) - && help_money(v)) { - help_feed(v, u, &need); - } - } - /* Die Einheit hat nicht genug Geld zusammengekratzt und - * nimmt Schaden: */ - if (need > 0) { - int lspp = lifestyle(u) / u->number; - if (lspp > 0) { - int number = (need + lspp - 1) / lspp; - if (hunger(number, u)) - fset(u, UFL_HUNGER); - } - } - } - } - - /* 3. bestimmen, wie viele Bauern gefressen werden. - * bei fehlenden Bauern den Dämon hungern lassen - */ - for (u = r->units; u; u = u->next) { - if (u_race(u) == get_race(RC_DAEMON)) { - int hungry = u->number; - - /* use peasantblood before eating the peasants themselves */ - const struct potion_type *pt_blood = 0; - const resource_type *rt_blood = rt_find("peasantblood"); - if (rt_blood) { - pt_blood = rt_blood->ptype; - } - if (pt_blood) { - /* always start with the unit itself, then the first known unit that may have some blood */ - unit *donor = u; - while (donor != NULL && hungry > 0) { - int blut = get_effect(donor, pt_blood); - blut = _min(blut, hungry); - if (blut) { - change_effect(donor, pt_blood, -blut); - hungry -= blut; - } - if (donor == u) - donor = r->units; - while (donor != NULL) { - if (u_race(donor) == get_race(RC_DAEMON) && donor != u) { - if (get_effect(donor, pt_blood)) { - /* if he's in our faction, drain him: */ - if (donor->faction == u->faction) - break; - } + if (food_rules & FOOD_FROM_PEASANTS) { + faction *owner = region_get_owner(r); + /* if the region is owned, and the owner is nice, then we'll get + * food from the peasants - should not be used with WORK */ + if (owner != NULL && (get_alliance(owner, u->faction) & HELP_MONEY)) { + int rm = rmoney(r); + int use = _min(rm, need); + rsetmoney(r, rm - use); + need -= use; } - donor = donor->next; - } } - } - /* remaining demons feed on peasants */ - if (pl == NULL || !fval(pl, PFL_NOFEED)) { - if (peasantfood >= hungry) { - peasantfood -= hungry; - hungry = 0; - } else { - hungry -= peasantfood; - peasantfood = 0; - } - if (hungry > 0) { - static int demon_hunger = -1; - if (demon_hunger < 0) { - demon_hunger = get_param_int(global.parameters, "hunger.demons", 0); - } - if (demon_hunger == 0) { - /* demons who don't feed are hungry */ - if (hunger(hungry, u)) - fset(u, UFL_HUNGER); - } else { - /* no damage, but set the hungry-flag */ - fset(u, UFL_HUNGER); - } - } - } - } - } - rsetpeasants(r, peasantfood / 10); - /* 3. Von den überlebenden das Geld abziehen: */ - for (u = r->units; u; u = u->next) { - int need = _min(get_money(u), lifestyle(u)); - change_money(u, -need); - } + need -= get_money(u); + if (need > 0) { + unit *v; + + for (v = r->units; need && v; v = v->next) { + if (v->faction == u->faction && help_money(v)) { + int give = get_money(v) - lifestyle(v); + give = _min(need, give); + if (give > 0) { + change_money(v, -give); + change_money(u, give); + need -= give; + } + } + } + } + } + + /* 2. Versorgung durch Fremde. Das Silber alliierter Einheiten wird + * entsprechend verteilt. */ + for (u = r->units; u; u = u->next) { + int need = lifestyle(u); + faction *f = u->faction; + + need -= _max(0, get_money(u)); + + if (need > 0) { + unit *v; + + if (food_rules & FOOD_FROM_OWNER) { + /* the owner of the region is the first faction to help out when you're hungry */ + faction *owner = region_get_owner(r); + if (owner && owner != u->faction) { + for (v = r->units; v; v = v->next) { + if (v->faction == owner && alliedunit(v, f, HELP_MONEY) + && help_money(v)) { + help_feed(v, u, &need); + break; + } + } + } + } + for (v = r->units; need && v; v = v->next) { + if (v->faction != f && alliedunit(v, f, HELP_MONEY) + && help_money(v)) { + help_feed(v, u, &need); + } + } + + /* Die Einheit hat nicht genug Geld zusammengekratzt und + * nimmt Schaden: */ + if (need > 0) { + int lspp = lifestyle(u) / u->number; + if (lspp > 0) { + int number = (need + lspp - 1) / lspp; + if (hunger(number, u)) + fset(u, UFL_HUNGER); + } + } + } + } + + /* 3. bestimmen, wie viele Bauern gefressen werden. + * bei fehlenden Bauern den Dämon hungern lassen + */ + for (u = r->units; u; u = u->next) { + if (u_race(u) == get_race(RC_DAEMON)) { + int hungry = u->number; + + /* use peasantblood before eating the peasants themselves */ + const struct potion_type *pt_blood = 0; + const resource_type *rt_blood = rt_find("peasantblood"); + if (rt_blood) { + pt_blood = rt_blood->ptype; + } + if (pt_blood) { + /* always start with the unit itself, then the first known unit that may have some blood */ + unit *donor = u; + while (donor != NULL && hungry > 0) { + int blut = get_effect(donor, pt_blood); + blut = _min(blut, hungry); + if (blut) { + change_effect(donor, pt_blood, -blut); + hungry -= blut; + } + if (donor == u) + donor = r->units; + while (donor != NULL) { + if (u_race(donor) == get_race(RC_DAEMON) && donor != u) { + if (get_effect(donor, pt_blood)) { + /* if he's in our faction, drain him: */ + if (donor->faction == u->faction) + break; + } + } + donor = donor->next; + } + } + } + /* remaining demons feed on peasants */ + if (pl == NULL || !fval(pl, PFL_NOFEED)) { + if (peasantfood >= hungry) { + peasantfood -= hungry; + hungry = 0; + } + else { + hungry -= peasantfood; + peasantfood = 0; + } + if (hungry > 0) { + static int demon_hunger = -1; + if (demon_hunger < 0) { + demon_hunger = get_param_int(global.parameters, "hunger.demons", 0); + } + if (demon_hunger == 0) { + /* demons who don't feed are hungry */ + if (hunger(hungry, u)) + fset(u, UFL_HUNGER); + } + else { + /* no damage, but set the hungry-flag */ + fset(u, UFL_HUNGER); + } + } + } + } + } + rsetpeasants(r, peasantfood / 10); + + /* 3. Von den überlebenden das Geld abziehen: */ + for (u = r->units; u; u = u->next) { + int need = _min(get_money(u), lifestyle(u)); + change_money(u, -need); + } } static void age_unit(region * r, unit * u) { if (u_race(u) == get_race(RC_SPELL)) { - if (--u->age <= 0) { - remove_unit(&r->units, u); - } - } else { - ++u->age; - if (u->number > 0 && u_race(u)->age) { - u_race(u)->age(u); - } - } -#ifdef ASTRAL_ITEM_RESTRICTIONS - if (u->region && is_astral(u->region)) { - item **itemp = &u->items; - while (*itemp) { - item *itm = *itemp; - if ((itm->type->flags & ITF_NOTLOST) == 0) { - if (itm->type->flags & (ITF_BIG | ITF_ANIMAL | ITF_CURSED)) { - ADDMSG(&u->faction->msgs, msg_message("itemcrumble", - "unit region item amount", - u, u->region, itm->type->rtype, itm->number)); - i_free(i_remove(itemp, itm)); - continue; + if (--u->age <= 0) { + remove_unit(&r->units, u); + } + } + else { + ++u->age; + if (u->number > 0 && u_race(u)->age) { + u_race(u)->age(u); + } + } +#ifdef ASTRAL_ITEM_RESTRICTIONS + if (u->region && is_astral(u->region)) { + item **itemp = &u->items; + while (*itemp) { + item *itm = *itemp; + if ((itm->type->flags & ITF_NOTLOST) == 0) { + if (itm->type->flags & (ITF_BIG | ITF_ANIMAL | ITF_CURSED)) { + ADDMSG(&u->faction->msgs, msg_message("itemcrumble", + "unit region item amount", + u, u->region, itm->type->rtype, itm->number)); + i_free(i_remove(itemp, itm)); + continue; + } + } + itemp = &itm->next; } - } - itemp = &itm->next; } - } #endif } static void live(region * r) { - unit **up = &r->units; + unit **up = &r->units; - get_food(r); + get_food(r); - while (*up) { - unit *u = *up; - /* IUW: age_unit() kann u loeschen, u->next ist dann - * undefiniert, also muessen wir hier schon das nächste - * Element bestimmen */ + while (*up) { + unit *u = *up; + /* IUW: age_unit() kann u loeschen, u->next ist dann + * undefiniert, also muessen wir hier schon das nächste + * Element bestimmen */ - int effect = get_effect(u, oldpotiontype[P_FOOL]); - if (effect > 0) { /* Trank "Dumpfbackenbrot" */ - skill *sv = u->skills, *sb = NULL; - while (sv != u->skills + u->skill_size) { - if (sb == NULL || skill_compare(sv, sb) > 0) { - sb = sv; + int effect = get_effect(u, oldpotiontype[P_FOOL]); + if (effect > 0) { /* Trank "Dumpfbackenbrot" */ + skill *sv = u->skills, *sb = NULL; + while (sv != u->skills + u->skill_size) { + if (sb == NULL || skill_compare(sv, sb) > 0) { + sb = sv; + } + ++sv; + } + /* bestes Talent raussuchen */ + if (sb != NULL) { + int weeks = _min(effect, u->number); + reduce_skill(u, sb, weeks); + ADDMSG(&u->faction->msgs, msg_message("dumbeffect", + "unit weeks skill", u, weeks, (skill_t)sb->id)); + } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */ + change_effect(u, oldpotiontype[P_FOOL], -effect); } - ++sv; - } - /* bestes Talent raussuchen */ - if (sb != NULL) { - int weeks = _min(effect, u->number); - reduce_skill(u, sb, weeks); - ADDMSG(&u->faction->msgs, msg_message("dumbeffect", - "unit weeks skill", u, weeks, (skill_t) sb->id)); - } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */ - change_effect(u, oldpotiontype[P_FOOL], -effect); + age_unit(r, u); + if (*up == u) + up = &u->next; } - age_unit(r, u); - if (*up == u) - up = &u->next; - } } /* @@ -449,113 +453,113 @@ static void live(region * r) static void calculate_emigration(region * r) { - int i; - int maxp = maxworkingpeasants(r); - int rp = rpeasants(r); - int max_immigrants = MAX_IMMIGRATION(maxp - rp); + int i; + int maxp = maxworkingpeasants(r); + int rp = rpeasants(r); + int max_immigrants = MAX_IMMIGRATION(maxp - rp); - if (r->terrain == newterrain(T_VOLCANO) - || r->terrain == newterrain(T_VOLCANO_SMOKING)) { - max_immigrants = max_immigrants / 10; - } - - for (i = 0; max_immigrants > 0 && i != MAXDIRECTIONS; i++) { - int dir = (turn + i) % MAXDIRECTIONS; - region *rc = rconnect(r, (direction_t) dir); - - if (rc != NULL && fval(rc->terrain, LAND_REGION)) { - int rp2 = rpeasants(rc); - int maxp2 = maxworkingpeasants(rc); - int max_emigration = MAX_EMIGRATION(rp2 - maxp2); - - if (max_emigration > 0) { - max_emigration = _min(max_emigration, max_immigrants); - r->land->newpeasants += max_emigration; - rc->land->newpeasants -= max_emigration; - max_immigrants -= max_emigration; - } + if (r->terrain == newterrain(T_VOLCANO) + || r->terrain == newterrain(T_VOLCANO_SMOKING)) { + max_immigrants = max_immigrants / 10; + } + + for (i = 0; max_immigrants > 0 && i != MAXDIRECTIONS; i++) { + int dir = (turn + i) % MAXDIRECTIONS; + region *rc = rconnect(r, (direction_t)dir); + + if (rc != NULL && fval(rc->terrain, LAND_REGION)) { + int rp2 = rpeasants(rc); + int maxp2 = maxworkingpeasants(rc); + int max_emigration = MAX_EMIGRATION(rp2 - maxp2); + + if (max_emigration > 0) { + max_emigration = _min(max_emigration, max_immigrants); + r->land->newpeasants += max_emigration; + rc->land->newpeasants -= max_emigration; + max_immigrants -= max_emigration; + } + } } - } } /** Bauern vermehren sich */ static void peasants(region * r) { - int peasants = rpeasants(r); - int money = rmoney(r); - int maxp = production(r) * MAXPEASANTS_PER_AREA; - int n, satiated; - int dead = 0; + int peasants = rpeasants(r); + int money = rmoney(r); + int maxp = production(r) * MAXPEASANTS_PER_AREA; + int n, satiated; + int dead = 0; - /* Bis zu 1000 Bauern können Zwillinge bekommen oder 1000 Bauern - * wollen nicht! */ + /* Bis zu 1000 Bauern können Zwillinge bekommen oder 1000 Bauern + * wollen nicht! */ - if (peasants > 0 && get_param_int(global.parameters, "rules.peasants.growth", 1)) { - int glueck = 0; - double fraction = peasants * 0.0001F * PEASANTGROWTH; - int births = (int)fraction; - attrib *a = a_find(r->attribs, &at_peasantluck); + if (peasants > 0 && get_param_int(global.parameters, "rules.peasants.growth", 1)) { + int glueck = 0; + double fraction = peasants * 0.0001F * PEASANTGROWTH; + int births = (int)fraction; + attrib *a = a_find(r->attribs, &at_peasantluck); - if (rng_double() < (fraction - births)) { - /* because we don't want regions that never grow pga. rounding. */ - ++births; - } - if (a != NULL) { - glueck = a->data.i * 1000; - } - - for (n = peasants; n; --n) { - int chances = 0; - - if (glueck > 0) { - --glueck; - chances += PEASANTLUCK; - } - - while (chances--) { - if (rng_int() % 10000 < PEASANTGROWTH) { - /* Only raise with 75% chance if peasants have - * reached 90% of maxpopulation */ - if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) { + if (rng_double() < (fraction - births)) { + /* because we don't want regions that never grow pga. rounding. */ ++births; - } } - } + if (a != NULL) { + glueck = a->data.i * 1000; + } + + for (n = peasants; n; --n) { + int chances = 0; + + if (glueck > 0) { + --glueck; + chances += PEASANTLUCK; + } + + while (chances--) { + if (rng_int() % 10000 < PEASANTGROWTH) { + /* Only raise with 75% chance if peasants have + * reached 90% of maxpopulation */ + if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) { + ++births; + } + } + } + } + peasants += births; } - peasants += births; - } - /* Alle werden satt, oder halt soviele für die es auch Geld gibt */ + /* Alle werden satt, oder halt soviele für die es auch Geld gibt */ - satiated = _min(peasants, money / maintenance_cost(NULL)); - rsetmoney(r, money - satiated * maintenance_cost(NULL)); + satiated = _min(peasants, money / maintenance_cost(NULL)); + rsetmoney(r, money - satiated * maintenance_cost(NULL)); - /* Von denjenigen, die nicht satt geworden sind, verhungert der - * Großteil. dead kann nie größer als rpeasants(r) - satiated werden, - * so dass rpeasants(r) >= 0 bleiben muß. */ + /* Von denjenigen, die nicht satt geworden sind, verhungert der + * Großteil. dead kann nie größer als rpeasants(r) - satiated werden, + * so dass rpeasants(r) >= 0 bleiben muß. */ - /* Es verhungert maximal die unterernährten Bevölkerung. */ + /* Es verhungert maximal die unterernährten Bevölkerung. */ - n = _min(peasants - satiated, rpeasants(r)); - dead += (int)(0.5F + n * PEASANT_STARVATION_CHANCE); + n = _min(peasants - satiated, rpeasants(r)); + dead += (int)(0.5F + n * PEASANT_STARVATION_CHANCE); - if (dead > 0) { - message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead)); - msg_release(msg); - peasants -= dead; - } + if (dead > 0) { + message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead)); + msg_release(msg); + peasants -= dead; + } - rsetpeasants(r, peasants); + rsetpeasants(r, peasants); } /* ------------------------------------------------------------- */ typedef struct migration { - struct migration *next; - region *r; - int horses; - int trees; + struct migration *next; + region *r; + int horses; + int trees; } migration; #define MSIZE 1023 @@ -564,459 +568,463 @@ migration *free_migrants; static migration *get_migrants(region * r) { - int key = reg_hashkey(r); - int index = key % MSIZE; - migration *m = migrants[index]; - while (m && m->r != r) - m = m->next; - if (m == NULL) { - /* Es gibt noch keine Migration. Also eine erzeugen - */ - m = free_migrants; - if (!m) - m = calloc(1, sizeof(migration)); - else { - free_migrants = free_migrants->next; - m->horses = 0; - m->trees = 0; + int key = reg_hashkey(r); + int index = key % MSIZE; + migration *m = migrants[index]; + while (m && m->r != r) + m = m->next; + if (m == NULL) { + /* Es gibt noch keine Migration. Also eine erzeugen + */ + m = free_migrants; + if (!m) + m = calloc(1, sizeof(migration)); + else { + free_migrants = free_migrants->next; + m->horses = 0; + m->trees = 0; + } + m->r = r; + m->next = migrants[index]; + migrants[index] = m; } - m->r = r; - m->next = migrants[index]; - migrants[index] = m; - } - return m; + return m; } static void migrate(region * r) { - int key = reg_hashkey(r); - int index = key % MSIZE; - migration **hp = &migrants[index]; - fset(r, RF_MIGRATION); - while (*hp && (*hp)->r != r) - hp = &(*hp)->next; - if (*hp) { - migration *m = *hp; - rsethorses(r, rhorses(r) + m->horses); - /* Was macht das denn hier? - * Baumwanderung wird in trees() gemacht. - * wer fragt das? Die Baumwanderung war abhängig von der - * Auswertungsreihenfolge der regionen, - * das hatte ich geändert. jemand hat es wieder gelöscht, toll. - * ich habe es wieder aktiviert, muß getestet werden. - */ - *hp = m->next; - m->next = free_migrants; - free_migrants = m; - } + int key = reg_hashkey(r); + int index = key % MSIZE; + migration **hp = &migrants[index]; + fset(r, RF_MIGRATION); + while (*hp && (*hp)->r != r) + hp = &(*hp)->next; + if (*hp) { + migration *m = *hp; + rsethorses(r, rhorses(r) + m->horses); + /* Was macht das denn hier? + * Baumwanderung wird in trees() gemacht. + * wer fragt das? Die Baumwanderung war abhängig von der + * Auswertungsreihenfolge der regionen, + * das hatte ich geändert. jemand hat es wieder gelöscht, toll. + * ich habe es wieder aktiviert, muß getestet werden. + */ + *hp = m->next; + m->next = free_migrants; + free_migrants = m; + } } static void horses(region * r) { - int horses, maxhorses; - direction_t n; + int horses, maxhorses; + direction_t n; - /* Logistisches Wachstum, Optimum bei halbem Maximalbesatz. */ - maxhorses = maxworkingpeasants(r) / 10; - maxhorses = _max(0, maxhorses); - horses = rhorses(r); - if (horses > 0) { - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { - rsethorses(r, (int)(horses * 0.9F)); - } else if (maxhorses) { - int i; - double growth = - (RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses - - horses)) / maxhorses; + /* Logistisches Wachstum, Optimum bei halbem Maximalbesatz. */ + maxhorses = maxworkingpeasants(r) / 10; + maxhorses = _max(0, maxhorses); + horses = rhorses(r); + if (horses > 0) { + if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + rsethorses(r, (int)(horses * 0.9F)); + } + else if (maxhorses) { + int i; + double growth = + (RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses - + horses)) / maxhorses; - if (growth > 0) { - if (a_find(r->attribs, &at_horseluck)) - growth *= 2; - /* printf("Horses: <%d> %d -> ", growth, horses); */ - i = (int)(0.5F + (horses * 0.0001F) * growth); - /* printf("%d\n", horses); */ - rsethorses(r, horses + i); - } + if (growth > 0) { + if (a_find(r->attribs, &at_horseluck)) + growth *= 2; + /* printf("Horses: <%d> %d -> ", growth, horses); */ + i = (int)(0.5F + (horses * 0.0001F) * growth); + /* printf("%d\n", horses); */ + rsethorses(r, horses + i); + } + } } - } - /* Pferde wandern in Nachbarregionen. - * Falls die Nachbarregion noch berechnet - * werden muß, wird eine migration-Struktur gebildet, - * die dann erst in die Berechnung der Nachbarstruktur einfließt. - */ + /* Pferde wandern in Nachbarregionen. + * Falls die Nachbarregion noch berechnet + * werden muß, wird eine migration-Struktur gebildet, + * die dann erst in die Berechnung der Nachbarstruktur einfließt. + */ - for (n = 0; n != MAXDIRECTIONS; n++) { - region *r2 = rconnect(r, n); - if (r2 && fval(r2->terrain, WALK_INTO)) { - int pt = (rhorses(r) * HORSEMOVE) / 100; - pt = (int)normalvariate(pt, pt / 4.0); - pt = _max(0, pt); - if (fval(r2, RF_MIGRATION)) - rsethorses(r2, rhorses(r2) + pt); - else { - migration *nb; - /* haben wir die Migration schonmal benutzt? - * wenn nicht, müssen wir sie suchen. - * Wandernde Pferde vermehren sich nicht. - */ - nb = get_migrants(r2); - nb->horses += pt; - } - /* Wandernde Pferde sollten auch abgezogen werden */ - rsethorses(r, rhorses(r) - pt); + for (n = 0; n != MAXDIRECTIONS; n++) { + region *r2 = rconnect(r, n); + if (r2 && fval(r2->terrain, WALK_INTO)) { + int pt = (rhorses(r) * HORSEMOVE) / 100; + pt = (int)normalvariate(pt, pt / 4.0); + pt = _max(0, pt); + if (fval(r2, RF_MIGRATION)) + rsethorses(r2, rhorses(r2) + pt); + else { + migration *nb; + /* haben wir die Migration schonmal benutzt? + * wenn nicht, müssen wir sie suchen. + * Wandernde Pferde vermehren sich nicht. + */ + nb = get_migrants(r2); + nb->horses += pt; + } + /* Wandernde Pferde sollten auch abgezogen werden */ + rsethorses(r, rhorses(r) - pt); + } } - } - assert(rhorses(r) >= 0); + assert(rhorses(r) >= 0); } static int count_race(const region * r, const race * rc) { - unit *u; - int c = 0; + unit *u; + int c = 0; - for (u = r->units; u; u = u->next) - if (u_race(u) == rc) - c += u->number; + for (u = r->units; u; u = u->next) + if (u_race(u) == rc) + c += u->number; - return c; + return c; } extern struct attrib_type at_germs; static void growing_trees_e3(region * r, const int current_season, - const int last_weeks_season) +const int last_weeks_season) { - static const int transform[4][3] = { - {-1, -1, 0}, - {TREE_SEED, TREE_SAPLING, 2}, - {TREE_SAPLING, TREE_TREE, 2}, - {TREE_TREE, TREE_SEED, 2} - }; + static const int transform[4][3] = { + { -1, -1, 0 }, + { TREE_SEED, TREE_SAPLING, 2 }, + { TREE_SAPLING, TREE_TREE, 2 }, + { TREE_TREE, TREE_SEED, 2 } + }; - if (r->land && current_season != last_weeks_season - && transform[current_season][2]) { - int src_type = transform[current_season][0]; - int dst_type = transform[current_season][1]; - int src = rtrees(r, src_type); - int dst = rtrees(r, dst_type); - int grow = src / transform[current_season][2]; - if (grow > 0) { - if (src_type != TREE_TREE) { - rsettrees(r, src_type, src - grow); - } - rsettrees(r, dst_type, dst + grow); - - if (dst_type == TREE_SEED && r->terrain->size) { - region *rn[MAXDIRECTIONS]; - int d; - double fgrow = grow / (double)MAXDIRECTIONS; - - get_neighbours(r, rn); - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rx = rn[d]; - if (rx && rx->land) { - double scale = 1.0; - int g; - double fg, ch; - int seeds = rtrees(rx, dst_type); - - if (r->terrain->size > rx->terrain->size) { - scale = (scale * rx->terrain->size) / r->terrain->size; + if (r->land && current_season != last_weeks_season + && transform[current_season][2]) { + int src_type = transform[current_season][0]; + int dst_type = transform[current_season][1]; + int src = rtrees(r, src_type); + int dst = rtrees(r, dst_type); + int grow = src / transform[current_season][2]; + if (grow > 0) { + if (src_type != TREE_TREE) { + rsettrees(r, src_type, src - grow); } - fg = scale * fgrow; - g = (int)fg; - ch = fg - g; - if (chance(ch)) - ++g; - if (g > 0) { - rsettrees(rx, dst_type, seeds + g); + rsettrees(r, dst_type, dst + grow); + + if (dst_type == TREE_SEED && r->terrain->size) { + region *rn[MAXDIRECTIONS]; + int d; + double fgrow = grow / (double)MAXDIRECTIONS; + + get_neighbours(r, rn); + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rx = rn[d]; + if (rx && rx->land) { + double scale = 1.0; + int g; + double fg, ch; + int seeds = rtrees(rx, dst_type); + + if (r->terrain->size > rx->terrain->size) { + scale = (scale * rx->terrain->size) / r->terrain->size; + } + fg = scale * fgrow; + g = (int)fg; + ch = fg - g; + if (chance(ch)) + ++g; + if (g > 0) { + rsettrees(rx, dst_type, seeds + g); + } + } + } } - } } - } } - } } static void growing_trees(region * r, const int current_season, const int last_weeks_season) { - int growth, grownup_trees, i, seeds, sprout; - direction_t d; - attrib *a; + int growth, grownup_trees, i, seeds, sprout; + direction_t d; + attrib *a; - if (current_season == SEASON_SUMMER || current_season == SEASON_AUTUMN) { - double seedchance = 0.01F * RESOURCE_QUANTITY; - int elves = count_race(r, get_race(RC_ELF)); + if (current_season == SEASON_SUMMER || current_season == SEASON_AUTUMN) { + double seedchance = 0.01F * RESOURCE_QUANTITY; + int elves = count_race(r, get_race(RC_ELF)); - a = a_find(r->attribs, &at_germs); - if (a && last_weeks_season == SEASON_SPRING) { - /* ungekeimte Samen bleiben erhalten, Sprößlinge wachsen */ - sprout = _min(a->data.sa[1], rtrees(r, 1)); - /* aus dem gesamt Sprößlingepool abziehen */ - rsettrees(r, 1, rtrees(r, 1) - sprout); - /* zu den Bäumen hinzufügen */ - rsettrees(r, 2, rtrees(r, 2) + sprout); + a = a_find(r->attribs, &at_germs); + if (a && last_weeks_season == SEASON_SPRING) { + /* ungekeimte Samen bleiben erhalten, Sprößlinge wachsen */ + sprout = _min(a->data.sa[1], rtrees(r, 1)); + /* aus dem gesamt Sprößlingepool abziehen */ + rsettrees(r, 1, rtrees(r, 1) - sprout); + /* zu den Bäumen hinzufügen */ + rsettrees(r, 2, rtrees(r, 2) + sprout); - a_removeall(&r->attribs, &at_germs); - } - - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { - rsettrees(r, 1, (int)(rtrees(r, 1) * 0.9)); - rsettrees(r, 2, (int)(rtrees(r, 2) * 0.9)); - return; - } - - if (production(r) <= 0) - return; - - /* Grundchance 1.0% */ - /* Jeder Elf in der Region erhöht die Chance marginal */ - elves = _min(elves, (production(r) * MAXPEASANTS_PER_AREA) / 8); - if (elves) { - seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY); - } - grownup_trees = rtrees(r, 2); - seeds = 0; - - if (grownup_trees > 0) { - double remainder = seedchance * grownup_trees; - seeds = (int)(remainder); - remainder -= seeds; - if (chance(remainder)) { - ++seeds; - } - if (seeds > 0) { - seeds += rtrees(r, 0); - rsettrees(r, 0, seeds); - } - } - - /* Bäume breiten sich in Nachbarregionen aus. */ - - /* Gesamtzahl der Samen: - * bis zu 6% (FORESTGROWTH*3) der Bäume samen in die Nachbarregionen */ - seeds = (rtrees(r, 2) * FORESTGROWTH * 3) / 1000000; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *r2 = rconnect(r, d); - if (r2 && fval(r2->terrain, LAND_REGION) && r2->terrain->size) { - /* Eine Landregion, wir versuchen Samen zu verteilen: - * Die Chance, das Samen ein Stück Boden finden, in dem sie - * keimen können, hängt von der Bewuchsdichte und der - * verfügbaren Fläche ab. In Gletschern gibt es weniger - * Möglichkeiten als in Ebenen. */ - sprout = 0; - seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size; - for (i = 0; i < seeds / MAXDIRECTIONS; i++) { - if (rng_int() % 10000 < seedchance) - sprout++; + a_removeall(&r->attribs, &at_germs); } - rsettrees(r2, 0, rtrees(r2, 0) + sprout); - } + + if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + rsettrees(r, 1, (int)(rtrees(r, 1) * 0.9)); + rsettrees(r, 2, (int)(rtrees(r, 2) * 0.9)); + return; + } + + if (production(r) <= 0) + return; + + /* Grundchance 1.0% */ + /* Jeder Elf in der Region erhöht die Chance marginal */ + elves = _min(elves, (production(r) * MAXPEASANTS_PER_AREA) / 8); + if (elves) { + seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY); + } + grownup_trees = rtrees(r, 2); + seeds = 0; + + if (grownup_trees > 0) { + double remainder = seedchance * grownup_trees; + seeds = (int)(remainder); + remainder -= seeds; + if (chance(remainder)) { + ++seeds; + } + if (seeds > 0) { + seeds += rtrees(r, 0); + rsettrees(r, 0, seeds); + } + } + + /* Bäume breiten sich in Nachbarregionen aus. */ + + /* Gesamtzahl der Samen: + * bis zu 6% (FORESTGROWTH*3) der Bäume samen in die Nachbarregionen */ + seeds = (rtrees(r, 2) * FORESTGROWTH * 3) / 1000000; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *r2 = rconnect(r, d); + if (r2 && fval(r2->terrain, LAND_REGION) && r2->terrain->size) { + /* Eine Landregion, wir versuchen Samen zu verteilen: + * Die Chance, das Samen ein Stück Boden finden, in dem sie + * keimen können, hängt von der Bewuchsdichte und der + * verfügbaren Fläche ab. In Gletschern gibt es weniger + * Möglichkeiten als in Ebenen. */ + sprout = 0; + seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size; + for (i = 0; i < seeds / MAXDIRECTIONS; i++) { + if (rng_int() % 10000 < seedchance) + sprout++; + } + rsettrees(r2, 0, rtrees(r2, 0) + sprout); + } + } + } + else if (current_season == SEASON_SPRING) { - } else if (current_season == SEASON_SPRING) { + if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) + return; - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) - return; + /* in at_germs merken uns die Zahl der Samen und Sprößlinge, die + * dieses Jahr älter werden dürfen, damit nicht ein Same im selben + * Zyklus zum Baum werden kann */ + a = a_find(r->attribs, &at_germs); + if (!a) { + a = a_add(&r->attribs, a_new(&at_germs)); + a->data.sa[0] = (short)rtrees(r, 0); + a->data.sa[1] = (short)rtrees(r, 1); + } + /* wir haben 6 Wochen zum wachsen, jeder Same/Sproß hat 18% Chance + * zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */ + growth = 1800; - /* in at_germs merken uns die Zahl der Samen und Sprößlinge, die - * dieses Jahr älter werden dürfen, damit nicht ein Same im selben - * Zyklus zum Baum werden kann */ - a = a_find(r->attribs, &at_germs); - if (!a) { - a = a_add(&r->attribs, a_new(&at_germs)); - a->data.sa[0] = (short)rtrees(r, 0); - a->data.sa[1] = (short)rtrees(r, 1); + /* Samenwachstum */ + + /* Raubbau abfangen, es dürfen nie mehr Samen wachsen, als aktuell + * in der Region sind */ + seeds = _min(a->data.sa[0], rtrees(r, 0)); + sprout = 0; + + for (i = 0; i < seeds; i++) { + if (rng_int() % 10000 < growth) + sprout++; + } + /* aus dem Samenpool dieses Jahres abziehen */ + a->data.sa[0] = (short)(seeds - sprout); + /* aus dem gesamt Samenpool abziehen */ + rsettrees(r, 0, rtrees(r, 0) - sprout); + /* zu den Sprößlinge hinzufügen */ + rsettrees(r, 1, rtrees(r, 1) + sprout); + + /* Baumwachstum */ + + /* hier gehen wir davon aus, das Jungbäume nicht ohne weiteres aus + * der Region entfernt werden können, da Jungbäume in der gleichen + * Runde nachwachsen, wir also nicht mehr zwischen diesjährigen und + * 'alten' Jungbäumen unterscheiden könnten */ + sprout = _min(a->data.sa[1], rtrees(r, 1)); + grownup_trees = 0; + + for (i = 0; i < sprout; i++) { + if (rng_int() % 10000 < growth) + grownup_trees++; + } + /* aus dem Sprößlingepool dieses Jahres abziehen */ + a->data.sa[1] = (short)(sprout - grownup_trees); + /* aus dem gesamt Sprößlingepool abziehen */ + rsettrees(r, 1, rtrees(r, 1) - grownup_trees); + /* zu den Bäumen hinzufügen */ + rsettrees(r, 2, rtrees(r, 2) + grownup_trees); } - /* wir haben 6 Wochen zum wachsen, jeder Same/Sproß hat 18% Chance - * zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */ - growth = 1800; - - /* Samenwachstum */ - - /* Raubbau abfangen, es dürfen nie mehr Samen wachsen, als aktuell - * in der Region sind */ - seeds = _min(a->data.sa[0], rtrees(r, 0)); - sprout = 0; - - for (i = 0; i < seeds; i++) { - if (rng_int() % 10000 < growth) - sprout++; - } - /* aus dem Samenpool dieses Jahres abziehen */ - a->data.sa[0] = (short)(seeds - sprout); - /* aus dem gesamt Samenpool abziehen */ - rsettrees(r, 0, rtrees(r, 0) - sprout); - /* zu den Sprößlinge hinzufügen */ - rsettrees(r, 1, rtrees(r, 1) + sprout); - - /* Baumwachstum */ - - /* hier gehen wir davon aus, das Jungbäume nicht ohne weiteres aus - * der Region entfernt werden können, da Jungbäume in der gleichen - * Runde nachwachsen, wir also nicht mehr zwischen diesjährigen und - * 'alten' Jungbäumen unterscheiden könnten */ - sprout = _min(a->data.sa[1], rtrees(r, 1)); - grownup_trees = 0; - - for (i = 0; i < sprout; i++) { - if (rng_int() % 10000 < growth) - grownup_trees++; - } - /* aus dem Sprößlingepool dieses Jahres abziehen */ - a->data.sa[1] = (short)(sprout - grownup_trees); - /* aus dem gesamt Sprößlingepool abziehen */ - rsettrees(r, 1, rtrees(r, 1) - grownup_trees); - /* zu den Bäumen hinzufügen */ - rsettrees(r, 2, rtrees(r, 2) + grownup_trees); - } } static void growing_herbs(region * r, const int current_season, const int last_weeks_season) { - /* Jetzt die Kräutervermehrung. Vermehrt wird logistisch: - * - * Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene - * Kräuter))% sich zu vermehren. */ - if (current_season != SEASON_WINTER) { - int i; - for (i = rherbs(r); i > 0; i--) { - if (rng_int() % 100 < (100 - rherbs(r))) - rsetherbs(r, (short)(rherbs(r) + 1)); + /* Jetzt die Kräutervermehrung. Vermehrt wird logistisch: + * + * Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene + * Kräuter))% sich zu vermehren. */ + if (current_season != SEASON_WINTER) { + int i; + for (i = rherbs(r); i > 0; i--) { + if (rng_int() % 100 < (100 - rherbs(r))) + rsetherbs(r, (short)(rherbs(r) + 1)); + } } - } } void demographics(void) { - region *r; - static int last_weeks_season = -1; - static int current_season = -1; + region *r; + static int last_weeks_season = -1; + static int current_season = -1; - if (current_season < 0) { - gamedate date; - get_gamedate(turn, &date); - current_season = date.season; - get_gamedate(turn - 1, &date); - last_weeks_season = date.season; - } - - for (r = regions; r; r = r->next) { - ++r->age; /* also oceans. no idea why we didn't always do that */ - live(r); - /* check_split_dragons(); */ - - if (!fval(r->terrain, SEA_REGION)) { - /* die Nachfrage nach Produkten steigt. */ - struct demand *dmd; - if (r->land) { - static int plant_rules = -1; - - if (plant_rules < 0) { - plant_rules = - get_param_int(global.parameters, "rules.economy.grow", 0); - } - for (dmd = r->land->demands; dmd; dmd = dmd->next) { - if (dmd->value > 0 && dmd->value < MAXDEMAND) { - float rise = DMRISE; - if (buildingtype_exists(r, bt_find("harbour"), true)) - rise = DMRISEHAFEN; - if (rng_double() < rise) - ++dmd->value; - } - } - /* Seuchen erst nachdem die Bauern sich vermehrt haben - * und gewandert sind */ - - calculate_emigration(r); - peasants(r); - if (r->age > 20) { - plagues(r, false); - } - horses(r); - if (plant_rules == 0) { /* E1 */ - growing_trees(r, current_season, last_weeks_season); - growing_herbs(r, current_season, last_weeks_season); - } else { /* E3 */ - growing_trees_e3(r, current_season, last_weeks_season); - } - } - - update_resources(r); - if (r->land) - migrate(r); + if (current_season < 0) { + gamedate date; + get_gamedate(turn, &date); + current_season = date.season; + get_gamedate(turn - 1, &date); + last_weeks_season = date.season; } - } - while (free_migrants) { - migration *m = free_migrants->next; - free(free_migrants); - free_migrants = m; - }; - if (verbosity >= 1) - putchar('\n'); - remove_empty_units(); + for (r = regions; r; r = r->next) { + ++r->age; /* also oceans. no idea why we didn't always do that */ + live(r); + /* check_split_dragons(); */ - log_info(" - Einwanderung..."); - for (r = regions; r; r = r->next) { - if (r->land && r->land->newpeasants) { - int rp = rpeasants(r) + r->land->newpeasants; - rsetpeasants(r, _max(0, rp)); + if (!fval(r->terrain, SEA_REGION)) { + /* die Nachfrage nach Produkten steigt. */ + struct demand *dmd; + if (r->land) { + static int plant_rules = -1; + + if (plant_rules < 0) { + plant_rules = + get_param_int(global.parameters, "rules.economy.grow", 0); + } + for (dmd = r->land->demands; dmd; dmd = dmd->next) { + if (dmd->value > 0 && dmd->value < MAXDEMAND) { + float rise = DMRISE; + if (buildingtype_exists(r, bt_find("harbour"), true)) + rise = DMRISEHAFEN; + if (rng_double() < rise) + ++dmd->value; + } + } + /* Seuchen erst nachdem die Bauern sich vermehrt haben + * und gewandert sind */ + + calculate_emigration(r); + peasants(r); + if (r->age > 20) { + plagues(r, false); + } + horses(r); + if (plant_rules == 0) { /* E1 */ + growing_trees(r, current_season, last_weeks_season); + growing_herbs(r, current_season, last_weeks_season); + } + else { /* E3 */ + growing_trees_e3(r, current_season, last_weeks_season); + } + } + + update_resources(r); + if (r->land) + migrate(r); + } } - } + while (free_migrants) { + migration *m = free_migrants->next; + free(free_migrants); + free_migrants = m; + }; + if (verbosity >= 1) + putchar('\n'); - checkorders(); + remove_empty_units(); + + log_info(" - Einwanderung..."); + for (r = regions; r; r = r->next) { + if (r->land && r->land->newpeasants) { + int rp = rpeasants(r) + r->land->newpeasants; + rsetpeasants(r, _max(0, rp)); + } + } + + checkorders(); } /* ------------------------------------------------------------- */ static int modify(int i) { - int c; + int c; - c = i * 2 / 3; + c = i * 2 / 3; - if (c >= 1) { - return (c + rng_int() % c); - } else { - return (i); - } + if (c >= 1) { + return (c + rng_int() % c); + } + else { + return (i); + } } static void inactivefaction(faction * f) { - FILE *inactiveFILE; - char zText[128]; + FILE *inactiveFILE; + char zText[128]; - sprintf(zText, "%s/%s", datapath(), "inactive"); - inactiveFILE = fopen(zText, "a"); + sprintf(zText, "%s/%s", datapath(), "inactive"); + inactiveFILE = fopen(zText, "a"); - if (inactiveFILE) { - fprintf(inactiveFILE, "%s:%s:%d:%d\n", - factionid(f), - LOC(default_locale, rc_name(f->race, 1)), - modify(count_all(f)), turn - f->lastorders); + if (inactiveFILE) { + fprintf(inactiveFILE, "%s:%s:%d:%d\n", + factionid(f), + LOC(default_locale, rc_name(f->race, 1)), + modify(count_all(f)), turn - f->lastorders); - fclose(inactiveFILE); - } + fclose(inactiveFILE); + } } static void transfer_faction(faction * f, faction * f2) { - unit *u, *un; + unit *u, *un; - for (u = f->units; u;) { - un = u->nextF; - if (!unit_has_cursed_item(u) - && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) { - u_setfaction(u, f2); + for (u = f->units; u;) { + un = u->nextF; + if (!unit_has_cursed_item(u) + && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) { + u_setfaction(u, f2); + } + u = un; } - u = un; - } } /* test if the unit can slip through a siege undetected. @@ -1025,388 +1033,395 @@ static void transfer_faction(faction * f, faction * f2) */ static int slipthru(const region * r, const unit * u, const building * b) { - unit *u2; - int n, o; + unit *u2; + int n, o; - /* b ist die burg, in die man hinein oder aus der man heraus will. */ - if (b == NULL || b->besieged < b->size * SIEGEFACTOR) { - return 1; - } - - /* u wird am hinein- oder herausschluepfen gehindert, wenn STEALTH <= - * OBSERVATION +2 der belagerer u2 ist */ - n = eff_skill(u, SK_STEALTH, r); - - for (u2 = r->units; u2; u2 = u2->next) { - if (usiege(u2) == b) { - - if (invisible(u, u2) >= u->number) - continue; - - o = eff_skill(u2, SK_PERCEPTION, r); - - if (o + 2 >= n) { - return 0; /* entdeckt! */ - } + /* b ist die burg, in die man hinein oder aus der man heraus will. */ + if (b == NULL || b->besieged < b->size * SIEGEFACTOR) { + return 1; } - } - return 1; + + /* u wird am hinein- oder herausschluepfen gehindert, wenn STEALTH <= + * OBSERVATION +2 der belagerer u2 ist */ + n = eff_skill(u, SK_STEALTH, r); + + for (u2 = r->units; u2; u2 = u2->next) { + if (usiege(u2) == b) { + + if (invisible(u, u2) >= u->number) + continue; + + o = eff_skill(u2, SK_PERCEPTION, r); + + if (o + 2 >= n) { + return 0; /* entdeckt! */ + } + } + } + return 1; } int can_contact(const region * r, const unit * u, const unit * u2) { - /* hier geht es nur um die belagerung von burgen */ + /* hier geht es nur um die belagerung von burgen */ - if (u->building == u2->building) { - return 1; - } + if (u->building == u2->building) { + return 1; + } - /* unit u is trying to contact u2 - unasked for contact. wenn u oder u2 - * nicht in einer burg ist, oder die burg nicht belagert ist, ist - * slipthru () == 1. ansonsten ist es nur 1, wenn man die belagerer */ + /* unit u is trying to contact u2 - unasked for contact. wenn u oder u2 + * nicht in einer burg ist, oder die burg nicht belagert ist, ist + * slipthru () == 1. ansonsten ist es nur 1, wenn man die belagerer */ - if (slipthru(u->region, u, u->building) && slipthru(u->region, u2, u2->building)) { - return 1; - } + if (slipthru(u->region, u, u->building) && slipthru(u->region, u2, u2->building)) { + return 1; + } - return (alliedunit(u, u2->faction, HELP_GIVE)); + return (alliedunit(u, u2->faction, HELP_GIVE)); } int contact_cmd(unit * u, order * ord) { - /* unit u kontaktiert unit u2. Dies setzt den contact einfach auf 1 - - * ein richtiger toggle ist (noch?) nicht noetig. die region als - * parameter ist nur deswegen wichtig, weil er an getunit () - * weitergegeben wird. dies wird fuer das auffinden von tempunits in - * getnewunit () verwendet! */ - unit *u2; - region *r = u->region; + /* unit u kontaktiert unit u2. Dies setzt den contact einfach auf 1 - + * ein richtiger toggle ist (noch?) nicht noetig. die region als + * parameter ist nur deswegen wichtig, weil er an getunit () + * weitergegeben wird. dies wird fuer das auffinden von tempunits in + * getnewunit () verwendet! */ + unit *u2; + region *r = u->region; - init_tokens(ord); - skip_token(); - u2 = getunitg(r, u->faction); + init_tokens(ord); + skip_token(); + u2 = getunitg(r, u->faction); - if (u2 != NULL) { - if (!can_contact(r, u, u2)) { - cmistake(u, u->thisorder, 23, MSG_EVENT); - return -1; + if (u2 != NULL) { + if (!can_contact(r, u, u2)) { + cmistake(u, u->thisorder, 23, MSG_EVENT); + return -1; + } + usetcontact(u, u2); } - usetcontact(u, u2); - } - return 0; + return 0; } int leave_cmd(unit * u, struct order *ord) { - region *r = u->region; + region *r = u->region; - if (fval(u, UFL_ENTER)) { - /* if we just entered this round, then we don't leave again */ + if (fval(u, UFL_ENTER)) { + /* if we just entered this round, then we don't leave again */ + return 0; + } + + if (fval(r->terrain, SEA_REGION) && u->ship) { + if (!fval(u_race(u), RCF_SWIM)) { + cmistake(u, ord, 11, MSG_MOVE); + return 0; + } + if (has_horses(u)) { + cmistake(u, ord, 231, MSG_MOVE); + return 0; + } + } + if (!slipthru(r, u, u->building)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "entrance_besieged", + "building", u->building)); + } + else { + leave(u, true); + } return 0; - } - - if (fval(r->terrain, SEA_REGION) && u->ship) { - if (!fval(u_race(u), RCF_SWIM)) { - cmistake(u, ord, 11, MSG_MOVE); - return 0; - } - if (has_horses(u)) { - cmistake(u, ord, 231, MSG_MOVE); - return 0; - } - } - if (!slipthru(r, u, u->building)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "entrance_besieged", - "building", u->building)); - } else { - leave(u, true); - } - return 0; } static bool EnhancedQuit(void) { - static int value = -1; - if (value < 0) { - const char *str = get_param(global.parameters, "alliance.transferquit"); - value = (str != 0 && strcmp(str, "true") == 0); - } - return value; + static int value = -1; + if (value < 0) { + const char *str = get_param(global.parameters, "alliance.transferquit"); + value = (str != 0 && strcmp(str, "true") == 0); + } + return value; } int quit_cmd(unit * u, struct order *ord) { - faction *f = u->faction; - const char *passwd; + faction *f = u->faction; + const char *passwd; - init_tokens(ord); - skip_token(); /* skip keyword */ + init_tokens(ord); + skip_token(); /* skip keyword */ - passwd = getstrtoken(); - if (checkpasswd(f, (const char *)passwd, false)) { - if (EnhancedQuit()) { - int f2_id = getid(); - if (f2_id > 0) { - faction *f2 = findfaction(f2_id); + passwd = getstrtoken(); + if (checkpasswd(f, (const char *)passwd, false)) { + if (EnhancedQuit()) { + int f2_id = getid(); + if (f2_id > 0) { + faction *f2 = findfaction(f2_id); - if (f2 == NULL) { - cmistake(u, ord, 66, MSG_EVENT); - return 0; - } else if (!u->faction->alliance - || u->faction->alliance != f2->alliance) { - cmistake(u, ord, 315, MSG_EVENT); - return 0; - } else if (!alliedfaction(NULL, f, f2, HELP_MONEY)) { - cmistake(u, ord, 316, MSG_EVENT); - return 0; - } else { - variant var; - var.i = f2_id; - a_add(&f->attribs, object_create("quit", TINTEGER, var)); + if (f2 == NULL) { + cmistake(u, ord, 66, MSG_EVENT); + return 0; + } + else if (!u->faction->alliance + || u->faction->alliance != f2->alliance) { + cmistake(u, ord, 315, MSG_EVENT); + return 0; + } + else if (!alliedfaction(NULL, f, f2, HELP_MONEY)) { + cmistake(u, ord, 316, MSG_EVENT); + return 0; + } + else { + variant var; + var.i = f2_id; + a_add(&f->attribs, object_create("quit", TINTEGER, var)); + } + } } - } + fset(f, FFL_QUIT); } - fset(f, FFL_QUIT); - } else { - char buffer[64]; - write_order(ord, buffer, sizeof(buffer)); - cmistake(u, ord, 86, MSG_EVENT); - log_warning("QUIT with illegal password for faction %s: %s\n", factionid(f), buffer); - } - return 0; + else { + char buffer[64]; + write_order(ord, buffer, sizeof(buffer)); + cmistake(u, ord, 86, MSG_EVENT); + log_warning("QUIT with illegal password for faction %s: %s\n", factionid(f), buffer); + } + return 0; } static bool mayenter(region * r, unit * u, building * b) { - unit *u2; - if (fval(b, BLD_UNGUARDED)) - return true; - u2 = building_owner(b); + unit *u2; + if (fval(b, BLD_UNGUARDED)) + return true; + u2 = building_owner(b); - if (u2 == NULL || ucontact(u2, u) - || alliedunit(u2, u->faction, HELP_GUARD)) - return true; + if (u2 == NULL || ucontact(u2, u) + || alliedunit(u2, u->faction, HELP_GUARD)) + return true; - return false; + return false; } static int mayboard(const unit * u, ship * sh) { - unit *u2 = ship_owner(sh); + unit *u2 = ship_owner(sh); - return (!u2 || ucontact(u2, u) || alliedunit(u2, u->faction, HELP_GUARD)); + return (!u2 || ucontact(u2, u) || alliedunit(u2, u->faction, HELP_GUARD)); } static bool CheckOverload(void) { - static int value = -1; - if (value < 0) { - value = get_param_int(global.parameters, "rules.check_overload", 0); - } - return value; + static int value = -1; + if (value < 0) { + value = get_param_int(global.parameters, "rules.check_overload", 0); + } + return value; } int enter_ship(unit * u, struct order *ord, int id, int report) { - region *r = u->region; - ship *sh; + region *r = u->region; + ship *sh; - /* Muss abgefangen werden, sonst koennten Schwimmer an - * Bord von Schiffen an Land gelangen. */ - if (!fval(u_race(u), RCF_CANSAIL) || (!fval(u_race(u), RCF_WALK) - && !fval(u_race(u), RCF_FLY))) { - cmistake(u, ord, 233, MSG_MOVE); - return 0; - } - - sh = findship(id); - if (sh == NULL || sh->region != r) { - if (report) - cmistake(u, ord, 20, MSG_MOVE); - return 0; - } - if (sh == u->ship) { - return 1; - } - if (!mayboard(u, sh)) { - if (report) - cmistake(u, ord, 34, MSG_MOVE); - return 0; - } - if (CheckOverload()) { - int sweight, scabins; - int mweight = shipcapacity(sh); - int mcabins = sh->type->cabins; - - if (mweight > 0) { - getshipweight(sh, &sweight, &scabins); - sweight += weight(u); - if (mcabins) { - int pweight = u->number * u_race(u)->weight; - /* weight goes into number of cabins, not cargo */ - scabins += pweight; - sweight -= pweight; - } - - if (sweight > mweight || (mcabins && (scabins > mcabins))) { - if (report) - cmistake(u, ord, 34, MSG_MOVE); + /* Muss abgefangen werden, sonst koennten Schwimmer an + * Bord von Schiffen an Land gelangen. */ + if (!fval(u_race(u), RCF_CANSAIL) || (!fval(u_race(u), RCF_WALK) + && !fval(u_race(u), RCF_FLY))) { + cmistake(u, ord, 233, MSG_MOVE); return 0; - } } - } - if (leave(u, false)) { - u_set_ship(u, sh); - fset(u, UFL_ENTER); - return 1; - } else if (report) { - cmistake(u, ord, 150, MSG_MOVE); - } - return 0; + sh = findship(id); + if (sh == NULL || sh->region != r) { + if (report) + cmistake(u, ord, 20, MSG_MOVE); + return 0; + } + if (sh == u->ship) { + return 1; + } + if (!mayboard(u, sh)) { + if (report) + cmistake(u, ord, 34, MSG_MOVE); + return 0; + } + if (CheckOverload()) { + int sweight, scabins; + int mweight = shipcapacity(sh); + int mcabins = sh->type->cabins; + + if (mweight > 0) { + getshipweight(sh, &sweight, &scabins); + sweight += weight(u); + if (mcabins) { + int pweight = u->number * u_race(u)->weight; + /* weight goes into number of cabins, not cargo */ + scabins += pweight; + sweight -= pweight; + } + + if (sweight > mweight || (mcabins && (scabins > mcabins))) { + if (report) + cmistake(u, ord, 34, MSG_MOVE); + return 0; + } + } + } + + if (leave(u, false)) { + u_set_ship(u, sh); + fset(u, UFL_ENTER); + return 1; + } + else if (report) { + cmistake(u, ord, 150, MSG_MOVE); + } + return 0; } int enter_building(unit * u, order * ord, int id, int report) { - region *r = u->region; - building *b; + region *r = u->region; + building *b; - /* Schwimmer können keine Gebäude betreten, außer diese sind - * auf dem Ozean */ - if (!fval(u_race(u), RCF_WALK) && !fval(u_race(u), RCF_FLY)) { - if (!fval(r->terrain, SEA_REGION)) { - if (report) { - cmistake(u, ord, 232, MSG_MOVE); - } - return 0; + /* Schwimmer können keine Gebäude betreten, außer diese sind + * auf dem Ozean */ + if (!fval(u_race(u), RCF_WALK) && !fval(u_race(u), RCF_FLY)) { + if (!fval(r->terrain, SEA_REGION)) { + if (report) { + cmistake(u, ord, 232, MSG_MOVE); + } + return 0; + } } - } - b = findbuilding(id); - if (b == NULL || b->region != r) { - if (report) { - cmistake(u, ord, 6, MSG_MOVE); + b = findbuilding(id); + if (b == NULL || b->region != r) { + if (report) { + cmistake(u, ord, 6, MSG_MOVE); + } + return 0; + } + if (!mayenter(r, u, b)) { + if (report) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_denied", + "building", b)); + } + return 0; + } + if (!slipthru(r, u, b)) { + if (report) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_besieged", + "building", b)); + } + return 0; + } + + if (leave(u, 0)) { + fset(u, UFL_ENTER); + u_set_building(u, b); + return 1; + } + else if (report) { + cmistake(u, ord, 150, MSG_MOVE); } return 0; - } - if (!mayenter(r, u, b)) { - if (report) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_denied", - "building", b)); - } - return 0; - } - if (!slipthru(r, u, b)) { - if (report) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_besieged", - "building", b)); - } - return 0; - } - - if (leave(u, 0)) { - fset(u, UFL_ENTER); - u_set_building(u, b); - return 1; - } else if (report) { - cmistake(u, ord, 150, MSG_MOVE); - } - return 0; } static void do_contact(region * r) { - unit * u; - for (u = r->units; u; u = u->next) { - order *ord; - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_CONTACT) { - contact_cmd(u, ord); - } + unit * u; + for (u = r->units; u; u = u->next) { + order *ord; + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_CONTACT) { + contact_cmd(u, ord); + } + } } - } } void do_enter(struct region *r, bool is_final_attempt) { - unit **uptr; + unit **uptr; - for (uptr = &r->units; *uptr;) { - unit *u = *uptr; - order **ordp = &u->orders; + for (uptr = &r->units; *uptr;) { + unit *u = *uptr; + order **ordp = &u->orders; - while (*ordp) { - order *ord = *ordp; - if (getkeyword(ord) == K_ENTER) { - param_t p; - int id; - unit *ulast = NULL; - const char * s; + while (*ordp) { + order *ord = *ordp; + if (getkeyword(ord) == K_ENTER) { + param_t p; + int id; + unit *ulast = NULL; + const char * s; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - p = findparam_ex(s, u->faction->locale); - id = getid(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); + p = findparam_ex(s, u->faction->locale); + id = getid(); - switch (p) { - case P_BUILDING: - case P_GEBAEUDE: - if (u->building && u->building->no == id) - break; - if (enter_building(u, ord, id, is_final_attempt)) { - unit *ub; - for (ub = u; ub; ub = ub->next) { - if (ub->building == u->building) { - ulast = ub; - } + switch (p) { + case P_BUILDING: + case P_GEBAEUDE: + if (u->building && u->building->no == id) + break; + if (enter_building(u, ord, id, is_final_attempt)) { + unit *ub; + for (ub = u; ub; ub = ub->next) { + if (ub->building == u->building) { + ulast = ub; + } + } + } + break; + + case P_SHIP: + if (u->ship && u->ship->no == id) + break; + if (enter_ship(u, ord, id, is_final_attempt)) { + unit *ub; + ulast = u; + for (ub = u; ub; ub = ub->next) { + if (ub->ship == u->ship) { + ulast = ub; + } + } + } + break; + + default: + if (is_final_attempt) { + cmistake(u, ord, 79, MSG_MOVE); + } + } + if (ulast != NULL) { + /* Wenn wir hier angekommen sind, war der Befehl + * erfolgreich und wir löschen ihn, damit er im + * zweiten Versuch nicht nochmal ausgeführt wird. */ + *ordp = ord->next; + ord->next = NULL; + free_order(ord); + + if (ulast != u) { + /* put u behind ulast so it's the last unit in the building */ + *uptr = u->next; + u->next = ulast->next; + ulast->next = u; + } + break; + } } - } - break; - - case P_SHIP: - if (u->ship && u->ship->no == id) - break; - if (enter_ship(u, ord, id, is_final_attempt)) { - unit *ub; - ulast = u; - for (ub = u; ub; ub = ub->next) { - if (ub->ship == u->ship) { - ulast = ub; - } - } - } - break; - - default: - if (is_final_attempt) { - cmistake(u, ord, 79, MSG_MOVE); - } + if (*ordp == ord) + ordp = &ord->next; } - if (ulast != NULL) { - /* Wenn wir hier angekommen sind, war der Befehl - * erfolgreich und wir löschen ihn, damit er im - * zweiten Versuch nicht nochmal ausgeführt wird. */ - *ordp = ord->next; - ord->next = NULL; - free_order(ord); - - if (ulast != u) { - /* put u behind ulast so it's the last unit in the building */ - *uptr = u->next; - u->next = ulast->next; - ulast->next = u; - } - break; - } - } - if (*ordp == ord) - ordp = &ord->next; + if (*uptr == u) + uptr = &u->next; } - if (*uptr == u) - uptr = &u->next; - } } int dropouts[2]; @@ -1414,103 +1429,104 @@ int *age = NULL; static void nmr_death(faction * f) { - static int rule = -1; - if (rule < 0) - rule = get_param_int(global.parameters, "rules.nmr.destroy", 0); - if (rule) { - unit *u; - for (u = f->units; u; u = u->nextF) { - if (u->building && building_owner(u->building)==u) { - remove_building(&u->region->buildings, u->building); - } + static int rule = -1; + if (rule < 0) + rule = get_param_int(global.parameters, "rules.nmr.destroy", 0); + if (rule) { + unit *u; + for (u = f->units; u; u = u->nextF) { + if (u->building && building_owner(u->building) == u) { + remove_building(&u->region->buildings, u->building); + } + } } - } } static void remove_idle_players(void) { - faction *f; + faction *f; - log_info(" - beseitige Spieler, die sich zu lange nicht mehr gemeldet haben..."); + log_info(" - beseitige Spieler, die sich zu lange nicht mehr gemeldet haben..."); - for (f = factions; f; f = f->next) { - if (fval(f, FFL_NOIDLEOUT)) { - f->lastorders = turn; - } - if (NMRTimeout() > 0 && turn - f->lastorders >= NMRTimeout()) { - nmr_death(f); - destroyfaction(f); - continue; - } - if (turn != f->lastorders) { - char info[256]; - sprintf(info, "%d Einheiten, %d Personen, %d Silber", - f->no_units, f->num_total, f->money); - } - - if (NMRTimeout() > 0 && turn - f->lastorders >= (NMRTimeout() - 1)) { - inactivefaction(f); - continue; - } - } - log_info(" - beseitige Spieler, die sich nach der Anmeldung nicht gemeldet haben..."); - - age = calloc(_max(4, turn + 1), sizeof(int)); - for (f = factions; f; f = f->next) - if (!is_monsters(f)) { - if (RemoveNMRNewbie() && !fval(f, FFL_NOIDLEOUT)) { - if (f->age >= 0 && f->age <= turn) - ++age[f->age]; - if (f->age == 2 || f->age == 3) { - if (f->lastorders == turn - 2) { - destroyfaction(f); - ++dropouts[f->age - 2]; - continue; - } + for (f = factions; f; f = f->next) { + if (fval(f, FFL_NOIDLEOUT)) { + f->lastorders = turn; + } + if (NMRTimeout() > 0 && turn - f->lastorders >= NMRTimeout()) { + nmr_death(f); + destroyfaction(f); + continue; + } + if (turn != f->lastorders) { + char info[256]; + sprintf(info, "%d Einheiten, %d Personen, %d Silber", + f->no_units, f->num_total, f->money); + } + + if (NMRTimeout() > 0 && turn - f->lastorders >= (NMRTimeout() - 1)) { + inactivefaction(f); + continue; } - } } + log_info(" - beseitige Spieler, die sich nach der Anmeldung nicht gemeldet haben..."); + + age = calloc(_max(4, turn + 1), sizeof(int)); + for (f = factions; f; f = f->next) + if (!is_monsters(f)) { + if (RemoveNMRNewbie() && !fval(f, FFL_NOIDLEOUT)) { + if (f->age >= 0 && f->age <= turn) + ++age[f->age]; + if (f->age == 2 || f->age == 3) { + if (f->lastorders == turn - 2) { + destroyfaction(f); + ++dropouts[f->age - 2]; + continue; + } + } + } + } } void quit(void) { - faction **fptr = &factions; - while (*fptr) { - faction *f = *fptr; - if (f->flags & FFL_QUIT) { - if (EnhancedQuit()) { - /* this doesn't work well (use object_name()) */ - attrib *a = a_find(f->attribs, &at_object); - if (a) { - variant var; - object_type type; - var.i = 0; - object_get(a, &type, &var); - assert(var.i && type == TINTEGER); - if (var.i) { - int f2_id = var.i; - faction *f2 = findfaction(f2_id); + faction **fptr = &factions; + while (*fptr) { + faction *f = *fptr; + if (f->flags & FFL_QUIT) { + if (EnhancedQuit()) { + /* this doesn't work well (use object_name()) */ + attrib *a = a_find(f->attribs, &at_object); + if (a) { + variant var; + object_type type; + var.i = 0; + object_get(a, &type, &var); + assert(var.i && type == TINTEGER); + if (var.i) { + int f2_id = var.i; + faction *f2 = findfaction(f2_id); - assert(f2_id > 0); - assert(f2 != NULL); - transfer_faction(f, f2); - } + assert(f2_id > 0); + assert(f2 != NULL); + transfer_faction(f, f2); + } + } + } + destroyfaction(f); + } + else { + ++f->age; + if (f->age + 1 < NewbieImmunity()) { + ADDMSG(&f->msgs, msg_message("newbieimmunity", "turns", + NewbieImmunity() - f->age - 1)); + } + } + if (*fptr == f) { + fptr = &f->next; } - } - destroyfaction(f); - } else { - ++f->age; - if (f->age + 1 < NewbieImmunity()) { - ADDMSG(&f->msgs, msg_message("newbieimmunity", "turns", - NewbieImmunity() - f->age - 1)); - } } - if (*fptr == f) { - fptr = &f->next; - } - } - remove_idle_players(); - remove_empty_units(); + remove_idle_players(); + remove_empty_units(); } /* ------------------------------------------------------------- */ @@ -1519,590 +1535,608 @@ void quit(void) int ally_cmd(unit * u, struct order *ord) { - ally *sf, **sfp; - faction *f; - int keyword, not_kw; - const char *s; + ally *sf, **sfp; + faction *f; + int keyword, not_kw; + const char *s; - init_tokens(ord); - skip_token(); - f = getfaction(); + init_tokens(ord); + skip_token(); + f = getfaction(); - if (f == NULL || is_monsters(f)) { - cmistake(u, ord, 66, MSG_EVENT); - return 0; - } - if (f == u->faction) - return 0; - - s = getstrtoken(); - - if (!s[0]) - keyword = P_ANY; - else - keyword = findparam(s, u->faction->locale); - - sfp = &u->faction->allies; - if (fval(u, UFL_GROUP)) { - attrib *a = a_find(u->attribs, &at_group); - if (a) - sfp = &((group *) a->data.v)->allies; - } - for (sf = *sfp; sf; sf = sf->next) - if (sf->faction == f) - break; /* Gleich die passende raussuchen, wenn vorhanden */ - - not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */ - - if (!sf) { - if (keyword == P_NOT || not_kw == P_NOT) { - /* Wir helfen der Partei gar nicht... */ - return 0; - } else { - sf = calloc(1, sizeof(ally)); - sf->faction = f; - sf->status = 0; - addlist(sfp, sf); + if (f == NULL || is_monsters(f)) { + cmistake(u, ord, 66, MSG_EVENT); + return 0; } - } - switch (keyword) { - case P_NOT: - sf->status = 0; - break; + if (f == u->faction) + return 0; - case NOPARAM: - cmistake(u, ord, 137, MSG_EVENT); + s = getstrtoken(); + + if (!s[0]) + keyword = P_ANY; + else + keyword = findparam(s, u->faction->locale); + + sfp = &u->faction->allies; + if (fval(u, UFL_GROUP)) { + attrib *a = a_find(u->attribs, &at_group); + if (a) + sfp = &((group *)a->data.v)->allies; + } + for (sf = *sfp; sf; sf = sf->next) + if (sf->faction == f) + break; /* Gleich die passende raussuchen, wenn vorhanden */ + + not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */ + + if (!sf) { + if (keyword == P_NOT || not_kw == P_NOT) { + /* Wir helfen der Partei gar nicht... */ + return 0; + } + else { + sf = calloc(1, sizeof(ally)); + sf->faction = f; + sf->status = 0; + addlist(sfp, sf); + } + } + switch (keyword) { + case P_NOT: + sf->status = 0; + break; + + case NOPARAM: + cmistake(u, ord, 137, MSG_EVENT); + return 0; + + case P_ANY: + if (not_kw == P_NOT) + sf->status = 0; + else + sf->status = HELP_ALL; + break; + + case P_TRAVEL: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_TRAVEL); + else + sf->status = sf->status | HELP_TRAVEL; + break; + + case P_GIVE: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_GIVE); + else + sf->status = sf->status | HELP_GIVE; + break; + + case P_MONEY: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_MONEY); + else + sf->status = sf->status | HELP_MONEY; + break; + + case P_FIGHT: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_FIGHT); + else + sf->status = sf->status | HELP_FIGHT; + break; + + case P_FACTIONSTEALTH: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH); + else + sf->status = sf->status | HELP_FSTEALTH; + break; + + case P_GUARD: + if (not_kw == P_NOT) + sf->status = sf->status & (HELP_ALL - HELP_GUARD); + else + sf->status = sf->status | HELP_GUARD; + break; + } + + sf->status &= HelpMask(); + + if (sf->status == 0) { /* Alle HELPs geloescht */ + removelist(sfp, sf); + } return 0; - - case P_ANY: - if (not_kw == P_NOT) - sf->status = 0; - else - sf->status = HELP_ALL; - break; - - case P_TRAVEL: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_TRAVEL); - else - sf->status = sf->status | HELP_TRAVEL; - break; - - case P_GIVE: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_GIVE); - else - sf->status = sf->status | HELP_GIVE; - break; - - case P_MONEY: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_MONEY); - else - sf->status = sf->status | HELP_MONEY; - break; - - case P_FIGHT: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_FIGHT); - else - sf->status = sf->status | HELP_FIGHT; - break; - - case P_FACTIONSTEALTH: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH); - else - sf->status = sf->status | HELP_FSTEALTH; - break; - - case P_GUARD: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_GUARD); - else - sf->status = sf->status | HELP_GUARD; - break; - } - - sf->status &= HelpMask(); - - if (sf->status == 0) { /* Alle HELPs geloescht */ - removelist(sfp, sf); - } - return 0; } static struct local_names *pnames; static void init_prefixnames(void) { - int i; - for (i = 0; localenames[i]; ++i) { - const struct locale *lang = get_locale(localenames[i]); - bool exist = false; - struct local_names *in = pnames; + int i; + for (i = 0; localenames[i]; ++i) { + const struct locale *lang = get_locale(localenames[i]); + bool exist = false; + struct local_names *in = pnames; - while (in != NULL) { - if (in->lang == lang) { - exist = true; - break; - } - in = in->next; - } - if (in == NULL) - in = calloc(sizeof(local_names), 1); - in->next = pnames; - in->lang = lang; - - if (!exist) { - int key; - for (key = 0; race_prefixes[key]; ++key) { - variant var; - const char *pname = - locale_string(lang, mkname("prefix", race_prefixes[key])); - if (findtoken(in->names, pname, &var) == E_TOK_NOMATCH || var.i != key) { - var.i = key; - addtoken(&in->names, pname, var); - addtoken(&in->names, locale_string(lang, mkname("prefix", - race_prefixes[key])), var); + while (in != NULL) { + if (in->lang == lang) { + exist = true; + break; + } + in = in->next; } - } + if (in == NULL) + in = calloc(sizeof(local_names), 1); + in->next = pnames; + in->lang = lang; + + if (!exist) { + int key; + for (key = 0; race_prefixes[key]; ++key) { + variant var; + const char *pname = + locale_string(lang, mkname("prefix", race_prefixes[key])); + if (findtoken(in->names, pname, &var) == E_TOK_NOMATCH || var.i != key) { + var.i = key; + addtoken(&in->names, pname, var); + addtoken(&in->names, locale_string(lang, mkname("prefix", + race_prefixes[key])), var); + } + } + } + pnames = in; } - pnames = in; - } } int prefix_cmd(unit * u, struct order *ord) { - attrib **ap; - const char *s; - local_names *in = pnames; - variant var; - const struct locale *lang = u->faction->locale; + attrib **ap; + const char *s; + local_names *in = pnames; + variant var; + const struct locale *lang = u->faction->locale; - while (in != NULL) { - if (in->lang == lang) - break; - in = in->next; - } - if (in == NULL) { - init_prefixnames(); - for (in = pnames; in->lang != lang; in = in->next) ; - } - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - if (!*s) { - attrib *a = NULL; - if (fval(u, UFL_GROUP)) { - a = a_find(u->attribs, &at_group); + while (in != NULL) { + if (in->lang == lang) + break; + in = in->next; } - if (a) { - group *g = (group *) a->data.v; - a_removeall(&g->attribs, &at_raceprefix); - } else { - a_removeall(&u->faction->attribs, &at_raceprefix); + if (in == NULL) { + init_prefixnames(); + for (in = pnames; in->lang != lang; in = in->next); + } + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + + if (!*s) { + attrib *a = NULL; + if (fval(u, UFL_GROUP)) { + a = a_find(u->attribs, &at_group); + } + if (a) { + group *g = (group *)a->data.v; + a_removeall(&g->attribs, &at_raceprefix); + } + else { + a_removeall(&u->faction->attribs, &at_raceprefix); + } + return 0; + } + + if (findtoken(in->names, s, &var) == E_TOK_NOMATCH) { + return 0; + } + else if (race_prefixes[var.i] == NULL) { + cmistake(u, ord, 299, MSG_EVENT); + } + else { + ap = &u->faction->attribs; + if (fval(u, UFL_GROUP)) { + attrib *a = a_find(u->attribs, &at_group); + group *g = (group *)a->data.v; + if (a) + ap = &g->attribs; + } + set_prefix(ap, race_prefixes[var.i]); } return 0; - } - - if (findtoken(in->names, s, &var) == E_TOK_NOMATCH) { - return 0; - } else if (race_prefixes[var.i] == NULL) { - cmistake(u, ord, 299, MSG_EVENT); - } else { - ap = &u->faction->attribs; - if (fval(u, UFL_GROUP)) { - attrib *a = a_find(u->attribs, &at_group); - group *g = (group *) a->data.v; - if (a) - ap = &g->attribs; - } - set_prefix(ap, race_prefixes[var.i]); - } - return 0; } static cmp_building_cb get_cmp_region_owner(void) { - if (rule_region_owners()) { - return &cmp_current_owner; - } else { - return &cmp_wage; - } + if (rule_region_owners()) { + return &cmp_current_owner; + } + else { + return &cmp_wage; + } } int display_cmd(unit * u, struct order *ord) { - char **s = NULL; - const char *str; - region *r = u->region; + char **s = NULL; + const char *str; + region *r = u->region; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - str = getstrtoken(); - switch (findparam_ex(str, u->faction->locale)) { - case P_BUILDING: - case P_GEBAEUDE: - if (!u->building) { - cmistake(u, ord, 145, MSG_PRODUCE); - break; - } - if (building_owner(u->building)!=u) { - cmistake(u, ord, 5, MSG_PRODUCE); - break; - } - if (!fval(u->building->type, BTF_NAMECHANGE) && u->building->display && u->building->display[0]) { - cmistake(u, ord, 278, MSG_EVENT); - break; - } - s = &u->building->display; - break; + str = getstrtoken(); + switch (findparam_ex(str, u->faction->locale)) { + case P_BUILDING: + case P_GEBAEUDE: + if (!u->building) { + cmistake(u, ord, 145, MSG_PRODUCE); + break; + } + if (building_owner(u->building) != u) { + cmistake(u, ord, 5, MSG_PRODUCE); + break; + } + if (!fval(u->building->type, BTF_NAMECHANGE) && u->building->display && u->building->display[0]) { + cmistake(u, ord, 278, MSG_EVENT); + break; + } + s = &u->building->display; + break; - case P_SHIP: - if (!u->ship) { - cmistake(u, ord, 144, MSG_PRODUCE); - break; - } - if (ship_owner(u->ship)!=u) { - cmistake(u, ord, 12, MSG_PRODUCE); - break; - } - s = &u->ship->display; - break; + case P_SHIP: + if (!u->ship) { + cmistake(u, ord, 144, MSG_PRODUCE); + break; + } + if (ship_owner(u->ship) != u) { + cmistake(u, ord, 12, MSG_PRODUCE); + break; + } + s = &u->ship->display; + break; - case P_UNIT: - s = &u->display; - break; + case P_UNIT: + s = &u->display; + break; - case P_PRIVAT: - { - const char *d = getstrtoken(); - if (d == NULL || *d == 0) { - usetprivate(u, NULL); - } else { - usetprivate(u, d); + case P_PRIVAT: + { + const char *d = getstrtoken(); + if (d == NULL || *d == 0) { + usetprivate(u, NULL); + } + else { + usetprivate(u, d); + } } - } - break; + break; - case P_REGION: - if (!u->building) { - cmistake(u, ord, 145, MSG_EVENT); - break; + case P_REGION: + if (!u->building) { + cmistake(u, ord, 145, MSG_EVENT); + break; + } + if (building_owner(u->building) != u) { + cmistake(u, ord, 148, MSG_EVENT); + break; + } + if (u->building != largestbuilding(r, get_cmp_region_owner(), false)) { + cmistake(u, ord, 147, MSG_EVENT); + break; + } + s = &r->display; + break; + + default: + cmistake(u, ord, 110, MSG_EVENT); + break; } - if (building_owner(u->building)!=u) { - cmistake(u, ord, 148, MSG_EVENT); - break; + + if (s != NULL) { + const char *s2 = getstrtoken(); + + free(*s); + *s = _strdup(s2); + if (strlen(s2) >= DISPLAYSIZE) { + (*s)[DISPLAYSIZE] = 0; + } } - if (u->building != largestbuilding(r, get_cmp_region_owner(), false)) { - cmistake(u, ord, 147, MSG_EVENT); - break; - } - s = &r->display; - break; - default: - cmistake(u, ord, 110, MSG_EVENT); - break; - } - - if (s != NULL) { - const char *s2 = getstrtoken(); - - free(*s); - *s = _strdup(s2); - if (strlen(s2) >= DISPLAYSIZE) { - (*s)[DISPLAYSIZE] = 0; - } - } - - return 0; + return 0; } bool renamed_building(const building * b) { - const struct locale *lang = locales; - size_t len = strlen(b->name); - for (; lang; lang = nextlocale(lang)) { - const char *bdname = LOC(lang, b->type->_name); - if (bdname) { - size_t bdlen = strlen(bdname); - if (len >= bdlen && strncmp(b->name, bdname, bdlen) == 0) { - return false; - } + const struct locale *lang = locales; + size_t len = strlen(b->name); + for (; lang; lang = nextlocale(lang)) { + const char *bdname = LOC(lang, b->type->_name); + if (bdname) { + size_t bdlen = strlen(bdname); + if (len >= bdlen && strncmp(b->name, bdname, bdlen) == 0) { + return false; + } + } } - } - return true; + return true; } static int rename_cmd(unit * u, order * ord, char **s, const char *s2) { - if (!s2[0]) { - cmistake(u, ord, 84, MSG_EVENT); + if (!s2[0]) { + cmistake(u, ord, 84, MSG_EVENT); + return 0; + } + + /* TODO: Validate to make sure people don't have illegal characters in + * names, phishing-style? () come to mind. */ + + free(*s); + *s = _strdup(s2); + if (strlen(s2) >= NAMESIZE) { + (*s)[NAMESIZE] = 0; + } return 0; - } - - /* TODO: Validate to make sure people don't have illegal characters in - * names, phishing-style? () come to mind. */ - - free(*s); - *s = _strdup(s2); - if (strlen(s2) >= NAMESIZE) { - (*s)[NAMESIZE] = 0; - } - return 0; } int rename_building(unit * u, order * ord, building * b, const char *name) { - unit *owner = b ? building_owner(b) : 0; - bool foreign = !(owner && owner->faction == u->faction); + unit *owner = b ? building_owner(b) : 0; + bool foreign = !(owner && owner->faction == u->faction); - if (!b) { - cmistake(u, ord, u->building ? 6 : 145, MSG_EVENT); - return -1; - } - - if (!fval(b->type, BTF_NAMECHANGE) && renamed_building(b)) { - cmistake(u, ord, 278, MSG_EVENT); - return -1; - } - - if (foreign) { - if (renamed_building(b)) { - cmistake(u, ord, 246, MSG_EVENT); - return -1; + if (!b) { + cmistake(u, ord, u->building ? 6 : 145, MSG_EVENT); + return -1; } - if (owner) { - if (cansee(owner->faction, u->region, u, 0)) { - ADDMSG(&owner->faction->msgs, - msg_message("renamed_building_seen", - "building renamer region", b, u, u->region)); - } else { - ADDMSG(&owner->faction->msgs, - msg_message("renamed_building_notseen", - "building region", b, u->region)); - } + if (!fval(b->type, BTF_NAMECHANGE) && renamed_building(b)) { + cmistake(u, ord, 278, MSG_EVENT); + return -1; } - } else { - if (owner!=u) { - cmistake(u, ord, 148, MSG_PRODUCE); - return -1; - } - } - return rename_cmd(u, ord, &b->name, name); + if (foreign) { + if (renamed_building(b)) { + cmistake(u, ord, 246, MSG_EVENT); + return -1; + } + + if (owner) { + if (cansee(owner->faction, u->region, u, 0)) { + ADDMSG(&owner->faction->msgs, + msg_message("renamed_building_seen", + "building renamer region", b, u, u->region)); + } + else { + ADDMSG(&owner->faction->msgs, + msg_message("renamed_building_notseen", + "building region", b, u->region)); + } + } + } + else { + if (owner != u) { + cmistake(u, ord, 148, MSG_PRODUCE); + return -1; + } + } + + return rename_cmd(u, ord, &b->name, name); } int name_cmd(struct unit *u, struct order *ord) { - building *b = u->building; - region *r = u->region; - char **s = NULL; - param_t p; - bool foreign = false; - const char *str; + building *b = u->building; + region *r = u->region; + char **s = NULL; + param_t p; + bool foreign = false; + const char *str; - init_tokens(ord); - skip_token(); - str = getstrtoken(); - p = findparam_ex(str, u->faction->locale); - - if (p == P_FOREIGN) { + init_tokens(ord); + skip_token(); str = getstrtoken(); - foreign = true; p = findparam_ex(str, u->faction->locale); - } - switch (p) { - case P_ALLIANCE: - if (!foreign && f_get_alliance(u->faction)) { - alliance *al = u->faction->alliance; - faction *lead = alliance_get_leader(al); - if (lead == u->faction) { - s = &al->name; - } - } - break; - case P_BUILDING: - case P_GEBAEUDE: - if (foreign) { - b = getbuilding(u->region); + if (p == P_FOREIGN) { + str = getstrtoken(); + foreign = true; + p = findparam_ex(str, u->faction->locale); } - return rename_building(u, ord, b, getstrtoken()); - - case P_FACTION: - if (foreign) { - faction *f; - - f = getfaction(); - if (!f) { - cmistake(u, ord, 66, MSG_EVENT); + switch (p) { + case P_ALLIANCE: + if (!foreign && f_get_alliance(u->faction)) { + alliance *al = u->faction->alliance; + faction *lead = alliance_get_leader(al); + if (lead == u->faction) { + s = &al->name; + } + } break; - } - if (f->age < 10) { - cmistake(u, ord, 248, MSG_EVENT); + case P_BUILDING: + case P_GEBAEUDE: + if (foreign) { + b = getbuilding(u->region); + } + + return rename_building(u, ord, b, getstrtoken()); + + case P_FACTION: + if (foreign) { + faction *f; + + f = getfaction(); + if (!f) { + cmistake(u, ord, 66, MSG_EVENT); + break; + } + if (f->age < 10) { + cmistake(u, ord, 248, MSG_EVENT); + break; + } + else { + const struct locale *lang = locales; + for (; lang; lang = nextlocale(lang)) { + const char *fdname = LOC(lang, "factiondefault"); + size_t fdlen = strlen(fdname); + if (strlen(f->name) >= fdlen && strncmp(f->name, fdname, fdlen) == 0) { + break; + } + } + if (lang == NULL) { + cmistake(u, ord, 247, MSG_EVENT); + break; + } + } + if (cansee(f, r, u, 0)) { + ADDMSG(&f->msgs, + msg_message("renamed_faction_seen", "unit region", u, r)); + } + else { + ADDMSG(&f->msgs, msg_message("renamed_faction_notseen", "", r)); + } + s = &f->name; + } + else { + s = &u->faction->name; + } break; - } else { - const struct locale *lang = locales; - for (; lang; lang = nextlocale(lang)) { - const char *fdname = LOC(lang, "factiondefault"); - size_t fdlen = strlen(fdname); - if (strlen(f->name) >= fdlen && strncmp(f->name, fdname, fdlen) == 0) { + + case P_SHIP: + if (foreign) { + ship *sh = getship(r); + unit *uo; + + if (!sh) { + cmistake(u, ord, 20, MSG_EVENT); + break; + } + else { + const struct locale *lang = locales; + for (; lang; lang = nextlocale(lang)) { + const char *sdname = LOC(lang, sh->type->_name); + size_t sdlen = strlen(sdname); + if (strlen(sh->name) >= sdlen + && strncmp(sh->name, sdname, sdlen) == 0) { + break; + } + + sdname = LOC(lang, parameters[P_SHIP]); + sdlen = strlen(sdname); + if (strlen(sh->name) >= sdlen + && strncmp(sh->name, sdname, sdlen) == 0) { + break; + } + + } + if (lang == NULL) { + cmistake(u, ord, 245, MSG_EVENT); + break; + } + } + uo = ship_owner(sh); + if (uo) { + if (cansee(uo->faction, r, u, 0)) { + ADDMSG(&uo->faction->msgs, + msg_message("renamed_ship_seen", "ship renamer region", sh, u, r)); + } + else { + ADDMSG(&uo->faction->msgs, + msg_message("renamed_ship_notseen", "ship region", sh, r)); + } + } + s = &sh->name; + } + else { + if (!u->ship) { + cmistake(u, ord, 144, MSG_PRODUCE); + break; + } + if (ship_owner(u->ship) != u) { + cmistake(u, ord, 12, MSG_PRODUCE); + break; + } + s = &u->ship->name; + } + break; + + case P_UNIT: + if (foreign) { + unit *u2 = getunit(r, u->faction); + + if (!u2 || !cansee(u->faction, r, u2, 0)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + break; + } + else { + const char *udefault = LOC(u2->faction->locale, "unitdefault"); + size_t udlen = strlen(udefault); + size_t unlen = strlen(u2->name); + if (unlen >= udlen && strncmp(u2->name, udefault, udlen) != 0) { + cmistake(u2, ord, 244, MSG_EVENT); + break; + } + } + if (cansee(u2->faction, r, u, 0)) { + ADDMSG(&u2->faction->msgs, msg_message("renamed_seen", + "renamer renamed region", u, u2, r)); + } + else { + ADDMSG(&u2->faction->msgs, msg_message("renamed_notseen", + "renamed region", u2, r)); + } + s = &u2->name; + } + else { + s = &u->name; + } + break; + + case P_REGION: + if (!b) { + cmistake(u, ord, 145, MSG_EVENT); break; - } } - if (lang == NULL) { - cmistake(u, ord, 247, MSG_EVENT); - break; - } - } - if (cansee(f, r, u, 0)) { - ADDMSG(&f->msgs, - msg_message("renamed_faction_seen", "unit region", u, r)); - } else { - ADDMSG(&f->msgs, msg_message("renamed_faction_notseen", "", r)); - } - s = &f->name; - } else { - s = &u->faction->name; - } - break; - - case P_SHIP: - if (foreign) { - ship *sh = getship(r); - unit *uo; - - if (!sh) { - cmistake(u, ord, 20, MSG_EVENT); - break; - } else { - const struct locale *lang = locales; - for (; lang; lang = nextlocale(lang)) { - const char *sdname = LOC(lang, sh->type->_name); - size_t sdlen = strlen(sdname); - if (strlen(sh->name) >= sdlen - && strncmp(sh->name, sdname, sdlen) == 0) { + if (building_owner(b) != u) { + cmistake(u, ord, 148, MSG_EVENT); break; - } + } - sdname = LOC(lang, parameters[P_SHIP]); - sdlen = strlen(sdname); - if (strlen(sh->name) >= sdlen - && strncmp(sh->name, sdname, sdlen) == 0) { + if (b != largestbuilding(r, get_cmp_region_owner(), false)) { + cmistake(u, ord, 147, MSG_EVENT); break; - } - } - if (lang == NULL) { - cmistake(u, ord, 245, MSG_EVENT); - break; - } - } - uo = ship_owner(sh); - if (uo) { - if (cansee(uo->faction, r, u, 0)) { - ADDMSG(&uo->faction->msgs, - msg_message("renamed_ship_seen", "ship renamer region", sh, u, r)); - } else { - ADDMSG(&uo->faction->msgs, - msg_message("renamed_ship_notseen", "ship region", sh, r)); - } - } - s = &sh->name; - } else { - if (!u->ship) { - cmistake(u, ord, 144, MSG_PRODUCE); + s = &r->land->name; break; - } - if (ship_owner(u->ship)!=u) { - cmistake(u, ord, 12, MSG_PRODUCE); - break; - } - s = &u->ship->name; - } - break; - case P_UNIT: - if (foreign) { - unit *u2 = getunit(r, u->faction); - - if (!u2 || !cansee(u->faction, r, u2, 0)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - break; - } else { - const char *udefault = LOC(u2->faction->locale, "unitdefault"); - size_t udlen = strlen(udefault); - size_t unlen = strlen(u2->name); - if (unlen >= udlen && strncmp(u2->name, udefault, udlen) != 0) { - cmistake(u2, ord, 244, MSG_EVENT); - break; + case P_GROUP: + { + attrib *a = NULL; + if (fval(u, UFL_GROUP)) + a = a_find(u->attribs, &at_group); + if (a) { + group *g = (group *)a->data.v; + s = &g->name; + break; + } + else { + cmistake(u, ord, 109, MSG_EVENT); + break; } - } - if (cansee(u2->faction, r, u, 0)) { - ADDMSG(&u2->faction->msgs, msg_message("renamed_seen", - "renamer renamed region", u, u2, r)); - } else { - ADDMSG(&u2->faction->msgs, msg_message("renamed_notseen", - "renamed region", u2, r)); - } - s = &u2->name; - } else { - s = &u->name; } - break; - - case P_REGION: - if (!b) { - cmistake(u, ord, 145, MSG_EVENT); - break; - } - if (building_owner(b)!=u) { - cmistake(u, ord, 148, MSG_EVENT); - break; + break; + default: + cmistake(u, ord, 109, MSG_EVENT); + break; } - if (b != largestbuilding(r, get_cmp_region_owner(), false)) { - cmistake(u, ord, 147, MSG_EVENT); - break; + if (s != NULL) { + return rename_cmd(u, ord, s, getstrtoken()); } - s = &r->land->name; - break; - case P_GROUP: - { - attrib *a = NULL; - if (fval(u, UFL_GROUP)) - a = a_find(u->attribs, &at_group); - if (a) { - group *g = (group *) a->data.v; - s = &g->name; - break; - } else { - cmistake(u, ord, 109, MSG_EVENT); - break; - } - } - break; - default: - cmistake(u, ord, 109, MSG_EVENT); - break; - } - - if (s != NULL) { - return rename_cmd(u, ord, s, getstrtoken()); - } - - return 0; + return 0; } /* ------------------------------------------------------------- */ @@ -2110,768 +2144,784 @@ int name_cmd(struct unit *u, struct order *ord) void deliverMail(faction * f, region * r, unit * u, const char *s, unit * receiver) { - if (!cansee(f, r, u, 0)) { - u = NULL; - } - if (!receiver) { /* BOTSCHAFT an PARTEI */ - ADDMSG(&f->msgs, - msg_message("regionmessage", "region sender string", r, u, s)); - } else { /* BOTSCHAFT an EINHEIT */ - ADDMSG(&f->msgs, - msg_message("unitmessage", "region unit sender string", r, - receiver, u, s)); - } + if (!cansee(f, r, u, 0)) { + u = NULL; + } + if (!receiver) { /* BOTSCHAFT an PARTEI */ + ADDMSG(&f->msgs, + msg_message("regionmessage", "region sender string", r, u, s)); + } + else { /* BOTSCHAFT an EINHEIT */ + ADDMSG(&f->msgs, + msg_message("unitmessage", "region unit sender string", r, + receiver, u, s)); + } } static void mailunit(region * r, unit * u, int n, struct order *ord, const char *s) { - unit *u2 = findunitr(r, n); + unit *u2 = findunitr(r, n); - if (u2 && cansee(u->faction, r, u2, 0)) { - deliverMail(u2->faction, r, u, s, u2); - /* now done in prepare_mail_cmd */ - } else { - /* Immer eine Meldung - sonst koennte man so getarnte EHs enttarnen: - * keine Meldung -> EH hier. */ - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "feedback_unit_not_found", "")); - } + if (u2 && cansee(u->faction, r, u2, 0)) { + deliverMail(u2->faction, r, u, s, u2); + /* now done in prepare_mail_cmd */ + } + else { + /* Immer eine Meldung - sonst koennte man so getarnte EHs enttarnen: + * keine Meldung -> EH hier. */ + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "feedback_unit_not_found", "")); + } } static void mailfaction(unit * u, int n, struct order *ord, const char *s) { - faction *f; + faction *f; - f = findfaction(n); - if (f && n > 0) - deliverMail(f, u->region, u, s, NULL); - else - cmistake(u, ord, 66, MSG_MESSAGE); + f = findfaction(n); + if (f && n > 0) + deliverMail(f, u->region, u, s, NULL); + else + cmistake(u, ord, 66, MSG_MESSAGE); } int mail_cmd(unit * u, struct order *ord) { - region *r = u->region; - unit *u2; - const char *s; - int n, cont; + region *r = u->region; + unit *u2; + const char *s; + int n, cont; - init_tokens(ord); - skip_token(); /* skip the keyword */ - s = getstrtoken(); + init_tokens(ord); + skip_token(); /* skip the keyword */ + s = getstrtoken(); - /* Falls kein Parameter, ist das eine Einheitsnummer; - * das Füllwort "AN" muß wegfallen, da gültige Nummer! */ + /* Falls kein Parameter, ist das eine Einheitsnummer; + * das Füllwort "AN" muß wegfallen, da gültige Nummer! */ - do { - cont = 0; - switch (findparam_ex(s, u->faction->locale)) { - case P_REGION: - /* können alle Einheiten in der Region sehen */ - s = getstrtoken(); - if (!s[0]) { - cmistake(u, ord, 30, MSG_MESSAGE); - break; - } else { - ADDMSG(&r->msgs, msg_message("mail_result", "unit message", u, s)); - return 0; - } + do { + cont = 0; + switch (findparam_ex(s, u->faction->locale)) { + case P_REGION: + /* können alle Einheiten in der Region sehen */ + s = getstrtoken(); + if (!s[0]) { + cmistake(u, ord, 30, MSG_MESSAGE); + break; + } + else { + ADDMSG(&r->msgs, msg_message("mail_result", "unit message", u, s)); + return 0; + } - case P_FACTION: - { - bool see = false; + case P_FACTION: + { + bool see = false; - n = getfactionid(); + n = getfactionid(); - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->faction->no == n && seefaction(u->faction, r, u2, 0)) { - see = true; - break; - } - } + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction->no == n && seefaction(u->faction, r, u2, 0)) { + see = true; + break; + } + } - if (!see) { - cmistake(u, ord, 66, MSG_MESSAGE); - break; - } + if (!see) { + cmistake(u, ord, 66, MSG_MESSAGE); + break; + } - s = getstrtoken(); - if (!s[0]) { - cmistake(u, ord, 30, MSG_MESSAGE); - break; - } - mailfaction(u, n, ord, s); - return 0; - } - - case P_UNIT: - { - bool see = false; - n = getid(); - - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->no == n && cansee(u->faction, r, u2, 0)) { - see = true; - break; - } - } - - if (!see) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return 0; - } - - s = getstrtoken(); - if (!s[0]) { - cmistake(u, ord, 30, MSG_MESSAGE); - break; - } else { - attrib *a = a_find(u2->attribs, &at_eventhandler); - if (a != NULL) { - event_arg args[3]; - args[0].data.v = (void *)s; - args[0].type = "string"; - args[1].data.v = (void *)u; - args[1].type = "unit"; - args[2].type = NULL; - handle_event(a, "message", args); + s = getstrtoken(); + if (!s[0]) { + cmistake(u, ord, 30, MSG_MESSAGE); + break; + } + mailfaction(u, n, ord, s); + return 0; } - mailunit(r, u, n, ord, s); - } - return 0; - } + case P_UNIT: + { + bool see = false; + n = getid(); - case P_BUILDING: - case P_GEBAEUDE: - { - building *b = getbuilding(r); + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->no == n && cansee(u->faction, r, u2, 0)) { + see = true; + break; + } + } - if (!b) { - cmistake(u, ord, 6, MSG_MESSAGE); - break; - } + if (!see) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + return 0; + } - s = getstrtoken(); + s = getstrtoken(); + if (!s[0]) { + cmistake(u, ord, 30, MSG_MESSAGE); + break; + } + else { + attrib *a = a_find(u2->attribs, &at_eventhandler); + if (a != NULL) { + event_arg args[3]; + args[0].data.v = (void *)s; + args[0].type = "string"; + args[1].data.v = (void *)u; + args[1].type = "unit"; + args[2].type = NULL; + handle_event(a, "message", args); + } - if (!s[0]) { - cmistake(u, ord, 30, MSG_MESSAGE); - break; - } - - for (u2 = r->units; u2; u2 = u2->next) - freset(u2->faction, FFL_SELECT); - - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->building == b && !fval(u2->faction, FFL_SELECT) - && cansee(u->faction, r, u2, 0)) { - mailunit(r, u, u2->no, ord, s); - fset(u2->faction, FFL_SELECT); + mailunit(r, u, n, ord, s); + } + return 0; } - } - return 0; - } - case P_SHIP: - { - ship *sh = getship(r); + case P_BUILDING: + case P_GEBAEUDE: + { + building *b = getbuilding(r); - if (!sh) { - cmistake(u, ord, 20, MSG_MESSAGE); - break; - } + if (!b) { + cmistake(u, ord, 6, MSG_MESSAGE); + break; + } - s = getstrtoken(); + s = getstrtoken(); - if (!s[0]) { - cmistake(u, ord, 30, MSG_MESSAGE); - break; - } + if (!s[0]) { + cmistake(u, ord, 30, MSG_MESSAGE); + break; + } - for (u2 = r->units; u2; u2 = u2->next) - freset(u2->faction, FFL_SELECT); + for (u2 = r->units; u2; u2 = u2->next) + freset(u2->faction, FFL_SELECT); - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->ship == sh && !fval(u2->faction, FFL_SELECT) - && cansee(u->faction, r, u2, 0)) { - mailunit(r, u, u2->no, ord, s); - fset(u2->faction, FFL_SELECT); + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->building == b && !fval(u2->faction, FFL_SELECT) + && cansee(u->faction, r, u2, 0)) { + mailunit(r, u, u2->no, ord, s); + fset(u2->faction, FFL_SELECT); + } + } + return 0; } - } - return 0; - } - default: - /* possibly filler token? */ - s = getstrtoken(); - if (s && *s) - cont = 1; - break; - } - } - while (cont); - cmistake(u, ord, 149, MSG_MESSAGE); - return 0; + case P_SHIP: + { + ship *sh = getship(r); + + if (!sh) { + cmistake(u, ord, 20, MSG_MESSAGE); + break; + } + + s = getstrtoken(); + + if (!s[0]) { + cmistake(u, ord, 30, MSG_MESSAGE); + break; + } + + for (u2 = r->units; u2; u2 = u2->next) + freset(u2->faction, FFL_SELECT); + + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->ship == sh && !fval(u2->faction, FFL_SELECT) + && cansee(u->faction, r, u2, 0)) { + mailunit(r, u, u2->no, ord, s); + fset(u2->faction, FFL_SELECT); + } + } + return 0; + } + + default: + /* possibly filler token? */ + s = getstrtoken(); + if (s && *s) + cont = 1; + break; + } + } while (cont); + cmistake(u, ord, 149, MSG_MESSAGE); + return 0; } /* ------------------------------------------------------------- */ int banner_cmd(unit * u, struct order *ord) { - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - free(u->faction->banner); - u->faction->banner = _strdup(getstrtoken()); - add_message(&u->faction->msgs, msg_message("changebanner", "value", - u->faction->banner)); + free(u->faction->banner); + u->faction->banner = _strdup(getstrtoken()); + add_message(&u->faction->msgs, msg_message("changebanner", "value", + u->faction->banner)); - return 0; + return 0; } int email_cmd(unit * u, struct order *ord) { - const char *s; + const char *s; - init_tokens(ord); - skip_token(); - s = getstrtoken(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); - if (!s[0]) { - cmistake(u, ord, 85, MSG_EVENT); - } else { - faction *f = u->faction; - if (set_email(&f->email, (const char *)s) != 0) { - log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), s); - ADDMSG(&f->msgs, msg_message("changemail_invalid", "value", s)); - } else { - ADDMSG(&f->msgs, msg_message("changemail", "value", f->email)); + if (!s[0]) { + cmistake(u, ord, 85, MSG_EVENT); } - } - return 0; + else { + faction *f = u->faction; + if (set_email(&f->email, (const char *)s) != 0) { + log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), s); + ADDMSG(&f->msgs, msg_message("changemail_invalid", "value", s)); + } + else { + ADDMSG(&f->msgs, msg_message("changemail", "value", f->email)); + } + } + return 0; } int password_cmd(unit * u, struct order *ord) { - char pwbuf[32]; - int i; - const char *s; - bool pwok = true; + char pwbuf[32]; + int i; + const char *s; + bool pwok = true; - init_tokens(ord); - skip_token(); - s = getstrtoken(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); - if (!s || !*s) { - for (i = 0; i < 6; i++) - pwbuf[i] = (char)(97 + rng_int() % 26); - pwbuf[6] = 0; - } else { - char *c; - - strlcpy(pwbuf, (const char *)s, 31); - pwbuf[31] = 0; - c = pwbuf; - while (*c && pwok) { - if (!isalnum(*(unsigned char *)c)) - pwok = false; - c++; + if (!s || !*s) { + for (i = 0; i < 6; i++) + pwbuf[i] = (char)(97 + rng_int() % 26); + pwbuf[6] = 0; } - } - free(u->faction->passw); - if (!pwok) { - cmistake(u, ord, 283, MSG_EVENT); - u->faction->passw = _strdup(itoa36(rng_int())); - } else { - u->faction->passw = _strdup(pwbuf); - } - ADDMSG(&u->faction->msgs, msg_message("changepasswd", - "value", u->faction->passw)); - return 0; + else { + char *c; + + strlcpy(pwbuf, (const char *)s, 31); + pwbuf[31] = 0; + c = pwbuf; + while (*c && pwok) { + if (!isalnum(*(unsigned char *)c)) + pwok = false; + c++; + } + } + free(u->faction->passw); + if (!pwok) { + cmistake(u, ord, 283, MSG_EVENT); + u->faction->passw = _strdup(itoa36(rng_int())); + } + else { + u->faction->passw = _strdup(pwbuf); + } + ADDMSG(&u->faction->msgs, msg_message("changepasswd", + "value", u->faction->passw)); + return 0; } int send_cmd(unit * u, struct order *ord) { - const char *s; - int option; + const char *s; + int option; - init_tokens(ord); - skip_token(); - s = getstrtoken(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); - option = findoption(s, u->faction->locale); + option = findoption(s, u->faction->locale); - if (option == -1) { - cmistake(u, ord, 135, MSG_EVENT); - } else { - if (getparam(u->faction->locale) == P_NOT) { - if (option == O_COMPRESS || option == O_BZIP2) { - cmistake(u, ord, 305, MSG_EVENT); - } else { - u->faction->options = u->faction->options & ~(1 << option); - } - } else { - u->faction->options = u->faction->options | (1 << option); - if (option == O_COMPRESS) - u->faction->options &= ~(1 << O_BZIP2); - if (option == O_BZIP2) - u->faction->options &= ~(1 << O_COMPRESS); + if (option == -1) { + cmistake(u, ord, 135, MSG_EVENT); } - } - return 0; + else { + if (getparam(u->faction->locale) == P_NOT) { + if (option == O_COMPRESS || option == O_BZIP2) { + cmistake(u, ord, 305, MSG_EVENT); + } + else { + u->faction->options = u->faction->options & ~(1 << option); + } + } + else { + u->faction->options = u->faction->options | (1 << option); + if (option == O_COMPRESS) + u->faction->options &= ~(1 << O_BZIP2); + if (option == O_BZIP2) + u->faction->options &= ~(1 << O_COMPRESS); + } + } + return 0; } static bool display_item(faction * f, unit * u, const item_type * itype) { - const char *name; - const char *key; - const char *info; + const char *name; + const char *key; + const char *info; - if (u != NULL) { - int i = i_get(u->items, itype); - if (i == 0) { - if (u->region->land != NULL) { - i = i_get(u->region->land->items, itype); - } - if (i == 0) { - i = i_get(u->faction->items, itype); - if (i == 0) - return false; - } + if (u != NULL) { + int i = i_get(u->items, itype); + if (i == 0) { + if (u->region->land != NULL) { + i = i_get(u->region->land->items, itype); + } + if (i == 0) { + i = i_get(u->faction->items, itype); + if (i == 0) + return false; + } + } } - } - name = resourcename(itype->rtype, 0); - key = mkname("iteminfo", name); - info = locale_getstring(f->locale, key); + name = resourcename(itype->rtype, 0); + key = mkname("iteminfo", name); + info = locale_getstring(f->locale, key); - if (info == NULL) { - info = locale_string(f->locale, mkname("iteminfo", "no_info")); - } - ADDMSG(&f->msgs, msg_message("displayitem", "weight item description", - itype->weight, itype->rtype, info)); + if (info == NULL) { + info = locale_string(f->locale, mkname("iteminfo", "no_info")); + } + ADDMSG(&f->msgs, msg_message("displayitem", "weight item description", + itype->weight, itype->rtype, info)); - return true; + return true; } static bool display_potion(faction * f, unit * u, const potion_type * ptype) { - attrib *a; + attrib *a; - if (ptype == NULL) - return false; - else { - int i = i_get(u->items, ptype->itype); - if (i == 0 && 2 * ptype->level > effskill(u, SK_ALCHEMY)) { - return false; + if (ptype == NULL) + return false; + else { + int i = i_get(u->items, ptype->itype); + if (i == 0 && 2 * ptype->level > effskill(u, SK_ALCHEMY)) { + return false; + } } - } - a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != ptype) - a = a->next; - if (!a) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; - } + a = a_find(f->attribs, &at_showitem); + while (a && a->data.v != ptype) + a = a->next; + if (!a) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)ptype->itype; + } - return true; + return true; } static bool display_race(faction * f, unit * u, const race * rc) { - const char *name, *key; - const char *info; - int a, at_count; - char buf[2048], *bufp = buf; - size_t size = sizeof(buf) - 1; - int bytes; + const char *name, *key; + const char *info; + int a, at_count; + char buf[2048], *bufp = buf; + size_t size = sizeof(buf) - 1; + int bytes; - if (u && u_race(u) != rc) - return false; - name = rc_name(rc, 0); + if (u && u_race(u) != rc) + return false; + name = rc_name(rc, 0); - bytes = slprintf(bufp, size, "%s: ", LOC(f->locale, name)); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + bytes = slprintf(bufp, size, "%s: ", LOC(f->locale, name)); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); - key = mkname("raceinfo", rc->_name[0]); - info = locale_getstring(f->locale, key); - if (info == NULL) { - info = locale_string(f->locale, mkname("raceinfo", "no_info")); - } + key = mkname("raceinfo", rc->_name[0]); + info = locale_getstring(f->locale, key); + if (info == NULL) { + info = locale_string(f->locale, mkname("raceinfo", "no_info")); + } - bytes = (int)strlcpy(bufp, info, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, info, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); - /* hp_p : Trefferpunkte */ - bytes = - slprintf(bufp, size, " %d %s", rc->hitpoints, LOC(f->locale, - "stat_hitpoints")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - - /* b_attacke : Angriff */ - bytes = - slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_attack"), - (rc->at_default + rc->at_bonus)); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - - /* b_defense : Verteidigung */ - bytes = - slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_defense"), - (rc->df_default + rc->df_bonus)); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - - /* b_armor : Rüstung */ - if (rc->armor > 0) { + /* hp_p : Trefferpunkte */ bytes = - slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); + slprintf(bufp, size, " %d %s", rc->hitpoints, LOC(f->locale, + "stat_hitpoints")); if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - - if (size > 1) { - *bufp++ = '.'; - --size; - } else - WARN_STATIC_BUFFER(); - - /* b_damage : Schaden */ - at_count = 0; - for (a = 0; a < 6; a++) { - if (rc->attack[a].type != AT_NONE) { - at_count++; - } - } - if (rc->battle_flags & BF_EQUIPMENT) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_equipment")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - if (rc->battle_flags & BF_RES_PIERCE) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_pierce")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - if (rc->battle_flags & BF_RES_CUT) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_cut")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - if (rc->battle_flags & BF_RES_BASH) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_bash")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - - bytes = - _snprintf(bufp, size, " %d %s", at_count, LOC(f->locale, - (at_count == 1) ? "stat_attack" : "stat_attacks")); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - - for (a = 0; a < 6; a++) { - if (rc->attack[a].type != AT_NONE) { - if (a != 0) - bytes = (int)strlcpy(bufp, ", ", size); - else - bytes = (int)strlcpy(bufp, ": ", size); - if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - switch (rc->attack[a].type) { - case AT_STANDARD: - bytes = - _snprintf(bufp, size, "%s (%s)", - LOC(f->locale, "attack_standard"), rc->def_damage); - break; - case AT_NATURAL: - bytes = - _snprintf(bufp, size, "%s (%s)", - LOC(f->locale, "attack_natural"), rc->attack[a].data.dice); - break; - case AT_SPELL: - case AT_COMBATSPELL: - case AT_DRAIN_ST: - case AT_DRAIN_EXP: - case AT_DAZZLE: - bytes = _snprintf(bufp, size, "%s", LOC(f->locale, "attack_magical")); - break; - case AT_STRUCTURAL: - bytes = - _snprintf(bufp, size, "%s (%s)", - LOC(f->locale, "attack_structural"), rc->attack[a].data.dice); - break; - default: - bytes = 0; - } - - if (bytes && wrptr(&bufp, &size, bytes) != 0) + /* b_attacke : Angriff */ + bytes = + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_attack"), + (rc->at_default + rc->at_bonus)); + if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); + + /* b_defense : Verteidigung */ + bytes = + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_defense"), + (rc->df_default + rc->df_bonus)); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + + /* b_armor : Rüstung */ + if (rc->armor > 0) { + bytes = + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); } - } - if (size > 1) { - *bufp++ = '.'; - --size; - } else - WARN_STATIC_BUFFER(); + if (size > 1) { + *bufp++ = '.'; + --size; + } + else + WARN_STATIC_BUFFER(); - *bufp = 0; - addmessage(0, f, buf, MSG_EVENT, ML_IMPORTANT); + /* b_damage : Schaden */ + at_count = 0; + for (a = 0; a < 6; a++) { + if (rc->attack[a].type != AT_NONE) { + at_count++; + } + } + if (rc->battle_flags & BF_EQUIPMENT) { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_equipment")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + if (rc->battle_flags & BF_RES_PIERCE) { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_pierce")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + if (rc->battle_flags & BF_RES_CUT) { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_cut")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + if (rc->battle_flags & BF_RES_BASH) { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "stat_bash")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } - return true; + bytes = + _snprintf(bufp, size, " %d %s", at_count, LOC(f->locale, + (at_count == 1) ? "stat_attack" : "stat_attacks")); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + + for (a = 0; a < 6; a++) { + if (rc->attack[a].type != AT_NONE) { + if (a != 0) + bytes = (int)strlcpy(bufp, ", ", size); + else + bytes = (int)strlcpy(bufp, ": ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + + switch (rc->attack[a].type) { + case AT_STANDARD: + bytes = + _snprintf(bufp, size, "%s (%s)", + LOC(f->locale, "attack_standard"), rc->def_damage); + break; + case AT_NATURAL: + bytes = + _snprintf(bufp, size, "%s (%s)", + LOC(f->locale, "attack_natural"), rc->attack[a].data.dice); + break; + case AT_SPELL: + case AT_COMBATSPELL: + case AT_DRAIN_ST: + case AT_DRAIN_EXP: + case AT_DAZZLE: + bytes = _snprintf(bufp, size, "%s", LOC(f->locale, "attack_magical")); + break; + case AT_STRUCTURAL: + bytes = + _snprintf(bufp, size, "%s (%s)", + LOC(f->locale, "attack_structural"), rc->attack[a].data.dice); + break; + default: + bytes = 0; + } + + if (bytes && wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + } + + if (size > 1) { + *bufp++ = '.'; + --size; + } + else + WARN_STATIC_BUFFER(); + + *bufp = 0; + addmessage(0, f, buf, MSG_EVENT, ML_IMPORTANT); + + return true; } static void reshow(unit * u, struct order *ord, const char *s, param_t p) { - int skill, c; - const potion_type *ptype; - const item_type *itype; - const spell *sp = 0; - const race *rc; + int skill, c; + const potion_type *ptype; + const item_type *itype; + const spell *sp = 0; + const race *rc; - switch (p) { - case P_ZAUBER: - a_removeall(&u->faction->attribs, &at_seenspell); - break; - case P_POTIONS: - skill = effskill(u, SK_ALCHEMY); - c = 0; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - c += display_potion(u->faction, u, ptype); - } - } - if (c == 0) - cmistake(u, ord, 285, MSG_EVENT); - break; - case NOPARAM: - if (s) { - /* check if it's an item */ - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - ptype = resource2potion(item2resource(itype)); - if (ptype != NULL) { - if (display_potion(u->faction, u, ptype)) - break; - } else { - if (display_item(u->faction, u, itype)) - break; - } - } - /* try for a spell */ - sp = unit_getspell(u, s, u->faction->locale); - if (sp) { - attrib *a = a_find(u->faction->attribs, &at_seenspell); - while (a != NULL && a->type == &at_seenspell && a->data.v != sp) { - a = a->next; - } - if (a != NULL) { - a_remove(&u->faction->attribs, a); - } + switch (p) { + case P_ZAUBER: + a_removeall(&u->faction->attribs, &at_seenspell); break; - } - /* last, check if it's a race. */ - rc = findrace(s, u->faction->locale); - if (rc != NULL && display_race(u->faction, u, rc)) { + case P_POTIONS: + skill = effskill(u, SK_ALCHEMY); + c = 0; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + c += display_potion(u->faction, u, ptype); + } + } + if (c == 0) + cmistake(u, ord, 285, MSG_EVENT); + break; + case NOPARAM: + if (s) { + /* check if it's an item */ + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + ptype = resource2potion(item2resource(itype)); + if (ptype != NULL) { + if (display_potion(u->faction, u, ptype)) + break; + } + else { + if (display_item(u->faction, u, itype)) + break; + } + } + /* try for a spell */ + sp = unit_getspell(u, s, u->faction->locale); + if (sp) { + attrib *a = a_find(u->faction->attribs, &at_seenspell); + while (a != NULL && a->type == &at_seenspell && a->data.v != sp) { + a = a->next; + } + if (a != NULL) { + a_remove(&u->faction->attribs, a); + } + break; + } + /* last, check if it's a race. */ + rc = findrace(s, u->faction->locale); + if (rc != NULL && display_race(u->faction, u, rc)) { + break; + } + } + cmistake(u, ord, 21, MSG_EVENT); + break; + default: + cmistake(u, ord, 222, MSG_EVENT); break; - } } - cmistake(u, ord, 21, MSG_EVENT); - break; - default: - cmistake(u, ord, 222, MSG_EVENT); - break; - } } int promotion_cmd(unit * u, struct order *ord) { const struct resource_type *rsilver = get_resourcetype(R_SILVER); - int money, people; + int money, people; - if (fval(u, UFL_HERO)) { - /* TODO: message "is already a hero" */ - return 0; - } + if (fval(u, UFL_HERO)) { + /* TODO: message "is already a hero" */ + return 0; + } - if (maxheroes(u->faction) < countheroes(u->faction) + u->number) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "heroes_maxed", "max count", - maxheroes(u->faction), countheroes(u->faction))); - return 0; - } - if (!valid_race(u->faction, u_race(u))) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_race", "race", - u_race(u))); - return 0; - } - people = count_all(u->faction) * u->number; - money = get_pooled(u, rsilver, GET_ALL, people); + if (maxheroes(u->faction) < countheroes(u->faction) + u->number) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "heroes_maxed", "max count", + maxheroes(u->faction), countheroes(u->faction))); + return 0; + } + if (!valid_race(u->faction, u_race(u))) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_race", "race", + u_race(u))); + return 0; + } + people = count_all(u->faction) * u->number; + money = get_pooled(u, rsilver, GET_ALL, people); - if (people > money) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "heroes_cost", "cost have", people, money)); + if (people > money) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "heroes_cost", "cost have", people, money)); + return 0; + } + use_pooled(u, rsilver, GET_ALL, people); + fset(u, UFL_HERO); + ADDMSG(&u->faction->msgs, msg_message("hero_promotion", "unit cost", + u, people)); return 0; - } - use_pooled(u, rsilver, GET_ALL, people); - fset(u, UFL_HERO); - ADDMSG(&u->faction->msgs, msg_message("hero_promotion", "unit cost", - u, people)); - return 0; } int group_cmd(unit * u, struct order *ord) { - const char *s; + const char *s; - init_tokens(ord); - skip_token(); - s = getstrtoken(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); - join_group(u, s); - return 0; + join_group(u, s); + return 0; } int origin_cmd(unit * u, struct order *ord) { - short px, py; + short px, py; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - px = (short)getint(); - py = (short)getint(); + px = (short)getint(); + py = (short)getint(); - set_ursprung(u->faction, getplaneid(u->region), px, py); - return 0; + set_ursprung(u->faction, getplaneid(u->region), px, py); + return 0; } int guard_off_cmd(unit * u, struct order *ord) { - assert(getkeyword(ord) == K_GUARD); - init_tokens(ord); - skip_token(); + assert(getkeyword(ord) == K_GUARD); + init_tokens(ord); + skip_token(); - if (getparam(u->faction->locale) == P_NOT) { - setguard(u, GUARD_NONE); - } - return 0; + if (getparam(u->faction->locale) == P_NOT) { + setguard(u, GUARD_NONE); + } + return 0; } int reshow_cmd(unit * u, struct order *ord) { - const char *s; - param_t p = NOPARAM; + const char *s; + param_t p = NOPARAM; - init_tokens(ord); - skip_token(); - s = getstrtoken(); + init_tokens(ord); + skip_token(); + s = getstrtoken(); - if (isparam(s, u->faction->locale, P_ANY)) { - p = getparam(u->faction->locale); - s = NULL; - } + if (isparam(s, u->faction->locale, P_ANY)) { + p = getparam(u->faction->locale); + s = NULL; + } - reshow(u, ord, s, p); - return 0; + reshow(u, ord, s, p); + return 0; } int status_cmd(unit * u, struct order *ord) { - const char *param; + const char *param; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - param = getstrtoken(); - switch (findparam(param, u->faction->locale)) { - case P_NOT: - setstatus(u, ST_AVOID); - break; - case P_BEHIND: - setstatus(u, ST_BEHIND); - break; - case P_FLEE: - setstatus(u, ST_FLEE); - break; - case P_CHICKEN: - setstatus(u, ST_CHICKEN); - break; - case P_AGGRO: - setstatus(u, ST_AGGRO); - break; - case P_VORNE: - setstatus(u, ST_FIGHT); - break; - case P_HELP: - if (getparam(u->faction->locale) == P_NOT) { - fset(u, UFL_NOAID); - } else { - freset(u, UFL_NOAID); + param = getstrtoken(); + switch (findparam(param, u->faction->locale)) { + case P_NOT: + setstatus(u, ST_AVOID); + break; + case P_BEHIND: + setstatus(u, ST_BEHIND); + break; + case P_FLEE: + setstatus(u, ST_FLEE); + break; + case P_CHICKEN: + setstatus(u, ST_CHICKEN); + break; + case P_AGGRO: + setstatus(u, ST_AGGRO); + break; + case P_VORNE: + setstatus(u, ST_FIGHT); + break; + case P_HELP: + if (getparam(u->faction->locale) == P_NOT) { + fset(u, UFL_NOAID); + } + else { + freset(u, UFL_NOAID); + } + break; + default: + if (param[0]) { + add_message(&u->faction->msgs, + msg_feedback(u, ord, "unknown_status", "")); + } + else { + setstatus(u, ST_FIGHT); + } } - break; - default: - if (param[0]) { - add_message(&u->faction->msgs, - msg_feedback(u, ord, "unknown_status", "")); - } else { - setstatus(u, ST_FIGHT); - } - } - return 0; + return 0; } int combatspell_cmd(unit * u, struct order *ord) { - const char *s; - int level = 0; - spell *sp = 0; + const char *s; + int level = 0; + spell *sp = 0; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - /* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */ - if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) { - unset_combatspell(u, 0); - return 0; - } - - /* Optional: STUFE n */ - if (findparam(s, u->faction->locale) == P_LEVEL) { - /* Merken, setzen kommt erst später */ - level = getint(); - level = _max(0, level); + init_tokens(ord); + skip_token(); s = getstrtoken(); - } - sp = unit_getspell(u, s, u->faction->locale); - if (!sp) { - cmistake(u, ord, 173, MSG_MAGIC); + /* KAMPFZAUBER [NICHT] löscht alle gesetzten Kampfzauber */ + if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) { + unset_combatspell(u, 0); + return 0; + } + + /* Optional: STUFE n */ + if (findparam(s, u->faction->locale) == P_LEVEL) { + /* Merken, setzen kommt erst später */ + level = getint(); + level = _max(0, level); + s = getstrtoken(); + } + + sp = unit_getspell(u, s, u->faction->locale); + if (!sp) { + cmistake(u, ord, 173, MSG_MAGIC); + return 0; + } + + s = getstrtoken(); + + if (findparam(s, u->faction->locale) == P_NOT) { + /* KAMPFZAUBER "" NICHT löscht diesen speziellen + * Kampfzauber */ + unset_combatspell(u, sp); + return 0; + } + else { + /* KAMPFZAUBER "" setzt diesen Kampfzauber */ + set_combatspell(u, sp, ord, level); + } + return 0; - } - - s = getstrtoken(); - - if (findparam(s, u->faction->locale) == P_NOT) { - /* KAMPFZAUBER "" NICHT löscht diesen speziellen - * Kampfzauber */ - unset_combatspell(u, sp); - return 0; - } else { - /* KAMPFZAUBER "" setzt diesen Kampfzauber */ - set_combatspell(u, sp, ord, level); - } - - return 0; } /* ------------------------------------------------------------- */ @@ -2882,107 +2932,115 @@ enum { E_GUARD_OK, E_GUARD_UNARMED, E_GUARD_NEWBIE, E_GUARD_FLEEING }; static int can_start_guarding(const unit * u) { - if (u->status >= ST_FLEE) - return E_GUARD_FLEEING; - if (fval(u_race(u), RCF_UNARMEDGUARD)) + if (u->status >= ST_FLEE) + return E_GUARD_FLEEING; + if (fval(u_race(u), RCF_UNARMEDGUARD)) + return E_GUARD_OK; + if (!armedmen(u, true)) + return E_GUARD_UNARMED; + if (IsImmune(u->faction)) + return E_GUARD_NEWBIE; return E_GUARD_OK; - if (!armedmen(u, true)) - return E_GUARD_UNARMED; - if (IsImmune(u->faction)) - return E_GUARD_NEWBIE; - return E_GUARD_OK; } void update_guards(void) { - const region *r; + const region *r; - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - if (fval(u, UFL_GUARD)) { - if (can_start_guarding(u) != E_GUARD_OK) { - setguard(u, GUARD_NONE); - } else { - attrib *a = a_find(u->attribs, &at_guard); - if (a && a->data.i == (int)guard_flags(u)) { - /* this is really rather not necessary */ - a_remove(&u->attribs, a); - } + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + if (fval(u, UFL_GUARD)) { + if (can_start_guarding(u) != E_GUARD_OK) { + setguard(u, GUARD_NONE); + } + else { + attrib *a = a_find(u->attribs, &at_guard); + if (a && a->data.i == (int)guard_flags(u)) { + /* this is really rather not necessary */ + a_remove(&u->attribs, a); + } + } + } } - } } - } } int guard_on_cmd(unit * u, struct order *ord) { - assert(getkeyword(ord) == K_GUARD); + assert(getkeyword(ord) == K_GUARD); - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - /* GUARD NOT is handled in goard_off_cmd earlier in the turn */ - if (getparam(u->faction->locale) == P_NOT) - return 0; + /* GUARD NOT is handled in goard_off_cmd earlier in the turn */ + if (getparam(u->faction->locale) == P_NOT) + return 0; - if (fval(u->region->terrain, SEA_REGION)) { - cmistake(u, ord, 2, MSG_EVENT); - } else { - if (fval(u, UFL_MOVED)) { - cmistake(u, ord, 187, MSG_EVENT); - } else if (fval(u_race(u), RCF_ILLUSIONARY) - || u_race(u) == get_race(RC_SPELL)) { - cmistake(u, ord, 95, MSG_EVENT); - } else { - /* Monster der Monsterpartei dürfen immer bewachen */ - if (is_monsters(u->faction)) { - guard(u, GUARD_ALL); - } else { - int err = can_start_guarding(u); - if (err == E_GUARD_OK) { - guard(u, GUARD_ALL); - } else if (err == E_GUARD_UNARMED) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_unarmed", "")); - } else if (err == E_GUARD_FLEEING) { - cmistake(u, ord, 320, MSG_EVENT); - } else if (err == E_GUARD_NEWBIE) { - cmistake(u, ord, 304, MSG_EVENT); - } - } + if (fval(u->region->terrain, SEA_REGION)) { + cmistake(u, ord, 2, MSG_EVENT); } - } - return 0; + else { + if (fval(u, UFL_MOVED)) { + cmistake(u, ord, 187, MSG_EVENT); + } + else if (fval(u_race(u), RCF_ILLUSIONARY) + || u_race(u) == get_race(RC_SPELL)) { + cmistake(u, ord, 95, MSG_EVENT); + } + else { + /* Monster der Monsterpartei dürfen immer bewachen */ + if (is_monsters(u->faction)) { + guard(u, GUARD_ALL); + } + else { + int err = can_start_guarding(u); + if (err == E_GUARD_OK) { + guard(u, GUARD_ALL); + } + else if (err == E_GUARD_UNARMED) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unit_unarmed", "")); + } + else if (err == E_GUARD_FLEEING) { + cmistake(u, ord, 320, MSG_EVENT); + } + else if (err == E_GUARD_NEWBIE) { + cmistake(u, ord, 304, MSG_EVENT); + } + } + } + } + return 0; } void sinkships(struct region * r) { - ship **shp = &r->ships; + ship **shp = &r->ships; - while (*shp) { - ship *sh = *shp; + while (*shp) { + ship *sh = *shp; - if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) { - if (fval(r->terrain, SEA_REGION) && (!enoughsailors(sh, r) - || get_captain(sh) == NULL)) { - /* Schiff nicht seetüchtig */ - float dmg = get_param_flt(global.parameters, - "rules.ship.damage.nocrewocean", - 0.30F); - damage_ship(sh, dmg); - } - if (ship_owner(sh) == NULL) { - float dmg = get_param_flt(global.parameters, "rules.ship.damage.nocrew", - 0.05F); - damage_ship(sh, dmg); - } + if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) { + if (fval(r->terrain, SEA_REGION) && (!enoughsailors(sh, r) + || get_captain(sh) == NULL)) { + /* Schiff nicht seetüchtig */ + float dmg = get_param_flt(global.parameters, + "rules.ship.damage.nocrewocean", + 0.30F); + damage_ship(sh, dmg); + } + if (ship_owner(sh) == NULL) { + float dmg = get_param_flt(global.parameters, "rules.ship.damage.nocrew", + 0.05F); + damage_ship(sh, dmg); + } + } + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(shp, sh); + } + if (*shp == sh) + shp = &sh->next; } - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(shp, sh); - } - if (*shp == sh) - shp = &sh->next; - } } /* The following functions do not really belong here: */ @@ -2990,268 +3048,279 @@ void sinkships(struct region * r) #include static attrib_type at_number = { - "faction_renum", - NULL, NULL, NULL, NULL, NULL, - ATF_UNIQUE + "faction_renum", + NULL, NULL, NULL, NULL, NULL, + ATF_UNIQUE }; void renumber_factions(void) - /* gibt parteien neue nummern */ +/* gibt parteien neue nummern */ { - struct renum { - struct renum *next; - int want; - faction *faction; - attrib *attrib; - } *renum = NULL, *rp; - faction *f; - for (f = factions; f; f = f->next) { - attrib *a = a_find(f->attribs, &at_number); - int want; - struct renum **rn; - faction *old; + struct renum { + struct renum *next; + int want; + faction *faction; + attrib *attrib; + } *renum = NULL, *rp; + faction *f; + for (f = factions; f; f = f->next) { + attrib *a = a_find(f->attribs, &at_number); + int want; + struct renum **rn; + faction *old; - if (!a) - continue; - want = a->data.i; - if (fval(f, FFL_NEWID)) { - ADDMSG(&f->msgs, msg_message("renumber_twice", "id", want)); - continue; + if (!a) + continue; + want = a->data.i; + if (fval(f, FFL_NEWID)) { + ADDMSG(&f->msgs, msg_message("renumber_twice", "id", want)); + continue; + } + old = findfaction(want); + if (old) { + a_remove(&f->attribs, a); + ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); + continue; + } + if (!faction_id_is_unused(want)) { + a_remove(&f->attribs, a); + ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); + continue; + } + for (rn = &renum; *rn; rn = &(*rn)->next) { + if ((*rn)->want >= want) + break; + } + if (*rn && (*rn)->want == want) { + ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); + } + else { + struct renum *r = calloc(sizeof(struct renum), 1); + r->next = *rn; + r->attrib = a; + r->faction = f; + r->want = want; + *rn = r; + } } - old = findfaction(want); - if (old) { - a_remove(&f->attribs, a); - ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); - continue; + for (rp = renum; rp; rp = rp->next) { + f = rp->faction; + a_remove(&f->attribs, rp->attrib); + renumber_faction(f, rp->want); } - if (!faction_id_is_unused(want)) { - a_remove(&f->attribs, a); - ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); - continue; + while (renum) { + rp = renum->next; + free(renum); + renum = rp; } - for (rn = &renum; *rn; rn = &(*rn)->next) { - if ((*rn)->want >= want) - break; - } - if (*rn && (*rn)->want == want) { - ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); - } else { - struct renum *r = calloc(sizeof(struct renum), 1); - r->next = *rn; - r->attrib = a; - r->faction = f; - r->want = want; - *rn = r; - } - } - for (rp = renum; rp; rp = rp->next) { - f = rp->faction; - a_remove(&f->attribs, rp->attrib); - renumber_faction(f, rp->want); - } - while (renum) { - rp = renum->next; - free(renum); - renum = rp; - } } void restack_units(void) { - region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; - bool sorted = false; - while (*up) { - unit *u = *up; - if (!fval(u, UFL_MARK)) { - struct order *ord; - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_SORT) { - const char *s; - param_t p; - int id; - unit *v; + region *r; + for (r = regions; r; r = r->next) { + unit **up = &r->units; + bool sorted = false; + while (*up) { + unit *u = *up; + if (!fval(u, UFL_MARK)) { + struct order *ord; + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_SORT) { + const char *s; + param_t p; + int id; + unit *v; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - p = findparam(s, u->faction->locale); - id = getid(); - v = findunit(id); + init_tokens(ord); + skip_token(); + s = getstrtoken(); + p = findparam(s, u->faction->locale); + id = getid(); + v = findunit(id); - if (!v || v->faction != u->faction || v->region != r) { - cmistake(u, ord, 258, MSG_EVENT); - } else if (v->building != u->building || v->ship != u->ship) { - cmistake(u, ord, 259, MSG_EVENT); - } else if (u->building && building_owner(u->building)==u) { - cmistake(u, ord, 260, MSG_EVENT); - } else if (u->ship && ship_owner(u->ship)==u) { - cmistake(u, ord, 260, MSG_EVENT); - } else if (v == u) { - cmistake(u, ord, 10, MSG_EVENT); - } else { - switch (p) { - case P_AFTER: - *up = u->next; - u->next = v->next; - v->next = u; - fset(u, UFL_MARK); - sorted = true; - break; - case P_BEFORE: - if (v->ship && ship_owner(v->ship)==v) { - cmistake(v, ord, 261, MSG_EVENT); - } else if (v->building && building_owner(v->building)==v) { - cmistake(v, ord, 261, MSG_EVENT); - } else { - unit **vp = &r->units; - while (*vp != v) - vp = &(*vp)->next; - *vp = u; - *up = u->next; - u->next = v; + if (!v || v->faction != u->faction || v->region != r) { + cmistake(u, ord, 258, MSG_EVENT); + } + else if (v->building != u->building || v->ship != u->ship) { + cmistake(u, ord, 259, MSG_EVENT); + } + else if (u->building && building_owner(u->building) == u) { + cmistake(u, ord, 260, MSG_EVENT); + } + else if (u->ship && ship_owner(u->ship) == u) { + cmistake(u, ord, 260, MSG_EVENT); + } + else if (v == u) { + cmistake(u, ord, 10, MSG_EVENT); + } + else { + switch (p) { + case P_AFTER: + *up = u->next; + u->next = v->next; + v->next = u; + fset(u, UFL_MARK); + sorted = true; + break; + case P_BEFORE: + if (v->ship && ship_owner(v->ship) == v) { + cmistake(v, ord, 261, MSG_EVENT); + } + else if (v->building && building_owner(v->building) == v) { + cmistake(v, ord, 261, MSG_EVENT); + } + else { + unit **vp = &r->units; + while (*vp != v) + vp = &(*vp)->next; + *vp = u; + *up = u->next; + u->next = v; + } + fset(u, UFL_MARK); + sorted = true; + break; + default: + /* TODO: syntax error message? */ + break; + } + } + break; + } } - fset(u, UFL_MARK); - sorted = true; - break; - default: - /* TODO: syntax error message? */ - break; - } } - break; - } + if (u == *up) + up = &u->next; + } + if (sorted) { + unit *u; + for (u = r->units; u; u = u->next) { + freset(u, UFL_MARK); + } } - } - if (u == *up) - up = &u->next; } - if (sorted) { - unit *u; - for (u = r->units; u; u = u->next) { - freset(u, UFL_MARK); - } - } - } } int renumber_cmd(unit * u, order * ord) { - const char *s; - int i; - faction *f = u->faction; + const char *s; + int i; + faction *f = u->faction; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - switch (findparam_ex(s, u->faction->locale)) { - - case P_FACTION: + init_tokens(ord); + skip_token(); s = getstrtoken(); - if (s && *s) { - int id = atoi36((const char *)s); - attrib *a = a_find(f->attribs, &at_number); - if (!a) - a = a_add(&f->attribs, a_new(&at_number)); - a->data.i = id; - } - break; + switch (findparam_ex(s, u->faction->locale)) { - case P_UNIT: - s = getstrtoken(); - if (s == NULL || *s == 0) { - i = newunitid(); - } else { - i = atoi36((const char *)s); - if (i <= 0 || i > MAX_UNIT_NR) { - cmistake(u, ord, 114, MSG_EVENT); + case P_FACTION: + s = getstrtoken(); + if (s && *s) { + int id = atoi36((const char *)s); + attrib *a = a_find(f->attribs, &at_number); + if (!a) + a = a_add(&f->attribs, a_new(&at_number)); + a->data.i = id; + } break; - } - if (forbiddenid(i)) { - cmistake(u, ord, 116, MSG_EVENT); - break; - } + case P_UNIT: + s = getstrtoken(); + if (s == NULL || *s == 0) { + i = newunitid(); + } + else { + i = atoi36((const char *)s); + if (i <= 0 || i > MAX_UNIT_NR) { + cmistake(u, ord, 114, MSG_EVENT); + break; + } - if (findunitg(i, u->region)) { - cmistake(u, ord, 115, MSG_EVENT); - break; - } - } - uunhash(u); - if (!ualias(u)) { - attrib *a = a_add(&u->attribs, a_new(&at_alias)); - a->data.i = -u->no; - } - u->no = i; - uhash(u); - break; + if (forbiddenid(i)) { + cmistake(u, ord, 116, MSG_EVENT); + break; + } - case P_SHIP: - if (!u->ship) { - cmistake(u, ord, 144, MSG_EVENT); - break; - } - if (ship_owner(u->ship)!=u) { - cmistake(u, ord, 146, MSG_EVENT); - break; - } - if (u->ship->coast != NODIRECTION) { - cmistake(u, ord, 116, MSG_EVENT); - break; - } - s = getstrtoken(); - if (s == NULL || *s == 0) { - i = newcontainerid(); - } else { - i = atoi36((const char *)s); - if (i <= 0 || i > MAX_CONTAINER_NR) { - cmistake(u, ord, 114, MSG_EVENT); + if (findunitg(i, u->region)) { + cmistake(u, ord, 115, MSG_EVENT); + break; + } + } + uunhash(u); + if (!ualias(u)) { + attrib *a = a_add(&u->attribs, a_new(&at_alias)); + a->data.i = -u->no; + } + u->no = i; + uhash(u); break; - } - if (findship(i) || findbuilding(i)) { - cmistake(u, ord, 115, MSG_EVENT); - break; - } - } - sunhash(u->ship); - u->ship->no = i; - shash(u->ship); - break; - case P_BUILDING: - case P_GEBAEUDE: - if (!u->building) { - cmistake(u, ord, 145, MSG_EVENT); - break; - } - if (building_owner(u->building)!=u) { - cmistake(u, ord, 148, MSG_EVENT); - break; - } - s = getstrtoken(); - if (*s == 0) { - i = newcontainerid(); - } else { - i = atoi36((const char *)s); - if (i <= 0 || i > MAX_CONTAINER_NR) { - cmistake(u, ord, 114, MSG_EVENT); - break; - } - if (findship(i) || findbuilding(i)) { - cmistake(u, ord, 115, MSG_EVENT); - break; - } - } - bunhash(u->building); - u->building->no = i; - bhash(u->building); - break; - default: - cmistake(u, ord, 239, MSG_EVENT); - } - return 0; + case P_SHIP: + if (!u->ship) { + cmistake(u, ord, 144, MSG_EVENT); + break; + } + if (ship_owner(u->ship) != u) { + cmistake(u, ord, 146, MSG_EVENT); + break; + } + if (u->ship->coast != NODIRECTION) { + cmistake(u, ord, 116, MSG_EVENT); + break; + } + s = getstrtoken(); + if (s == NULL || *s == 0) { + i = newcontainerid(); + } + else { + i = atoi36((const char *)s); + if (i <= 0 || i > MAX_CONTAINER_NR) { + cmistake(u, ord, 114, MSG_EVENT); + break; + } + if (findship(i) || findbuilding(i)) { + cmistake(u, ord, 115, MSG_EVENT); + break; + } + } + sunhash(u->ship); + u->ship->no = i; + shash(u->ship); + break; + case P_BUILDING: + case P_GEBAEUDE: + if (!u->building) { + cmistake(u, ord, 145, MSG_EVENT); + break; + } + if (building_owner(u->building) != u) { + cmistake(u, ord, 148, MSG_EVENT); + break; + } + s = getstrtoken(); + if (*s == 0) { + i = newcontainerid(); + } + else { + i = atoi36((const char *)s); + if (i <= 0 || i > MAX_CONTAINER_NR) { + cmistake(u, ord, 114, MSG_EVENT); + break; + } + if (findship(i) || findbuilding(i)) { + cmistake(u, ord, 115, MSG_EVENT); + break; + } + } + bunhash(u->building); + u->building->no = i; + bhash(u->building); + break; + + default: + cmistake(u, ord, 239, MSG_EVENT); + } + return 0; } static building *age_building(building * b) @@ -3263,214 +3332,217 @@ static building *age_building(building * b) bt_blessed = bt_find("blessedstonecircle"); ct_astralblock = ct_find("astralblock"); - /* blesses stone circles create an astral protection in the astral region - * above the shield, which prevents chaos suction and other spells. - * The shield is created when a magician enters the blessed stone circle, - * and lasts for as long as his skill level / 2 is, at no mana cost. - * - * TODO: this would be nicer in a btype->age function, but we don't have it. - */ - if (rtype && ct_astralblock && bt_blessed && b->type == bt_blessed) { - region *r = b->region; - region *rt = r_standard_to_astral(r); - unit *u, *mage = NULL; + /* blesses stone circles create an astral protection in the astral region + * above the shield, which prevents chaos suction and other spells. + * The shield is created when a magician enters the blessed stone circle, + * and lasts for as long as his skill level / 2 is, at no mana cost. + * + * TODO: this would be nicer in a btype->age function, but we don't have it. + */ + if (rtype && ct_astralblock && bt_blessed && b->type == bt_blessed) { + region *r = b->region; + region *rt = r_standard_to_astral(r); + unit *u, *mage = NULL; - /* step 1: give unicorns to people in the building, - * find out if there's a magician in there. */ - for (u = r->units; u; u = u->next) { - if (b == u->building && inside_building(u)) { - if (!(u_race(u)->ec_flags & GIVEITEM) == 0) { - int n, unicorns = 0; - for (n = 0; n != u->number; ++n) { - if (chance(0.02)) { - i_change(&u->items, rtype->itype, 1); - ++unicorns; + /* step 1: give unicorns to people in the building, + * find out if there's a magician in there. */ + for (u = r->units; u; u = u->next) { + if (b == u->building && inside_building(u)) { + if (!(u_race(u)->ec_flags & GIVEITEM) == 0) { + int n, unicorns = 0; + for (n = 0; n != u->number; ++n) { + if (chance(0.02)) { + i_change(&u->items, rtype->itype, 1); + ++unicorns; + } + if (unicorns) { + ADDMSG(&u->faction->msgs, msg_message("scunicorn", + "unit amount rtype", + u, unicorns, rtype)); + } + } + } + if (mage == NULL && is_mage(u)) { + mage = u; + } } - if (unicorns) { - ADDMSG(&u->faction->msgs, msg_message("scunicorn", - "unit amount rtype", - u, unicorns, rtype)); + } + + /* if there's a magician, and a connection to astral space, create the + * curse. */ + if (rt && !fval(rt->terrain, FORBIDDEN_REGION) && mage != NULL) { + curse *c = get_curse(rt->attribs, ct_astralblock); + if (c == NULL) { + if (mage != NULL) { + int sk = effskill(mage, SK_MAGIC); + float effect = 100; + /* the mage reactivates the circle */ + c = create_curse(mage, &rt->attribs, ct_astralblock, + (float)_max(1, sk), _max(1, sk / 2), effect, 0); + ADDMSG(&r->msgs, + msg_message("astralshield_activate", "region unit", r, mage)); + } + } + else if (mage != NULL) { + int sk = effskill(mage, SK_MAGIC); + c->duration = _max(c->duration, sk / 2); + c->vigour = _max(c->vigour, sk); } - } } - if (mage == NULL && is_mage(u)) { - mage = u; - } - } } - /* if there's a magician, and a connection to astral space, create the - * curse. */ - if (rt && !fval(rt->terrain, FORBIDDEN_REGION) && mage != NULL) { - curse *c = get_curse(rt->attribs, ct_astralblock); - if (c == NULL) { - if (mage != NULL) { - int sk = effskill(mage, SK_MAGIC); - float effect = 100; - /* the mage reactivates the circle */ - c = create_curse(mage, &rt->attribs, ct_astralblock, - (float)_max(1, sk), _max(1, sk / 2), effect, 0); - ADDMSG(&r->msgs, - msg_message("astralshield_activate", "region unit", r, mage)); - } - } else if (mage != NULL) { - int sk = effskill(mage, SK_MAGIC); - c->duration = _max(c->duration, sk / 2); - c->vigour = _max(c->vigour, sk); - } + a_age(&b->attribs); + handle_event(b->attribs, "timer", b); + + if (b->type->age) { + b->type->age(b); } - } - a_age(&b->attribs); - handle_event(b->attribs, "timer", b); - - if (b->type->age) { - b->type->age(b); - } - - return b; + return b; } static double rc_popularity(const struct race *rc) { - int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE); - return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */ + int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE); + return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */ } static void age_region(region * r) { - a_age(&r->attribs); - handle_event(r->attribs, "timer", r); + a_age(&r->attribs); + handle_event(r->attribs, "timer", r); - if (!r->land) - return; + if (!r->land) + return; - if (r->land->ownership && r->land->ownership->owner) { - int stability = turn - r->land->ownership->morale_turn; - int maxmorale = MORALE_DEFAULT; - building *b = largestbuilding(r, &cmp_taxes, false); - if (b) { - int bsize = buildingeffsize(b, false); - maxmorale = (int)(0.5 + b->type->taxes(b, bsize + 1) / MORALE_TAX_FACTOR); - } - if (r->land->morale < maxmorale) { - if (stability > MORALE_COOLDOWN && r->land->ownership->owner - && r->land->morale < MORALE_MAX) { - double ch = rc_popularity(r->land->ownership->owner->race); - if (is_cursed(r->attribs, C_GENEROUS, 0)) { - ch *= 1.2; /* 20% improvement */ + if (r->land->ownership && r->land->ownership->owner) { + int stability = turn - r->land->ownership->morale_turn; + int maxmorale = MORALE_DEFAULT; + building *b = largestbuilding(r, &cmp_taxes, false); + if (b) { + int bsize = buildingeffsize(b, false); + maxmorale = (int)(0.5 + b->type->taxes(b, bsize + 1) / MORALE_TAX_FACTOR); } - if (stability >= MORALE_AVERAGE * 2 || chance(ch)) { - region_set_morale(r, r->land->morale + 1, turn); + if (r->land->morale < maxmorale) { + if (stability > MORALE_COOLDOWN && r->land->ownership->owner + && r->land->morale < MORALE_MAX) { + double ch = rc_popularity(r->land->ownership->owner->race); + if (is_cursed(r->attribs, C_GENEROUS, 0)) { + ch *= 1.2; /* 20% improvement */ + } + if (stability >= MORALE_AVERAGE * 2 || chance(ch)) { + region_set_morale(r, r->land->morale + 1, turn); + } + } + } + else if (r->land->morale > maxmorale) { + region_set_morale(r, r->land->morale - 1, turn); } - } - } else if (r->land->morale > maxmorale) { - region_set_morale(r, r->land->morale - 1, turn); } - } else if (r->land->morale > MORALE_DEFAULT) { - region_set_morale(r, r->land->morale - 1, turn); - } + else if (r->land->morale > MORALE_DEFAULT) { + region_set_morale(r, r->land->morale - 1, turn); + } } static void ageing(void) { - faction *f; - region *r; + faction *f; + region *r; - /* altern spezieller Attribute, die eine Sonderbehandlung brauchen? */ - for (r = regions; r; r = r->next) { - unit *u; + /* altern spezieller Attribute, die eine Sonderbehandlung brauchen? */ + for (r = regions; r; r = r->next) { + unit *u; - for (u = r->units; u; u = u->next) { - /* Goliathwasser */ - int i = get_effect(u, oldpotiontype[P_STRONG]); - if (i > 0) { - change_effect(u, oldpotiontype[P_STRONG], -1 * _min(u->number, i)); - } - /* Berserkerblut */ - i = get_effect(u, oldpotiontype[P_BERSERK]); - if (i > 0) { - change_effect(u, oldpotiontype[P_BERSERK], -1 * _min(u->number, i)); - } + for (u = r->units; u; u = u->next) { + /* Goliathwasser */ + int i = get_effect(u, oldpotiontype[P_STRONG]); + if (i > 0) { + change_effect(u, oldpotiontype[P_STRONG], -1 * _min(u->number, i)); + } + /* Berserkerblut */ + i = get_effect(u, oldpotiontype[P_BERSERK]); + if (i > 0) { + change_effect(u, oldpotiontype[P_BERSERK], -1 * _min(u->number, i)); + } - if (is_cursed(u->attribs, C_OLDRACE, 0)) { - curse *c = get_curse(u->attribs, ct_find("oldrace")); - if (c->duration == 1 && !(c_flags(c) & CURSE_NOAGE)) { - u_setrace(u, get_race(curse_geteffect_int(c))); - u->irace = NULL; + if (is_cursed(u->attribs, C_OLDRACE, 0)) { + curse *c = get_curse(u->attribs, ct_find("oldrace")); + if (c->duration == 1 && !(c_flags(c) & CURSE_NOAGE)) { + u_setrace(u, get_race(curse_geteffect_int(c))); + u->irace = NULL; + } + } } - } - } - } - - /* Borders */ - age_borders(); - - /* Factions */ - for (f = factions; f; f = f->next) { - a_age(&f->attribs); - handle_event(f->attribs, "timer", f); - } - - /* Regionen */ - for (r = regions; r; r = r->next) { - building **bp; - unit **up; - ship **sp; - - age_region(r); - - /* Einheiten */ - for (up = &r->units; *up;) { - unit *u = *up; - a_age(&u->attribs); - if (u == *up) - handle_event(u->attribs, "timer", u); - if (u == *up) - up = &(*up)->next; } - /* Schiffe */ - for (sp = &r->ships; *sp;) { - ship *s = *sp; - a_age(&s->attribs); - if (s == *sp) - handle_event(s->attribs, "timer", s); - if (s == *sp) - sp = &(*sp)->next; + /* Borders */ + age_borders(); + + /* Factions */ + for (f = factions; f; f = f->next) { + a_age(&f->attribs); + handle_event(f->attribs, "timer", f); } - /* Gebäude */ - for (bp = &r->buildings; *bp;) { - building *b = *bp; - age_building(b); - if (b == *bp) - bp = &b->next; - } + /* Regionen */ + for (r = regions; r; r = r->next) { + building **bp; + unit **up; + ship **sp; - if (rule_region_owners()) { - update_owners(r); + age_region(r); + + /* Einheiten */ + for (up = &r->units; *up;) { + unit *u = *up; + a_age(&u->attribs); + if (u == *up) + handle_event(u->attribs, "timer", u); + if (u == *up) + up = &(*up)->next; + } + + /* Schiffe */ + for (sp = &r->ships; *sp;) { + ship *s = *sp; + a_age(&s->attribs); + if (s == *sp) + handle_event(s->attribs, "timer", s); + if (s == *sp) + sp = &(*sp)->next; + } + + /* Gebäude */ + for (bp = &r->buildings; *bp;) { + building *b = *bp; + age_building(b); + if (b == *bp) + bp = &b->next; + } + + if (rule_region_owners()) { + update_owners(r); + } } - } } static int maxunits(const faction * f) { - int flimit = rule_faction_limit(); - int alimit = rule_alliance_limit(); - if (alimit == 0) { - return flimit; - } - if (flimit == 0) { - return alimit; - } - return _min(alimit, flimit); + int flimit = rule_faction_limit(); + int alimit = rule_alliance_limit(); + if (alimit == 0) { + return flimit; + } + if (flimit == 0) { + return alimit; + } + return _min(alimit, flimit); } int checkunitnumber(const faction * f, int add) { int alimit, flimit; - int flags = COUNT_DEFAULT|COUNT_MIGRANTS|COUNT_UNITS; + int flags = COUNT_DEFAULT | COUNT_MIGRANTS | COUNT_UNITS; int fno = count_faction(f, flags) + add; flimit = rule_faction_limit(); if (flimit && fno > flimit) { @@ -3502,389 +3574,399 @@ int checkunitnumber(const faction * f, int add) void new_units(void) { - region *r; - unit *u, *u2; + region *r; + unit *u, *u2; - /* neue einheiten werden gemacht und ihre befehle (bis zum "ende" zu - * ihnen rueberkopiert, damit diese einheiten genauso wie die alten - * einheiten verwendet werden koennen. */ + /* neue einheiten werden gemacht und ihre befehle (bis zum "ende" zu + * ihnen rueberkopiert, damit diese einheiten genauso wie die alten + * einheiten verwendet werden koennen. */ - for (r = regions; r; r = r->next) { - for (u = r->units; u; u = u->next) { - order **ordp = &u->orders; + for (r = regions; r; r = r->next) { + for (u = r->units; u; u = u->next) { + order **ordp = &u->orders; - /* this needs to happen very early in the game somewhere. since this is - ** pretty much the first function called per turn, and I am lazy, I - ** decree that it goes here */ - if (u->flags & UFL_GUARD) { - fset(r, RF_GUARDED); - } - - while (*ordp) { - order *makeord = *ordp; - if (getkeyword(makeord) == K_MAKE) { - init_tokens(makeord); - skip_token(); - if (isparam(getstrtoken(), u->faction->locale, P_TEMP)) { - const char *token; - char *name = NULL; - int alias; - ship *sh; - order **newordersp; - int err = checkunitnumber(u->faction, 1); - - if (err) { - if (err == 1) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, makeord, - "too_many_units_in_alliance", - "allowed", maxunits(u->faction))); - } else { - ADDMSG(&u->faction->msgs, - msg_feedback(u, makeord, - "too_many_units_in_faction", - "allowed", maxunits(u->faction))); - } - ordp = &makeord->next; - - while (*ordp) { - order *ord = *ordp; - if (getkeyword(ord) == K_END) - break; - *ordp = ord->next; - ord->next = NULL; - free_order(ord); - } - continue; + /* this needs to happen very early in the game somewhere. since this is + ** pretty much the first function called per turn, and I am lazy, I + ** decree that it goes here */ + if (u->flags & UFL_GUARD) { + fset(r, RF_GUARDED); } - alias = getid(); - token = getstrtoken(); - if (token && token[0]) { - name = _strdup(token); - } - u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u); - if (name != NULL) - free(name); - fset(u2, UFL_ISNEW); - - a_add(&u2->attribs, a_new(&at_alias))->data.i = alias; - sh = leftship(u); - if (sh) { - set_leftship(u2, sh); - } - setstatus(u2, u->status); - - ordp = &makeord->next; - newordersp = &u2->orders; while (*ordp) { - order *ord = *ordp; - if (getkeyword(ord) == K_END) - break; - *ordp = ord->next; - ord->next = NULL; - *newordersp = ord; - newordersp = &ord->next; + order *makeord = *ordp; + if (getkeyword(makeord) == K_MAKE) { + init_tokens(makeord); + skip_token(); + if (isparam(getstrtoken(), u->faction->locale, P_TEMP)) { + const char *token; + char *name = NULL; + int alias; + ship *sh; + order **newordersp; + int err = checkunitnumber(u->faction, 1); + + if (err) { + if (err == 1) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, makeord, + "too_many_units_in_alliance", + "allowed", maxunits(u->faction))); + } + else { + ADDMSG(&u->faction->msgs, + msg_feedback(u, makeord, + "too_many_units_in_faction", + "allowed", maxunits(u->faction))); + } + ordp = &makeord->next; + + while (*ordp) { + order *ord = *ordp; + if (getkeyword(ord) == K_END) + break; + *ordp = ord->next; + ord->next = NULL; + free_order(ord); + } + continue; + } + alias = getid(); + + token = getstrtoken(); + if (token && token[0]) { + name = _strdup(token); + } + u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u); + if (name != NULL) + free(name); + fset(u2, UFL_ISNEW); + + a_add(&u2->attribs, a_new(&at_alias))->data.i = alias; + sh = leftship(u); + if (sh) { + set_leftship(u2, sh); + } + setstatus(u2, u->status); + + ordp = &makeord->next; + newordersp = &u2->orders; + while (*ordp) { + order *ord = *ordp; + if (getkeyword(ord) == K_END) + break; + *ordp = ord->next; + ord->next = NULL; + *newordersp = ord; + newordersp = &ord->next; + } + } + } + if (*ordp == makeord) + ordp = &makeord->next; } - } } - if (*ordp == makeord) - ordp = &makeord->next; - } } - } } /** Checks for two long orders and issues a warning if necessary. */ void check_long_orders(unit * u) { - order *ord; - keyword_t otherorder = MAXKEYWORDS; + order *ord; + keyword_t otherorder = MAXKEYWORDS; - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == NOKEYWORD) { - cmistake(u, ord, 22, MSG_EVENT); - } else if (is_long(ord)) { - keyword_t longorder = getkeyword(ord); - if (otherorder != MAXKEYWORDS) { - switch (longorder) { - case K_CAST: - if (otherorder != longorder) { - cmistake(u, ord, 52, MSG_EVENT); - } - break; - case K_BUY: - if (otherorder == K_SELL) { - otherorder = K_BUY; - } else { - cmistake(u, ord, 52, MSG_EVENT); - } - break; - case K_SELL: - if (otherorder != K_SELL && otherorder != K_BUY) { - cmistake(u, ord, 52, MSG_EVENT); - } - break; - default: - cmistake(u, ord, 52, MSG_EVENT); + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == NOKEYWORD) { + cmistake(u, ord, 22, MSG_EVENT); + } + else if (is_long(ord)) { + keyword_t longorder = getkeyword(ord); + if (otherorder != MAXKEYWORDS) { + switch (longorder) { + case K_CAST: + if (otherorder != longorder) { + cmistake(u, ord, 52, MSG_EVENT); + } + break; + case K_BUY: + if (otherorder == K_SELL) { + otherorder = K_BUY; + } + else { + cmistake(u, ord, 52, MSG_EVENT); + } + break; + case K_SELL: + if (otherorder != K_SELL && otherorder != K_BUY) { + cmistake(u, ord, 52, MSG_EVENT); + } + break; + default: + cmistake(u, ord, 52, MSG_EVENT); + } + } + else { + otherorder = longorder; + } } - } else { - otherorder = longorder; - } } - } } void update_long_order(unit * u) { - order *ord; - bool trade = false; - bool hunger = LongHunger(u); + order *ord; + bool trade = false; + bool hunger = LongHunger(u); - freset(u, UFL_MOVED); - freset(u, UFL_LONGACTION); - if (hunger) { - /* Hungernde Einheiten führen NUR den default-Befehl aus */ - set_order(&u->thisorder, default_order(u->faction->locale)); - } else { - check_long_orders(u); - } - /* check all orders for a potential new long order this round: */ - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == NOKEYWORD) - continue; - - if (u->old_orders && is_repeated(ord)) { - /* this new order will replace the old defaults */ - free_orders(&u->old_orders); - if (hunger) - break; - } - if (hunger) - continue; - - if (is_exclusive(ord)) { - /* Über dieser Zeile nur Befehle, die auch eine idle Faction machen darf */ - if (idle(u->faction)) { + freset(u, UFL_MOVED); + freset(u, UFL_LONGACTION); + if (hunger) { + /* Hungernde Einheiten führen NUR den default-Befehl aus */ set_order(&u->thisorder, default_order(u->faction->locale)); - } else { - set_order(&u->thisorder, copy_order(ord)); - } - break; - } else { - keyword_t keyword = getkeyword(ord); - switch (keyword) { - /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt - * werden. Da Handel erst nach anderen langen Befehlen kommt, - * muß das vorher abgefangen werden. Wir merken uns also - * hier, ob die Einheit handelt. */ - case K_BUY: - case K_SELL: - /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht - * werden. - * Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen - * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern - * nicht moeglich ist, Schulden zu machen. */ - trade = true; - break; - - case K_CAST: - /* dient dazu, das neben Zaubern kein weiterer Befehl - * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */ - set_order(&u->thisorder, copy_order(ord)); - break; - - default: - break; - } } - } + else { + check_long_orders(u); + } + /* check all orders for a potential new long order this round: */ + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == NOKEYWORD) + continue; - if (hunger) { - return; - } - /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht - * werden. */ + if (u->old_orders && is_repeated(ord)) { + /* this new order will replace the old defaults */ + free_orders(&u->old_orders); + if (hunger) + break; + } + if (hunger) + continue; - if (trade) { - /* fset(u, UFL_LONGACTION|UFL_NOTMOVING); */ - set_order(&u->thisorder, NULL); - } + if (is_exclusive(ord)) { + /* Über dieser Zeile nur Befehle, die auch eine idle Faction machen darf */ + if (idle(u->faction)) { + set_order(&u->thisorder, default_order(u->faction->locale)); + } + else { + set_order(&u->thisorder, copy_order(ord)); + } + break; + } + else { + keyword_t keyword = getkeyword(ord); + switch (keyword) { + /* Wenn gehandelt wird, darf kein langer Befehl ausgeführt + * werden. Da Handel erst nach anderen langen Befehlen kommt, + * muß das vorher abgefangen werden. Wir merken uns also + * hier, ob die Einheit handelt. */ + case K_BUY: + case K_SELL: + /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht + * werden. + * Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen + * mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern + * nicht moeglich ist, Schulden zu machen. */ + trade = true; + break; + + case K_CAST: + /* dient dazu, das neben Zaubern kein weiterer Befehl + * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */ + set_order(&u->thisorder, copy_order(ord)); + break; + + default: + break; + } + } + } + + if (hunger) { + return; + } + /* Wenn die Einheit handelt, muß der Default-Befehl gelöscht + * werden. */ + + if (trade) { + /* fset(u, UFL_LONGACTION|UFL_NOTMOVING); */ + set_order(&u->thisorder, NULL); + } } static int use_item(unit * u, const item_type * itype, int amount, struct order *ord) { - int i; - int target = read_unitid(u->faction, u->region); + int i; + int target = read_unitid(u->faction, u->region); - i = get_pooled(u, itype->rtype, GET_DEFAULT, amount); + i = get_pooled(u, itype->rtype, GET_DEFAULT, amount); - if (amount > i) { - amount = i; - } - if (amount == 0) { - return ENOITEM; - } - - if (target == -1) { - if (itype->use == NULL) { - return EUNUSABLE; + if (amount > i) { + amount = i; } - return itype->use(u, itype, amount, ord); - } else { - if (itype->useonother == NULL) { - return EUNUSABLE; + if (amount == 0) { + return ENOITEM; + } + + if (target == -1) { + if (itype->use == NULL) { + return EUNUSABLE; + } + return itype->use(u, itype, amount, ord); + } + else { + if (itype->useonother == NULL) { + return EUNUSABLE; + } + return itype->useonother(u, target, itype, amount, ord); } - return itype->useonother(u, target, itype, amount, ord); - } } static double heal_factor(const unit * u) { - static float elf_regen = -1; - switch (old_race(u_race(u))) { - case RC_TROLL: - case RC_DAEMON: - return 1.5; - case RC_GOBLIN: - return 2.0; - case RC_ELF: - if (elf_regen < 0) - elf_regen = get_param_flt(u_race(u)->parameters, "regen.forest", 1.0F); - if (elf_regen != 1.0 && r_isforest(u->region)) { - return elf_regen; + static float elf_regen = -1; + switch (old_race(u_race(u))) { + case RC_TROLL: + case RC_DAEMON: + return 1.5; + case RC_GOBLIN: + return 2.0; + case RC_ELF: + if (elf_regen < 0) + elf_regen = get_param_flt(u_race(u)->parameters, "regen.forest", 1.0F); + if (elf_regen != 1.0 && r_isforest(u->region)) { + return elf_regen; + } + return 1.0; + default: + return 1.0; } - return 1.0; - default: - return 1.0; - } } void monthly_healing(void) { - region *r; - static const curse_type *heal_ct = NULL; - if (heal_ct == NULL) - heal_ct = ct_find("healingzone"); + region *r; + static const curse_type *heal_ct = NULL; + if (heal_ct == NULL) + heal_ct = ct_find("healingzone"); - for (r = regions; r; r = r->next) { - unit *u; - double healingcurse = 0; + for (r = regions; r; r = r->next) { + unit *u; + double healingcurse = 0; - if (heal_ct != NULL) { - /* bonus zurücksetzen */ - curse *c = get_curse(r->attribs, heal_ct); - if (c != NULL) { - healingcurse = curse_geteffect(c); - } - } - for (u = r->units; u; u = u->next) { - int umhp = unit_max_hp(u) * u->number; - double p = 1.0; - - /* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht - * oder verändertes Ausdauertalent verursacht */ - if (u->hp > umhp) { - u->hp -= (int)ceil((u->hp - umhp) / 2.0); - if (u->hp < umhp) - u->hp = umhp; - continue; - } - - if (u_race(u)->flags & RCF_NOHEAL) - continue; - if (fval(u, UFL_HUNGER)) - continue; - - if (fval(r->terrain, SEA_REGION) && u->ship == NULL - && !(canswim(u) || canfly(u))) { - continue; - } - - p *= heal_factor(u); - if (u->hp < umhp) { -#ifdef NEW_DAEMONHUNGER_RULE - double maxheal = _max(u->number, umhp / 20.0); -#else - double maxheal = _max(u->number, umhp / 10.0); -#endif - int addhp; - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - if (btype == bt_find("inn")) { - p *= 1.5; + if (heal_ct != NULL) { + /* bonus zurücksetzen */ + curse *c = get_curse(r->attribs, heal_ct); + if (c != NULL) { + healingcurse = curse_geteffect(c); + } } - /* pro punkt 5% höher */ - p *= (1.0 + healingcurse * 0.05); + for (u = r->units; u; u = u->next) { + int umhp = unit_max_hp(u) * u->number; + double p = 1.0; - maxheal = p * maxheal; - addhp = (int)maxheal; - maxheal -= addhp; - if (maxheal > 0.0 && chance(maxheal)) - ++addhp; + /* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht + * oder verändertes Ausdauertalent verursacht */ + if (u->hp > umhp) { + u->hp -= (int)ceil((u->hp - umhp) / 2.0); + if (u->hp < umhp) + u->hp = umhp; + continue; + } - /* Aufaddieren der geheilten HP. */ - u->hp = _min(u->hp + addhp, umhp); + if (u_race(u)->flags & RCF_NOHEAL) + continue; + if (fval(u, UFL_HUNGER)) + continue; - /* soll man an negativer regeneration sterben können? */ - assert(u->hp > 0); - } + if (fval(r->terrain, SEA_REGION) && u->ship == NULL + && !(canswim(u) || canfly(u))) { + continue; + } + + p *= heal_factor(u); + if (u->hp < umhp) { +#ifdef NEW_DAEMONHUNGER_RULE + double maxheal = _max(u->number, umhp / 20.0); +#else + double maxheal = _max(u->number, umhp / 10.0); +#endif + int addhp; + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + if (btype == bt_find("inn")) { + p *= 1.5; + } + /* pro punkt 5% höher */ + p *= (1.0 + healingcurse * 0.05); + + maxheal = p * maxheal; + addhp = (int)maxheal; + maxheal -= addhp; + if (maxheal > 0.0 && chance(maxheal)) + ++addhp; + + /* Aufaddieren der geheilten HP. */ + u->hp = _min(u->hp + addhp, umhp); + + /* soll man an negativer regeneration sterben können? */ + assert(u->hp > 0); + } + } } - } } static void remove_exclusive(order ** ordp) { - while (*ordp) { - order *ord = *ordp; - if (is_exclusive(ord)) { - *ordp = ord->next; - ord->next = NULL; - free_order(ord); - } else { - ordp = &ord->next; + while (*ordp) { + order *ord = *ordp; + if (is_exclusive(ord)) { + *ordp = ord->next; + ord->next = NULL; + free_order(ord); + } + else { + ordp = &ord->next; + } } - } } void defaultorders(void) { - region *r; + region *r; - assert(!keyword_disabled(K_DEFAULT)); - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - bool neworders = false; - order **ordp = &u->orders; - while (*ordp != NULL) { - order *ord = *ordp; - if (getkeyword(ord) == K_DEFAULT) { - char lbuf[8192]; - order *new_order; - init_tokens(ord); - skip_token(); /* skip the keyword */ - strcpy(lbuf, getstrtoken()); - new_order = parse_order(lbuf, u->faction->locale); - *ordp = ord->next; - ord->next = NULL; - free_order(ord); - if (!neworders) { - /* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */ - remove_exclusive(&u->orders); - remove_exclusive(&u->old_orders); - neworders = true; - ordp = &u->orders; /* we could have broken ordp */ - } - if (new_order) - addlist(&u->old_orders, new_order); - } else - ordp = &ord->next; - } + assert(!keyword_disabled(K_DEFAULT)); + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + bool neworders = false; + order **ordp = &u->orders; + while (*ordp != NULL) { + order *ord = *ordp; + if (getkeyword(ord) == K_DEFAULT) { + char lbuf[8192]; + order *new_order; + init_tokens(ord); + skip_token(); /* skip the keyword */ + strcpy(lbuf, getstrtoken()); + new_order = parse_order(lbuf, u->faction->locale); + *ordp = ord->next; + ord->next = NULL; + free_order(ord); + if (!neworders) { + /* lange Befehle aus orders und old_orders löschen zu gunsten des neuen */ + remove_exclusive(&u->orders); + remove_exclusive(&u->old_orders); + neworders = true; + ordp = &u->orders; /* we could have broken ordp */ + } + if (new_order) + addlist(&u->old_orders, new_order); + } + else + ordp = &ord->next; + } + } } - } } /* ************************************************************ */ @@ -3896,177 +3978,181 @@ void defaultorders(void) static int faction_getmages(faction * f, unit ** results, int numresults) { - unit *u; - int maxlevel = 0, n = 0; + unit *u; + int maxlevel = 0, n = 0; - for (u = f->units; u; u = u->nextF) { - if (u->number > 0) { - sc_mage *mage = get_mage(u); - if (mage) { - int level = eff_skill(u, SK_MAGIC, u->region); - if (level > maxlevel) { - maxlevel = level; + for (u = f->units; u; u = u->nextF) { + if (u->number > 0) { + sc_mage *mage = get_mage(u); + if (mage) { + int level = eff_skill(u, SK_MAGIC, u->region); + if (level > maxlevel) { + maxlevel = level; + } + if (n < numresults) { + results[n++] = u; + } + } } - if (nspells) { - quicklist *ql; - int qi; - for (qi = 0, ql = src->spells; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *)ql_get(ql, qi); - if (sbe->level<=maxlevel) { - if (!spellbook_get(dst, sbe->sp)) { - spellbook_add(dst, sbe->sp, sbe->level); + assert(dst); + if (src && src->spells) { + quicklist *ql; + int qi; + for (qi = 0, ql = src->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry * sbe = (spellbook_entry *)ql_get(ql, qi); + if (sbe->level <= maxlevel) { + if (!spellbook_get(dst, sbe->sp)) { + spellbook_add(dst, sbe->sp, sbe->level); + } + } } - } } - } } static void update_spells(void) { - faction *f; + faction *f; - for (f = factions; f; f = f->next) { - if (f->magiegebiet != M_NONE && !is_monsters(f)) { - unit *mages[MAXMAGES]; - int i; - int maxlevel = faction_getmages(f, mages, MAXMAGES); + for (f = factions; f; f = f->next) { + if (f->magiegebiet != M_NONE && !is_monsters(f)) { + unit *mages[MAXMAGES]; + int i; + int maxlevel = faction_getmages(f, mages, MAXMAGES); - if (maxlevel && FactionSpells()) { - spellbook * book = get_spellbook(magic_school[f->magiegebiet]); - if (!f->spellbook) { - f->spellbook = create_spellbook(0); + if (maxlevel && FactionSpells()) { + spellbook * book = get_spellbook(magic_school[f->magiegebiet]); + if (!f->spellbook) { + f->spellbook = create_spellbook(0); + } + copy_spells(book, f->spellbook, maxlevel); + if (maxlevel > f->max_spelllevel) { + spellbook * common_spells = get_spellbook(magic_school[M_COMMON]); + pick_random_spells(f, maxlevel, common_spells, COMMONSPELLS); + } + } + show_new_spells(f, maxlevel, faction_get_spellbook(f)); + for (i = 0; i != MAXMAGES && mages[i]; ++i) { + unit * u = mages[i]; + sc_mage *mage = get_mage(u); + if (mage && mage->spellbook) { + int level = effskill(u, SK_MAGIC); + show_new_spells(f, level, mage->spellbook); + } + } } - copy_spells(book, f->spellbook, maxlevel); - if (maxlevel > f->max_spelllevel) { - spellbook * common_spells = get_spellbook(magic_school[M_COMMON]); - pick_random_spells(f, maxlevel, common_spells, COMMONSPELLS); - } - } - show_new_spells(f, maxlevel, faction_get_spellbook(f)); - for (i=0; i!=MAXMAGES && mages[i]; ++i) { - unit * u = mages[i]; - sc_mage *mage = get_mage(u); - if (mage && mage->spellbook) { - int level = effskill(u, SK_MAGIC); - show_new_spells(f, level, mage->spellbook); - } - } } - } } int use_cmd(unit * u, struct order *ord) { - const char *t; - int n, err = ENOITEM; - const item_type *itype; + const char *t; + int n, err = ENOITEM; + const item_type *itype; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - t = getstrtoken(); - n = atoi((const char *)t); - if (n == 0) { - if (isparam(t, u->faction->locale, P_ANY)) { - /* BENUTZE ALLES Yanxspirit */ - n = INT_MAX; - t = getstrtoken(); - } else { - /* BENUTZE Yanxspirit */ - n = 1; - } - } else { - /* BENUTZE 42 Yanxspirit */ t = getstrtoken(); - } - itype = finditemtype(t, u->faction->locale); - - if (itype != NULL) { - err = use_item(u, itype, n, ord); - assert(err <= 0 || !"use_item should not return positive values."); - if (err > 0) { - log_error("use_item returned a value>0 for %s\n", resourcename(itype->rtype, 0)); + n = atoi((const char *)t); + if (n == 0) { + if (isparam(t, u->faction->locale, P_ANY)) { + /* BENUTZE ALLES Yanxspirit */ + n = INT_MAX; + t = getstrtoken(); + } + else { + /* BENUTZE Yanxspirit */ + n = 1; + } } - } - switch (err) { - case ENOITEM: - cmistake(u, ord, 43, MSG_PRODUCE); - break; - case EUNUSABLE: - cmistake(u, ord, 76, MSG_PRODUCE); - break; - case ENOSKILL: - cmistake(u, ord, 50, MSG_PRODUCE); - break; - } - return err; + else { + /* BENUTZE 42 Yanxspirit */ + t = getstrtoken(); + } + itype = finditemtype(t, u->faction->locale); + + if (itype != NULL) { + err = use_item(u, itype, n, ord); + assert(err <= 0 || !"use_item should not return positive values."); + if (err > 0) { + log_error("use_item returned a value>0 for %s\n", resourcename(itype->rtype, 0)); + } + } + switch (err) { + case ENOITEM: + cmistake(u, ord, 43, MSG_PRODUCE); + break; + case EUNUSABLE: + cmistake(u, ord, 76, MSG_PRODUCE); + break; + case ENOSKILL: + cmistake(u, ord, 50, MSG_PRODUCE); + break; + } + return err; } int pay_cmd(unit * u, struct order *ord) { - if (!u->building) { - cmistake(u, ord, 6, MSG_EVENT); - } else { - param_t p; - init_tokens(ord); - skip_token(); - p = getparam(u->faction->locale); - if (p == P_NOT) { - unit *owner = building_owner(u->building); - if (owner->no != u->no) { - cmistake(u, ord, 1222, MSG_EVENT); - } else { - u->building->flags |= BLD_DONTPAY; - } + if (!u->building) { + cmistake(u, ord, 6, MSG_EVENT); } - } - return 0; + else { + param_t p; + init_tokens(ord); + skip_token(); + p = getparam(u->faction->locale); + if (p == P_NOT) { + unit *owner = building_owner(u->building); + if (owner->no != u->no) { + cmistake(u, ord, 1222, MSG_EVENT); + } + else { + u->building->flags |= BLD_DONTPAY; + } + } + } + return 0; } static int reserve_i(unit * u, struct order *ord, int flags) { - if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { - int use, count; - const resource_type *rtype; - const char *s; + if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { + int use, count; + const resource_type *rtype; + const char *s; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - count = atoip((const char *)s); + init_tokens(ord); + skip_token(); + s = getstrtoken(); + count = atoip((const char *)s); - if (count == 0 && findparam(s, u->faction->locale) == P_EACH) { - count = getint() * u->number; + if (count == 0 && findparam(s, u->faction->locale) == P_EACH) { + count = getint() * u->number; + } + + rtype = findresourcetype(getstrtoken(), u->faction->locale); + if (rtype == NULL) + return 0; + + set_resvalue(u, rtype, 0); /* make sure the pool is empty */ + use = use_pooled(u, rtype, flags, count); + if (use) { + set_resvalue(u, rtype, use); + change_resource(u, rtype, use); + return use; + } } - - rtype = findresourcetype(getstrtoken(), u->faction->locale); - if (rtype == NULL) - return 0; - - set_resvalue(u, rtype, 0); /* make sure the pool is empty */ - use = use_pooled(u, rtype, flags, count); - if (use) { - set_resvalue(u, rtype, use); - change_resource(u, rtype, use); - return use; - } - } - return 0; + return 0; } int reserve_cmd(unit * u, struct order *ord) { @@ -4079,258 +4165,264 @@ int reserve_self(unit * u, struct order *ord) { int claim_cmd(unit * u, struct order *ord) { - const char *t; - int n; - const item_type *itype; + const char *t; + int n; + const item_type *itype; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - t = getstrtoken(); - n = atoi((const char *)t); - if (n == 0) { - n = 1; - } else { t = getstrtoken(); - } - itype = finditemtype(t, u->faction->locale); - - if (itype != NULL) { - item **iclaim = i_find(&u->faction->items, itype); - if (iclaim != NULL && *iclaim != NULL) { - n = _min(n, (*iclaim)->number); - i_change(iclaim, itype, -n); - i_change(&u->items, itype, n); + n = atoi((const char *)t); + if (n == 0) { + n = 1; } - } else { - cmistake(u, ord, 43, MSG_PRODUCE); - } - return 0; + else { + t = getstrtoken(); + } + itype = finditemtype(t, u->faction->locale); + + if (itype != NULL) { + item **iclaim = i_find(&u->faction->items, itype); + if (iclaim != NULL && *iclaim != NULL) { + n = _min(n, (*iclaim)->number); + i_change(iclaim, itype, -n); + i_change(&u->items, itype, n); + } + } + else { + cmistake(u, ord, 43, MSG_PRODUCE); + } + return 0; } enum { - PROC_THISORDER = 1 << 0, - PROC_LONGORDER = 1 << 1 + PROC_THISORDER = 1 << 0, + PROC_LONGORDER = 1 << 1 }; typedef enum { PR_GLOBAL, PR_REGION_PRE, PR_UNIT, PR_ORDER, PR_REGION_POST } processor_t; typedef struct processor { - struct processor *next; - int priority; - processor_t type; - unsigned int flags; - union { - struct { - keyword_t kword; - int (*process) (struct unit *, struct order *); - } per_order; - struct { - void (*process) (struct unit *); - } per_unit; - struct { - void (*process) (struct region *); - } per_region; - struct { - void (*process) (void); - } global; - } data; - const char *name; + struct processor *next; + int priority; + processor_t type; + unsigned int flags; + union { + struct { + keyword_t kword; + int(*process) (struct unit *, struct order *); + } per_order; + struct { + void(*process) (struct unit *); + } per_unit; + struct { + void(*process) (struct region *); + } per_region; + struct { + void(*process) (void); + } global; + } data; + const char *name; } processor; static processor *processors; static processor *add_proc(int priority, const char *name, processor_t type) { - processor **pproc = &processors; - processor *proc; + processor **pproc = &processors; + processor *proc; - while (*pproc) { - proc = *pproc; - if (proc->priority > priority) - break; - else if (proc->priority == priority && proc->type >= type) - break; - pproc = &proc->next; - } - - proc = (processor *)malloc(sizeof(processor)); - proc->priority = priority; - proc->type = type; - proc->name = name; - proc->next = *pproc; - *pproc = proc; - return proc; -} - -void -add_proc_order(int priority, keyword_t kword, int (*parser) (struct unit *, - struct order *), unsigned int flags, const char *name) -{ - if (!keyword_disabled(kword)) { - processor *proc = add_proc(priority, name, PR_ORDER); - if (proc) { - proc->data.per_order.process = parser; - proc->data.per_order.kword = kword; - proc->flags = flags; + while (*pproc) { + proc = *pproc; + if (proc->priority > priority) + break; + else if (proc->priority == priority && proc->type >= type) + break; + pproc = &proc->next; } - } -} -void add_proc_global(int priority, void (*process) (void), const char *name) -{ - processor *proc = add_proc(priority, name, PR_GLOBAL); - if (proc) { - proc->data.global.process = process; - } -} - -void add_proc_region(int priority, void (*process) (region *), const char *name) -{ - processor *proc = add_proc(priority, name, PR_REGION_PRE); - if (proc) { - proc->data.per_region.process = process; - } + proc = (processor *)malloc(sizeof(processor)); + proc->priority = priority; + proc->type = type; + proc->name = name; + proc->next = *pproc; + *pproc = proc; + return proc; } void -add_proc_postregion(int priority, void (*process) (region *), const char *name) +add_proc_order(int priority, keyword_t kword, int(*parser) (struct unit *, +struct order *), unsigned int flags, const char *name) { - processor *proc = add_proc(priority, name, PR_REGION_POST); - if (proc) { - proc->data.per_region.process = process; - } + if (!keyword_disabled(kword)) { + processor *proc = add_proc(priority, name, PR_ORDER); + if (proc) { + proc->data.per_order.process = parser; + proc->data.per_order.kword = kword; + proc->flags = flags; + } + } } -void add_proc_unit(int priority, void (*process) (unit *), const char *name) +void add_proc_global(int priority, void(*process) (void), const char *name) { - processor *proc = add_proc(priority, name, PR_UNIT); - if (proc) { - proc->data.per_unit.process = process; - } + processor *proc = add_proc(priority, name, PR_GLOBAL); + if (proc) { + proc->data.global.process = process; + } +} + +void add_proc_region(int priority, void(*process) (region *), const char *name) +{ + processor *proc = add_proc(priority, name, PR_REGION_PRE); + if (proc) { + proc->data.per_region.process = process; + } +} + +void +add_proc_postregion(int priority, void(*process) (region *), const char *name) +{ + processor *proc = add_proc(priority, name, PR_REGION_POST); + if (proc) { + proc->data.per_region.process = process; + } +} + +void add_proc_unit(int priority, void(*process) (unit *), const char *name) +{ + processor *proc = add_proc(priority, name, PR_UNIT); + if (proc) { + proc->data.per_unit.process = process; + } } /* per priority, execute processors in order from PR_GLOBAL down to PR_ORDER */ void process(void) { - processor *proc = processors; - faction *f; + processor *proc = processors; + faction *f; - while (proc) { - int prio = proc->priority; - region *r; - processor *pglobal = proc; + while (proc) { + int prio = proc->priority; + region *r; + processor *pglobal = proc; - if (verbosity >= 3) - printf("- Step %u\n", prio); - while (proc && proc->priority == prio) { - if (proc->name && verbosity >= 1) - log_printf(stdout, " - %s\n", proc->name); - proc = proc->next; - } + if (verbosity >= 3) + printf("- Step %u\n", prio); + while (proc && proc->priority == prio) { + if (proc->name && verbosity >= 1) + log_printf(stdout, " - %s\n", proc->name); + proc = proc->next; + } - while (pglobal && pglobal->priority == prio && pglobal->type == PR_GLOBAL) { - pglobal->data.global.process(); - pglobal = pglobal->next; - } - if (pglobal == NULL || pglobal->priority != prio) - continue; - - for (r = regions; r; r = r->next) { - unit *u; - processor *pregion = pglobal; - - while (pregion && pregion->priority == prio - && pregion->type == PR_REGION_PRE) { - pregion->data.per_region.process(r); - pregion = pregion->next; - } - if (pregion == NULL || pregion->priority != prio) - continue; - - if (r->units) { - for (u = r->units; u; u = u->next) { - processor *porder, *punit = pregion; - - while (punit && punit->priority == prio && punit->type == PR_UNIT) { - punit->data.per_unit.process(u); - punit = punit->next; - } - if (punit == NULL || punit->priority != prio) + while (pglobal && pglobal->priority == prio && pglobal->type == PR_GLOBAL) { + pglobal->data.global.process(); + pglobal = pglobal->next; + } + if (pglobal == NULL || pglobal->priority != prio) continue; - porder = punit; - while (porder && porder->priority == prio && porder->type == PR_ORDER) { - order **ordp = &u->orders; - if (porder->flags & PROC_THISORDER) - ordp = &u->thisorder; - while (*ordp) { - order *ord = *ordp; - if (getkeyword(ord) == porder->data.per_order.kword) { - if (porder->flags & PROC_LONGORDER) { - if (u->number == 0) { - ord = NULL; - } - else if (u_race(u) == get_race(RC_INSECT) - && r_insectstalled(r) - && !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) { - ord = NULL; - } else if (LongHunger(u)) { - cmistake(u, ord, 224, MSG_MAGIC); - ord = NULL; - } else if (fval(u, UFL_LONGACTION)) { - /* this message was already given in laws.update_long_order - cmistake(u, ord, 52, MSG_PRODUCE); - */ - ord = NULL; - } else if (fval(r->terrain, SEA_REGION) - && u_race(u) != get_race(RC_AQUARIAN) - && !(u_race(u)->flags & RCF_SWIM)) { - /* error message disabled by popular demand */ - ord = NULL; - } - } - if (ord) { - porder->data.per_order.process(u, ord); - } - } - if (!ord || *ordp == ord) - ordp = &(*ordp)->next; + for (r = regions; r; r = r->next) { + unit *u; + processor *pregion = pglobal; + + while (pregion && pregion->priority == prio + && pregion->type == PR_REGION_PRE) { + pregion->data.per_region.process(r); + pregion = pregion->next; } - porder = porder->next; - } + if (pregion == NULL || pregion->priority != prio) + continue; + + if (r->units) { + for (u = r->units; u; u = u->next) { + processor *porder, *punit = pregion; + + while (punit && punit->priority == prio && punit->type == PR_UNIT) { + punit->data.per_unit.process(u); + punit = punit->next; + } + if (punit == NULL || punit->priority != prio) + continue; + + porder = punit; + while (porder && porder->priority == prio && porder->type == PR_ORDER) { + order **ordp = &u->orders; + if (porder->flags & PROC_THISORDER) + ordp = &u->thisorder; + while (*ordp) { + order *ord = *ordp; + if (getkeyword(ord) == porder->data.per_order.kword) { + if (porder->flags & PROC_LONGORDER) { + if (u->number == 0) { + ord = NULL; + } + else if (u_race(u) == get_race(RC_INSECT) + && r_insectstalled(r) + && !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) { + ord = NULL; + } + else if (LongHunger(u)) { + cmistake(u, ord, 224, MSG_MAGIC); + ord = NULL; + } + else if (fval(u, UFL_LONGACTION)) { + /* this message was already given in laws.update_long_order + cmistake(u, ord, 52, MSG_PRODUCE); + */ + ord = NULL; + } + else if (fval(r->terrain, SEA_REGION) + && u_race(u) != get_race(RC_AQUARIAN) + && !(u_race(u)->flags & RCF_SWIM)) { + /* error message disabled by popular demand */ + ord = NULL; + } + } + if (ord) { + porder->data.per_order.process(u, ord); + } + } + if (!ord || *ordp == ord) + ordp = &(*ordp)->next; + } + porder = porder->next; + } + } + } + + while (pregion && pregion->priority == prio + && pregion->type != PR_REGION_POST) { + pregion = pregion->next; + } + + while (pregion && pregion->priority == prio + && pregion->type == PR_REGION_POST) { + pregion->data.per_region.process(r); + pregion = pregion->next; + } + if (pregion == NULL || pregion->priority != prio) + continue; + } - } - - while (pregion && pregion->priority == prio - && pregion->type != PR_REGION_POST) { - pregion = pregion->next; - } - - while (pregion && pregion->priority == prio - && pregion->type == PR_REGION_POST) { - pregion->data.per_region.process(r); - pregion = pregion->next; - } - if (pregion == NULL || pregion->priority != prio) - continue; - } - } - if (verbosity >= 3) - printf("\n - Leere Gruppen loeschen...\n"); - for (f = factions; f; f = f->next) { - group **gp = &f->groups; - while (*gp) { - group *g = *gp; - if (g->members == 0) { - *gp = g->next; - free_group(g); - } else - gp = &g->next; + if (verbosity >= 3) + printf("\n - Leere Gruppen loeschen...\n"); + for (f = factions; f; f = f->next) { + group **gp = &f->groups; + while (*gp) { + group *g = *gp; + if (g->members == 0) { + *gp = g->next; + free_group(g); + } + else + gp = &g->next; + } } - } } @@ -4347,7 +4439,7 @@ int siege_cmd(unit * u, order * ord) init_tokens(ord); skip_token(); b = getbuilding(r); - + if (!b) { cmistake(u, ord, 31, MSG_BATTLE); return 31; @@ -4371,17 +4463,18 @@ int siege_cmd(unit * u, order * ord) if (eff_skill(u, SK_CATAPULT, r) >= 1) { katapultiere = d; d *= eff_skill(u, SK_CATAPULT, r); - } else { + } + else { d = 0; } - + bewaffnete = armedmen(u, true); if (d == 0 && bewaffnete == 0) { /* abbruch, falls unbewaffnet oder unfaehig, katapulte zu benutzen */ cmistake(u, ord, 80, MSG_EVENT); return 80; } - + if (!is_guard(u, GUARD_TRAVELTHRU)) { /* abbruch, wenn die einheit nicht vorher die region bewacht - als * warnung fuer alle anderen! */ @@ -4391,23 +4484,24 @@ int siege_cmd(unit * u, order * ord) /* einheit und burg markieren - spart zeit beim behandeln der einheiten * in der burg, falls die burg auch markiert ist und nicht alle * einheiten wieder abgesucht werden muessen! */ - + usetsiege(u, b); b->besieged += _max(bewaffnete, katapultiere); - + /* definitiver schaden eingeschraenkt */ - + d = _min(d, b->size - 1); - + /* meldung, schaden anrichten */ if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) { b->size -= d; use_pooled(u, rt_catapultammo, - GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); + GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); /* send message to the entire region */ ADDMSG(&r->msgs, msg_message("siege_catapults", - "unit building destruction", u, b, d)); - } else { + "unit building destruction", u, b, d)); + } + else { /* send message to the entire region */ ADDMSG(&r->msgs, msg_message("siege", "unit building", u, b)); } @@ -4416,30 +4510,30 @@ int siege_cmd(unit * u, order * ord) void do_siege(region * r) { - if (fval(r->terrain, LAND_REGION)) { - unit *u; + if (fval(r->terrain, LAND_REGION)) { + unit *u; - for (u = r->units; u; u = u->next) { - if (getkeyword(u->thisorder) == K_BESIEGE) { - siege_cmd(u, u->thisorder); - } + for (u = r->units; u; u = u->next) { + if (getkeyword(u->thisorder) == K_BESIEGE) { + siege_cmd(u, u->thisorder); + } + } } - } } static void enter_1(region * r) { - do_enter(r, 0); + do_enter(r, 0); } static void enter_2(region * r) { - do_enter(r, 1); + do_enter(r, 1); } static void maintain_buildings_1(region * r) { - maintain_buildings(r, false); + maintain_buildings(r, false); } /** warn about passwords that are not US ASCII. @@ -4450,264 +4544,278 @@ static void maintain_buildings_1(region * r) */ static int warn_password(void) { - faction *f = factions; - while (f) { - bool pwok = true; - const char *c = f->passw; - while (*c && pwok) { - if (!isalnum((unsigned char)*c)) - pwok = false; - c++; + faction *f = factions; + while (f) { + bool pwok = true; + const char *c = f->passw; + while (*c && pwok) { + if (!isalnum((unsigned char)*c)) + pwok = false; + c++; + } + if (!pwok) { + free(f->passw); + f->passw = _strdup(itoa36(rng_int())); + ADDMSG(&f->msgs, msg_message("illegal_password", "newpass", f->passw)); + } + f = f->next; } - if (!pwok) { - free(f->passw); - f->passw = _strdup(itoa36(rng_int())); - ADDMSG(&f->msgs, msg_message("illegal_password", "newpass", f->passw)); - } - f = f->next; - } - return 0; + return 0; } void init_processor(void) { - int p; + int p; - p = 10; - add_proc_global(p, &new_units, "Neue Einheiten erschaffen"); + p = 10; + add_proc_global(p, &new_units, "Neue Einheiten erschaffen"); - p += 10; - add_proc_unit(p, update_long_order, "Langen Befehl aktualisieren"); - add_proc_order(p, K_BANNER, banner_cmd, 0, NULL); - add_proc_order(p, K_EMAIL, &email_cmd, 0, NULL); - add_proc_order(p, K_PASSWORD, &password_cmd, 0, NULL); - add_proc_order(p, K_SEND, &send_cmd, 0, NULL); - add_proc_order(p, K_GROUP, &group_cmd, 0, NULL); - - p += 10; - add_proc_order(p, K_QUIT, &quit_cmd, 0, NULL); - add_proc_order(p, K_URSPRUNG, &origin_cmd, 0, NULL); - add_proc_order(p, K_ALLY, &ally_cmd, 0, NULL); - add_proc_order(p, K_PREFIX, &prefix_cmd, 0, NULL); - add_proc_order(p, K_SETSTEALTH, &setstealth_cmd, 0, NULL); - add_proc_order(p, K_STATUS, &status_cmd, 0, NULL); - add_proc_order(p, K_COMBATSPELL, &combatspell_cmd, 0, NULL); - add_proc_order(p, K_DISPLAY, &display_cmd, 0, NULL); - add_proc_order(p, K_NAME, &name_cmd, 0, NULL); - add_proc_order(p, K_GUARD, &guard_off_cmd, 0, NULL); - add_proc_order(p, K_RESHOW, &reshow_cmd, 0, NULL); - - if (get_param_int(global.parameters, "rules.alliances", 0) == 1) { p += 10; - add_proc_global(p, &alliance_cmd, NULL); - } + add_proc_unit(p, update_long_order, "Langen Befehl aktualisieren"); + add_proc_order(p, K_BANNER, banner_cmd, 0, NULL); + add_proc_order(p, K_EMAIL, &email_cmd, 0, NULL); + add_proc_order(p, K_PASSWORD, &password_cmd, 0, NULL); + add_proc_order(p, K_SEND, &send_cmd, 0, NULL); + add_proc_order(p, K_GROUP, &group_cmd, 0, NULL); - p += 10; - add_proc_region(p, do_contact, "Kontaktieren"); - add_proc_order(p, K_MAIL, &mail_cmd, 0, "Botschaften"); - - p += 10; /* all claims must be done before we can USE */ - add_proc_region(p, &enter_1, "Betreten (1. Versuch)"); - add_proc_order(p, K_USE, &use_cmd, 0, "Benutzen"); - - p += 10; /* in case it has any effects on alliance victories */ - add_proc_order(p, K_GIVE, &give_control_cmd, 0, "GIB KOMMANDO"); - - p += 10; /* in case it has any effects on alliance victories */ - add_proc_order(p, K_LEAVE, &leave_cmd, 0, "Verlassen"); - - add_proc_region(p, &do_battle, "Attackieren"); - - if (!keyword_disabled(K_BESIEGE)) { p += 10; - add_proc_region(p, &do_siege, "Belagern"); - } + add_proc_order(p, K_QUIT, &quit_cmd, 0, NULL); + add_proc_order(p, K_URSPRUNG, &origin_cmd, 0, NULL); + add_proc_order(p, K_ALLY, &ally_cmd, 0, NULL); + add_proc_order(p, K_PREFIX, &prefix_cmd, 0, NULL); + add_proc_order(p, K_SETSTEALTH, &setstealth_cmd, 0, NULL); + add_proc_order(p, K_STATUS, &status_cmd, 0, NULL); + add_proc_order(p, K_COMBATSPELL, &combatspell_cmd, 0, NULL); + add_proc_order(p, K_DISPLAY, &display_cmd, 0, NULL); + add_proc_order(p, K_NAME, &name_cmd, 0, NULL); + add_proc_order(p, K_GUARD, &guard_off_cmd, 0, NULL); + add_proc_order(p, K_RESHOW, &reshow_cmd, 0, NULL); - p += 10; /* can't allow reserve before siege (weapons) */ - add_proc_region(p, &enter_1, "Betreten (2. Versuch)"); - add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "Reservieren"); - add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL); - add_proc_unit(p, &follow_unit, "Folge auf Einheiten setzen"); + if (get_param_int(global.parameters, "rules.alliances", 0) == 1) { + p += 10; + add_proc_global(p, &alliance_cmd, NULL); + } - p += 10; /* rest rng again before economics */ - add_proc_region(p, &economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); - - p += 10; - if (!keyword_disabled(K_PAY)) { - add_proc_order(p, K_PAY, &pay_cmd, 0, "Gebaeudeunterhalt (disable)"); - } - add_proc_postregion(p, &maintain_buildings_1, - "Gebaeudeunterhalt (1. Versuch)"); - - p += 10; /* QUIT fuer sich alleine */ - add_proc_global(p, quit, "Sterben"); - - if (!keyword_disabled(K_CAST)) { p += 10; - add_proc_global(p, &magic, "Zaubern"); - } + add_proc_region(p, do_contact, "Kontaktieren"); + add_proc_order(p, K_MAIL, &mail_cmd, 0, "Botschaften"); - p += 10; - add_proc_order(p, K_TEACH, &teach_cmd, PROC_THISORDER | PROC_LONGORDER, - "Lehren"); - p += 10; - add_proc_order(p, K_STUDY, &learn_cmd, PROC_THISORDER | PROC_LONGORDER, - "Lernen"); + p += 10; /* all claims must be done before we can USE */ + add_proc_region(p, &enter_1, "Betreten (1. Versuch)"); + add_proc_order(p, K_USE, &use_cmd, 0, "Benutzen"); - p += 10; - add_proc_order(p, K_MAKE, &make_cmd, PROC_THISORDER | PROC_LONGORDER, - "Produktion"); - add_proc_postregion(p, &produce, "Arbeiten, Handel, Rekruten"); - add_proc_postregion(p, &split_allocations, "Produktion II"); + p += 10; /* in case it has any effects on alliance victories */ + add_proc_order(p, K_GIVE, &give_control_cmd, 0, "GIB KOMMANDO"); - p += 10; - add_proc_region(p, &enter_2, "Betreten (3. Versuch)"); + p += 10; /* in case it has any effects on alliance victories */ + add_proc_order(p, K_LEAVE, &leave_cmd, 0, "Verlassen"); - p += 10; - add_proc_region(p, &sinkships, "Schiffe sinken"); + add_proc_region(p, &do_battle, "Attackieren"); - p += 10; - add_proc_global(p, &movement, "Bewegungen"); + if (!keyword_disabled(K_BESIEGE)) { + p += 10; + add_proc_region(p, &do_siege, "Belagern"); + } + + p += 10; /* can't allow reserve before siege (weapons) */ + add_proc_region(p, &enter_1, "Betreten (2. Versuch)"); + add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "Reservieren"); + add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL); + add_proc_unit(p, &follow_unit, "Folge auf Einheiten setzen"); + + p += 10; /* rest rng again before economics */ + add_proc_region(p, &economics, "Zerstoeren, Geben, Rekrutieren, Vergessen"); - if (get_param_int(global.parameters, "work.auto", 0)) { p += 10; - add_proc_region(p, &auto_work, "Arbeiten (auto)"); - } + if (!keyword_disabled(K_PAY)) { + add_proc_order(p, K_PAY, &pay_cmd, 0, "Gebaeudeunterhalt (disable)"); + } + add_proc_postregion(p, &maintain_buildings_1, + "Gebaeudeunterhalt (1. Versuch)"); - p += 10; - add_proc_order(p, K_GUARD, &guard_on_cmd, 0, "Bewache (an)"); + p += 10; /* QUIT fuer sich alleine */ + add_proc_global(p, quit, "Sterben"); + + if (!keyword_disabled(K_CAST)) { + p += 10; + add_proc_global(p, &magic, "Zaubern"); + } - if (get_param_int(global.parameters, "rules.encounters", 0)) { p += 10; - add_proc_global(p, &encounters, "Zufallsbegegnungen"); - } - - p += 10; - add_proc_unit(p, &monster_kills_peasants, - "Monster fressen und vertreiben Bauern"); - - p += 10; - add_proc_global(p, &randomevents, "Zufallsereignisse"); - - p += 10; - - add_proc_global(p, &monthly_healing, "Regeneration (HP)"); - add_proc_global(p, ®enerate_aura, "Regeneration (Aura)"); - if (!keyword_disabled(K_DEFAULT)) { - add_proc_global(p, &defaultorders, "Defaults setzen"); - } - add_proc_global(p, &demographics, "Nahrung, Seuchen, Wachstum, Wanderung"); - - if (!keyword_disabled(K_SORT)) { + add_proc_order(p, K_TEACH, &teach_cmd, PROC_THISORDER | PROC_LONGORDER, + "Lehren"); p += 10; - add_proc_global(p, restack_units, "Einheiten sortieren"); - } - add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung"); - if (!keyword_disabled(K_NUMBER)) { - add_proc_order(p, K_NUMBER, &renumber_cmd, 0, "Neue Nummern (Einheiten)"); + add_proc_order(p, K_STUDY, &learn_cmd, PROC_THISORDER | PROC_LONGORDER, + "Lernen"); + p += 10; - add_proc_global(p, &renumber_factions, "Neue Nummern"); - } + add_proc_order(p, K_MAKE, &make_cmd, PROC_THISORDER | PROC_LONGORDER, + "Produktion"); + add_proc_postregion(p, &produce, "Arbeiten, Handel, Rekruten"); + add_proc_postregion(p, &split_allocations, "Produktion II"); + + p += 10; + add_proc_region(p, &enter_2, "Betreten (3. Versuch)"); + + p += 10; + add_proc_region(p, &sinkships, "Schiffe sinken"); + + p += 10; + add_proc_global(p, &movement, "Bewegungen"); + + if (get_param_int(global.parameters, "work.auto", 0)) { + p += 10; + add_proc_region(p, &auto_work, "Arbeiten (auto)"); + } + + p += 10; + add_proc_order(p, K_GUARD, &guard_on_cmd, 0, "Bewache (an)"); + + if (get_param_int(global.parameters, "rules.encounters", 0)) { + p += 10; + add_proc_global(p, &encounters, "Zufallsbegegnungen"); + } + + p += 10; + add_proc_unit(p, &monster_kills_peasants, + "Monster fressen und vertreiben Bauern"); + + p += 10; + add_proc_global(p, &randomevents, "Zufallsereignisse"); + + p += 10; + + add_proc_global(p, &monthly_healing, "Regeneration (HP)"); + add_proc_global(p, ®enerate_aura, "Regeneration (Aura)"); + if (!keyword_disabled(K_DEFAULT)) { + add_proc_global(p, &defaultorders, "Defaults setzen"); + } + add_proc_global(p, &demographics, "Nahrung, Seuchen, Wachstum, Wanderung"); + + if (!keyword_disabled(K_SORT)) { + p += 10; + add_proc_global(p, restack_units, "Einheiten sortieren"); + } + add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung"); + if (!keyword_disabled(K_NUMBER)) { + add_proc_order(p, K_NUMBER, &renumber_cmd, 0, "Neue Nummern (Einheiten)"); + p += 10; + add_proc_global(p, &renumber_factions, "Neue Nummern"); + } } void processorders(void) { - static int init = 0; + static int init = 0; - if (!init) { - init_processor(); - init = 1; - } - update_spells(); - process(); - /*************************************************/ + if (!init) { + init_processor(); + init = 1; + } + update_spells(); + process(); + /*************************************************/ - if (get_param_int(global.parameters, "modules.markets", 0)) { - do_markets(); - } + if (get_param_int(global.parameters, "modules.markets", 0)) { + do_markets(); + } - log_info(" - Attribute altern"); - ageing(); - remove_empty_units(); + log_info(" - Attribute altern"); + ageing(); + remove_empty_units(); - /* must happen AFTER age, because that would destroy them right away */ - if (get_param_int(global.parameters, "modules.wormholes", 0)) { - create_wormholes(); - } + /* must happen AFTER age, because that would destroy them right away */ + if (get_param_int(global.parameters, "modules.wormholes", 0)) { + create_wormholes(); + } - /* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich - * Beschreibungen geändert haben */ - update_spells(); - warn_password(); + /* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich + * Beschreibungen geändert haben */ + update_spells(); + warn_password(); } int writepasswd(void) { - FILE *F; - char zText[128]; + FILE *F; + char zText[128]; - sprintf(zText, "%s/passwd", basepath()); - F = fopen(zText, "w"); - if (!F) { - perror(zText); - } else { - faction *f; - log_info("writing passwords..."); - - for (f = factions; f; f = f->next) { - fprintf(F, "%s:%s:%s:%u\n", - factionid(f), f->email, f->passw, f->subscription); + sprintf(zText, "%s/passwd", basepath()); + F = fopen(zText, "w"); + if (!F) { + perror(zText); } - fclose(F); - return 0; - } - return 1; + else { + faction *f; + log_info("writing passwords..."); + + for (f = factions; f; f = f->next) { + fprintf(F, "%s:%s:%s:%u\n", + factionid(f), f->email, f->passw, f->subscription); + } + fclose(F); + return 0; + } + return 1; } void update_subscriptions(void) { - FILE *F; - char zText[MAX_PATH]; - faction *f; - strcat(strcpy(zText, basepath()), "/subscriptions"); - F = fopen(zText, "r"); - if (F == NULL) { - log_warning(0, "could not open %s.\n", zText); - return; - } - for (;;) { - char zFaction[5]; - int subscription, fno; - if (fscanf(F, "%d %s", &subscription, zFaction) <= 0) - break; - fno = atoi36(zFaction); - f = findfaction(fno); - if (f != NULL) { - f->subscription = subscription; + FILE *F; + char zText[MAX_PATH]; + faction *f; + strcat(strcpy(zText, basepath()), "/subscriptions"); + F = fopen(zText, "r"); + if (F == NULL) { + log_warning(0, "could not open %s.\n", zText); + return; } - } - fclose(F); + for (;;) { + char zFaction[5]; + int subscription, fno; + if (fscanf(F, "%d %s", &subscription, zFaction) <= 0) + break; + fno = atoi36(zFaction); + f = findfaction(fno); + if (f != NULL) { + f->subscription = subscription; + } + } + fclose(F); - sprintf(zText, "subscriptions.%u", turn); - F = fopen(zText, "w"); - for (f = factions; f != NULL; f = f->next) { - fprintf(F, "%s:%u:%s:%s:%u:\n", - itoa36(f->no), f->subscription, f->email, dbrace(f->race), f->lastorders); - } - fclose(F); + sprintf(zText, "subscriptions.%u", turn); + F = fopen(zText, "w"); + for (f = factions; f != NULL; f = f->next) { + fprintf(F, "%s:%u:%s:%s:%u:\n", + itoa36(f->no), f->subscription, f->email, dbrace(f->race), f->lastorders); + } + fclose(F); } +const char *confpath = 0; + int init_data(const char *filename, const char *catalog) { - int l; + char filepath[MAX_PATH], catpath[MAX_PATH]; + int l; - l = read_xml(filename, catalog); - init_locales(); - if (l) - return l; + if (confpath) { + if (filename) { + _snprintf(filepath, sizeof(filepath), "%s/%s", confpath, filename); + filename = filepath; + } + if (catalog) { + _snprintf(catpath, sizeof(catpath), "%s/%s", confpath, catalog); + catalog = catpath; + } + } + l = read_xml(filename, catalog); + init_locales(); + if (l) + return l; - if (turn < 0) { - turn = first_turn; - } - return 0; + if (turn < 0) { + turn = first_turn; + } + return 0; } diff --git a/src/main.c b/src/main.c index d204c98cd..ac6b08338 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -41,136 +41,146 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -static const char *logfile= "eressea.log"; +extern const char *confpath; +static const char *logfile = "eressea.log"; static const char *luafile = 0; static const char *inifile = "eressea.ini"; static int memdebug = 0; static void parse_config(const char *filename) { - dictionary *d = iniparser_new(filename); - if (d) { - load_inifile(d); - log_debug("reading from configuration file %s\n", filename); + dictionary *d = iniparser_new(filename); + if (d) { + load_inifile(d); + log_debug("reading from configuration file %s\n", filename); - memdebug = iniparser_getint(d, "eressea:memcheck", memdebug); + memdebug = iniparser_getint(d, "eressea:memcheck", memdebug); #ifdef USE_CURSES - /* only one value in the [editor] section */ - force_color = iniparser_getint(d, "editor:color", force_color); + /* only one value in the [editor] section */ + force_color = iniparser_getint(d, "editor:color", force_color); #endif - /* excerpt from [config] (the rest is used in bindings.c) */ - game_name = iniparser_getstring(d, "config:game", game_name); - } else { - log_warning("could not open configuration file %s\n", filename); - } - global.inifile = d; + /* excerpt from [config] (the rest is used in bindings.c) */ + game_name = iniparser_getstring(d, "config:game", game_name); + } + else { + log_error("could not open configuration file %s\n", filename); + } + global.inifile = d; } static int usage(const char *prog, const char *arg) { - if (arg) { - fprintf(stderr, "unknown argument: %s\n\n", arg); - } - fprintf(stderr, "Usage: %s [options]\n" - "-t : read this datafile, not the most current one\n" - "-f : execute a lua script\n" - "-q : be quite (same as -v 0)\n" - "-v : verbosity level\n" - "-C : run in interactive mode\n" - "--color : force curses to use colors even when not detected\n", prog); - return -1; + if (arg) { + fprintf(stderr, "unknown argument: %s\n\n", arg); + } + fprintf(stderr, "Usage: %s [options]\n" + "-t : read this datafile, not the most current one\n" + "-f : execute a lua script\n" + "-q : be quite (same as -v 0)\n" + "-v : verbosity level\n" + "-C : run in interactive mode\n" + "--color : force curses to use colors even when not detected\n", prog); + return -1; } static int get_arg(int argc, char **argv, size_t len, int index, const char **result, const char *def) { - if (argv[index][len]) { - *result = argv[index]+len; + if (argv[index][len]) { + *result = argv[index] + len; + return index; + } + if (index + 1 < argc) { + *result = argv[index + 1]; + return index + 1; + } + *result = def; return index; - } - if (index+1 < argc) { - *result = argv[index+1]; - return index+1; - } - *result = def; - return index; } static int parse_args(int argc, char **argv, int *exitcode) { - int i; + int i; - for (i = 1; i != argc; ++i) { - if (argv[i][0] != '-') { - luafile = argv[i]; - } else if (argv[i][1] == '-') { /* long format */ - if (strcmp(argv[i] + 2, "version") == 0) { - printf("\n%s PBEM host\n" - "Copyright (C) 1996-2005 C. Schlittchen, K. Zedel, E. Rehling, H. Peters.\n\n" - "Compilation: " __DATE__ " at " __TIME__ "\nVersion: %d.%d.%d\n\n", - global.gamename, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); + for (i = 1; i != argc; ++i) { + if (argv[i][0] != '-') { + luafile = argv[i]; + } + else if (argv[i][1] == '-') { /* long format */ + if (strcmp(argv[i] + 2, "version") == 0) { + printf("\n%s PBEM host\n" + "Copyright (C) 1996-2005 C. Schlittchen, K. Zedel, E. Rehling, H. Peters.\n\n" + "Compilation: " __DATE__ " at " __TIME__ "\nVersion: %d.%d.%d\n\n", + global.gamename, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); #ifdef USE_CURSES - } else if (strcmp(argv[i] + 2, "color") == 0) { - /* force the editor to have colors */ - force_color = 1; + } + else if (strcmp(argv[i] + 2, "color") == 0) { + /* force the editor to have colors */ + force_color = 1; #endif - } else if (strcmp(argv[i] + 2, "help") == 0) { - return usage(argv[0], NULL); - } else { - return usage(argv[0], argv[i]); - } - } else { - const char *arg; - switch (argv[i][1]) { - case 'f': - i = get_arg(argc, argv, 2, i, &luafile, 0); - break; - case 'l': - i = get_arg(argc, argv, 2, i, &logfile, 0); - break; - case 't': - i = get_arg(argc, argv, 2, i, &arg, 0); - turn = atoi(arg); - break; - case 'q': - verbosity = 0; - break; - case 'r': - i = get_arg(argc, argv, 2, i, &arg, 0); - turn = atoi(arg); - break; - case 'v': - i = get_arg(argc, argv, 2, i, &arg, 0); - verbosity = arg ? atoi(arg) : 0xff; - break; - case 'h': - usage(argv[0], NULL); - return 1; - default: - *exitcode = -1; - usage(argv[0], argv[i]); - return 1; - } + } + else if (strcmp(argv[i] + 2, "help") == 0) { + return usage(argv[0], NULL); + } + else { + return usage(argv[0], argv[i]); + } + } + else { + const char *arg; + switch (argv[i][1]) { + case 'c': + i = get_arg(argc, argv, 2, i, &confpath, 0); + break; + case 'f': + i = get_arg(argc, argv, 2, i, &luafile, 0); + break; + case 'l': + i = get_arg(argc, argv, 2, i, &logfile, 0); + break; + case 't': + i = get_arg(argc, argv, 2, i, &arg, 0); + turn = atoi(arg); + break; + case 'q': + verbosity = 0; + break; + case 'r': + i = get_arg(argc, argv, 2, i, &arg, 0); + turn = atoi(arg); + break; + case 'v': + i = get_arg(argc, argv, 2, i, &arg, 0); + verbosity = arg ? atoi(arg) : 0xff; + break; + case 'h': + usage(argv[0], NULL); + return 1; + default: + *exitcode = -1; + usage(argv[0], argv[i]); + return 1; + } + } } - } - - switch (verbosity) { - case 0: - log_stderr = 0; - break; - case 1: - log_stderr = LOG_CPERROR; - break; - case 2: - log_stderr = LOG_CPERROR|LOG_CPWARNING; - break; - case 3: - log_stderr = LOG_CPERROR|LOG_CPWARNING|LOG_CPDEBUG; - break; - default: - log_stderr = LOG_CPERROR|LOG_CPWARNING|LOG_CPDEBUG|LOG_CPINFO; - break; - } - return 0; + switch (verbosity) { + case 0: + log_stderr = 0; + break; + case 1: + log_stderr = LOG_CPERROR; + break; + case 2: + log_stderr = LOG_CPERROR | LOG_CPWARNING; + break; + case 3: + log_stderr = LOG_CPERROR | LOG_CPWARNING | LOG_CPDEBUG; + break; + default: + log_stderr = LOG_CPERROR | LOG_CPWARNING | LOG_CPDEBUG | LOG_CPINFO; + break; + } + + return 0; } #if defined(HAVE_SIGACTION) && defined(HAVE_EXECINFO) @@ -179,30 +189,30 @@ static int parse_args(int argc, char **argv, int *exitcode) static void report_segfault(int signo, siginfo_t * sinf, void *arg) { - void *btrace[50]; - size_t size; - int fd = fileno(stderr); + void *btrace[50]; + size_t size; + int fd = fileno(stderr); - fflush(stdout); - fputs("\n\nProgram received SIGSEGV, backtrace follows.\n", stderr); - size = backtrace(btrace, 50); - backtrace_symbols_fd(btrace, size, fd); - abort(); + fflush(stdout); + fputs("\n\nProgram received SIGSEGV, backtrace follows.\n", stderr); + size = backtrace(btrace, 50); + backtrace_symbols_fd(btrace, size, fd); + abort(); } static int setup_signal_handler(void) { - struct sigaction act; + struct sigaction act; - act.sa_flags = SA_ONESHOT | SA_SIGINFO; - act.sa_sigaction = report_segfault; - sigfillset(&act.sa_mask); - return sigaction(SIGSEGV, &act, NULL); + act.sa_flags = SA_ONESHOT | SA_SIGINFO; + act.sa_sigaction = report_segfault; + sigfillset(&act.sa_mask); + return sigaction(SIGSEGV, &act, NULL); } #else static int setup_signal_handler(void) { - return 0; + return 0; } #endif @@ -212,72 +222,82 @@ static int setup_signal_handler(void) void init_crtdbg(void) { #if (defined(_MSC_VER)) - int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - if (memdebug == 1) { - flags |= _CRTDBG_CHECK_ALWAYS_DF; /* expensive */ - } else if (memdebug == 2) { - flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF; - } else if (memdebug == 3) { - flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_128_DF; - } else if (memdebug == 4) { - flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_1024_DF; - } - _CrtSetDbgFlag(flags); + int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + if (memdebug == 1) { + flags |= _CRTDBG_CHECK_ALWAYS_DF; /* expensive */ + } else if (memdebug == 2) { + flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF; + } else if (memdebug == 3) { + flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_128_DF; + } else if (memdebug == 4) { + flags = (flags & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_1024_DF; + } + _CrtSetDbgFlag(flags); #endif } #endif void locale_init(void) { - setlocale(LC_CTYPE, ""); - setlocale(LC_NUMERIC, "C"); - if (towlower(0xC4) != 0xE4) { /* Ä => ä */ - log_error("Umlaut conversion is not working properly. Wrong locale? LANG=%s\n", - getenv("LANG")); - } + setlocale(LC_CTYPE, ""); + setlocale(LC_NUMERIC, "C"); + if (towlower(0xC4) != 0xE4) { /* Ä => ä */ + log_error("Umlaut conversion is not working properly. Wrong locale? LANG=%s\n", + getenv("LANG")); + } } extern void bind_monsters(struct lua_State *L); int main(int argc, char **argv) { - int err, result = 0; - lua_State *L; - setup_signal_handler(); - parse_config(inifile); - log_open(logfile); + char inipath[MAX_PATH]; + int err = 0; + lua_State *L; + setup_signal_handler(); - err = parse_args(argc, argv, &result); - if (err) { - return result; - } + /* parse args once to read config file location */ + if (parse_args(argc, argv, &err) != 0) { + return err; + } + /* ini file sets defaults for arguments*/ + if (confpath) { + _snprintf(inipath, sizeof(inipath), "%s/%s", confpath, inifile); + parse_config(inipath); + } + else { + parse_config(inifile); + } + /* parse arguments again, to override ini file */ + parse_args(argc, argv, &err); - locale_init(); + log_open(logfile); + locale_init(); #ifdef CRTDBG - init_crtdbg(); + init_crtdbg(); #endif L = lua_init(); - game_init(); - register_races(); - register_borders(); - register_spells(); - bind_monsters(L); - err = eressea_run(L, luafile); - if (err) { - log_error("server execution failed with code %d\n", err); - return err; - } + game_init(); + register_races(); + register_borders(); + register_spells(); + bind_monsters(L); + err = eressea_run(L, luafile); + if (err) { + log_error("server execution failed with code %d\n", err); + return err; + } #ifdef MSPACES - malloc_stats(); + malloc_stats(); #endif - game_done(); - lua_done(L); - log_close(); - if (global.inifile) { - iniparser_free(global.inifile); - } - return 0; + game_done(); + lua_done(L); + log_close(); + if (global.inifile) { + iniparser_free(global.inifile); + } + return 0; }