From 1918f56990ddacee2118ec4c0fd981b4bc0142a1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 8 Aug 2014 01:03:46 +0200 Subject: [PATCH] indentation + whitespace changes --- src/economy.c | 5073 ++++++++++++++++++++++---------------------- src/give.c | 663 +++--- src/kernel/magic.c | 3755 ++++++++++++++++---------------- src/kernel/move.c | 4115 +++++++++++++++++------------------ src/kernel/order.c | 681 +++--- src/laws.c | 3 +- 6 files changed, 7236 insertions(+), 7054 deletions(-) diff --git a/src/economy.c b/src/economy.c index de54b0206..f218c766c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1,7 +1,8 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, +Enno Rehling +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 @@ -75,15 +76,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include typedef struct request { - struct request *next; - struct unit *unit; - struct order *ord; - int qty; - int no; - union { - bool goblin; /* stealing */ - const struct luxury_type *ltype; /* trading */ - } type; + struct request *next; + struct unit *unit; + struct order *ord; + int qty; + int no; + union { + bool goblin; /* stealing */ + const struct luxury_type *ltype; /* trading */ + } type; } request; static int working; @@ -100,605 +101,615 @@ static int rules_recruit = -1; static void recruit_init(void) { - if (rules_recruit < 0) { - rules_recruit = 0; - if (get_param_int(global.parameters, "recruit.allow_merge", 1)) { - rules_recruit |= RECRUIT_MERGE; + if (rules_recruit < 0) { + rules_recruit = 0; + if (get_param_int(global.parameters, "recruit.allow_merge", 1)) { + rules_recruit |= RECRUIT_MERGE; + } } - } } int income(const unit * u) { - switch (old_race(u_race(u))) { - case RC_FIREDRAGON: - return 150 * u->number; - case RC_DRAGON: - return 1000 * u->number; - case RC_WYRM: - return 5000 * u->number; - default: - return 20 * u->number; - } + switch (old_race(u_race(u))) { + case RC_FIREDRAGON: + return 150 * u->number; + case RC_DRAGON: + return 1000 * u->number; + case RC_WYRM: + return 5000 * u->number; + default: + return 20 * u->number; + } } static void scramble(void *data, int n, size_t width) { - int j; - char temp[64]; - assert(width <= sizeof(temp)); - for (j = 0; j != n; ++j) { - int k = rng_int() % n; - if (k == j) - continue; - memcpy(temp, (char *)data + j * width, width); - memcpy((char *)data + j * width, (char *)data + k * width, width); - memcpy((char *)data + k * width, temp, width); - } + int j; + char temp[64]; + assert(width <= sizeof(temp)); + for (j = 0; j != n; ++j) { + int k = rng_int() % n; + if (k == j) + continue; + memcpy(temp, (char *)data + j * width, width); + memcpy((char *)data + j * width, (char *)data + k * width, width); + memcpy((char *)data + k * width, temp, width); + } } static void expandorders(region * r, request * requests) { - unit *u; - request *o; + unit *u; + request *o; - /* Alle Units ohne request haben ein -1, alle units mit orders haben ein - * 0 hier stehen */ + /* Alle Units ohne request haben ein -1, alle units mit orders haben ein + * 0 hier stehen */ - for (u = r->units; u; u = u->next) - u->n = -1; + for (u = r->units; u; u = u->next) + u->n = -1; - norders = 0; + norders = 0; - for (o = requests; o; o = o->next) { - if (o->qty > 0) { - norders += o->qty; - } - } - - if (norders > 0) { - int i = 0; - oa = (request *) calloc(norders, sizeof(request)); for (o = requests; o; o = o->next) { - if (o->qty > 0) { - int j; - for (j = o->qty; j; j--) { - oa[i] = *o; - oa[i].unit->n = 0; - i++; + if (o->qty > 0) { + norders += o->qty; } - } } - scramble(oa, norders, sizeof(request)); - } else { - oa = NULL; - } - while (requests) { - request *o = requests->next; - free_order(requests->ord); - free(requests); - requests = o; - } + + if (norders > 0) { + int i = 0; + oa = (request *)calloc(norders, sizeof(request)); + for (o = requests; o; o = o->next) { + if (o->qty > 0) { + int j; + for (j = o->qty; j; j--) { + oa[i] = *o; + oa[i].unit->n = 0; + i++; + } + } + } + scramble(oa, norders, sizeof(request)); + } + else { + oa = NULL; + } + while (requests) { + request *o = requests->next; + free_order(requests->ord); + free(requests); + requests = o; + } } /* ------------------------------------------------------------- */ static void change_level(unit * u, skill_t sk, int bylevel) { - skill *sv = unit_skill(u, sk); - assert(bylevel > 0); - if (sv == 0) - sv = add_skill(u, sk); - sk_set(sv, sv->level + bylevel); + skill *sv = unit_skill(u, sk); + assert(bylevel > 0); + if (sv == 0) + sv = add_skill(u, sk); + sk_set(sv, sv->level + bylevel); } typedef struct recruitment { - struct recruitment *next; - faction *f; - request *requests; - int total, assigned; + struct recruitment *next; + faction *f; + request *requests; + int total, assigned; } recruitment; /** Creates a list of recruitment structs, one for each faction. Adds every quantifyable request * to the faction's struct and to total. */ static recruitment *select_recruitment(request ** rop, - int (*quantify) (const struct race *, int), int *total) + int(*quantify) (const struct race *, int), int *total) { - recruitment *recruits = NULL; + recruitment *recruits = NULL; - while (*rop) { - recruitment *rec = recruits; - request *ro = *rop; - unit *u = ro->unit; - const race *rc = u_race(u); - int qty = quantify(rc, ro->qty); + while (*rop) { + recruitment *rec = recruits; + request *ro = *rop; + unit *u = ro->unit; + const race *rc = u_race(u); + int qty = quantify(rc, ro->qty); - if (qty < 0) { - rop = &ro->next; /* skip this one */ - } else { - *rop = ro->next; /* remove this one */ - while (rec && rec->f != u->faction) - rec = rec->next; - if (rec == NULL) { - rec = malloc(sizeof(recruitment)); - rec->f = u->faction; - rec->total = 0; - rec->assigned = 0; - rec->requests = NULL; - rec->next = recruits; - recruits = rec; - } - *total += qty; - rec->total += qty; - ro->next = rec->requests; - rec->requests = ro; + if (qty < 0) { + rop = &ro->next; /* skip this one */ + } + else { + *rop = ro->next; /* remove this one */ + while (rec && rec->f != u->faction) + rec = rec->next; + if (rec == NULL) { + rec = malloc(sizeof(recruitment)); + rec->f = u->faction; + rec->total = 0; + rec->assigned = 0; + rec->requests = NULL; + rec->next = recruits; + recruits = rec; + } + *total += qty; + rec->total += qty; + ro->next = rec->requests; + rec->requests = ro; + } } - } - return recruits; + return recruits; } static void add_recruits(unit * u, int number, int wanted) { - region *r = u->region; - assert(number <= wanted); - if (number > 0) { - unit *unew; - char equipment[64]; + region *r = u->region; + assert(number <= wanted); + if (number > 0) { + unit *unew; + char equipment[64]; - if (u->number == 0) { - set_number(u, number); - u->hp = number * unit_max_hp(u); - unew = u; - } else { - unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u); + if (u->number == 0) { + set_number(u, number); + u->hp = number * unit_max_hp(u); + unew = u; + } + else { + unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u); + } + + strlcpy(equipment, "new_", sizeof(equipment)); + strlcat(equipment, u_race(u)->_name[0], sizeof(equipment)); + strlcat(equipment, "_unit", sizeof(equipment)); + equip_unit(unew, get_equipment(equipment)); + + if (u_race(unew)->ec_flags & ECF_REC_HORSES) { + change_level(unew, SK_RIDING, 1); + } + + if (unew != u) { + transfermen(unew, u, unew->number); + remove_unit(&r->units, unew); + } } - - strlcpy(equipment, "new_", sizeof(equipment)); - strlcat(equipment, u_race(u)->_name[0], sizeof(equipment)); - strlcat(equipment, "_unit", sizeof(equipment)); - equip_unit(unew, get_equipment(equipment)); - - if (u_race(unew)->ec_flags & ECF_REC_HORSES) { - change_level(unew, SK_RIDING, 1); + if (number < wanted) { + ADDMSG(&u->faction->msgs, msg_message("recruit", + "unit region amount want", u, r, number, wanted)); } - - if (unew != u) { - transfermen(unew, u, unew->number); - remove_unit(&r->units, unew); - } - } - if (number < wanted) { - ADDMSG(&u->faction->msgs, msg_message("recruit", - "unit region amount want", u, r, number, wanted)); - } } static int any_recruiters(const struct race *rc, int qty) { - return (int)(qty * 2 * rc->recruit_multi); + return (int)(qty * 2 * rc->recruit_multi); } /*static int peasant_recruiters(const struct race *rc, int qty) { - if (rc->ec_flags & ECF_REC_ETHEREAL) - return -1; - if (rc->ec_flags & ECF_REC_HORSES) - return -1; - return (int)(qty * 2 * rc->recruit_multi); +if (rc->ec_flags & ECF_REC_ETHEREAL) +return -1; +if (rc->ec_flags & ECF_REC_HORSES) +return -1; +return (int)(qty * 2 * rc->recruit_multi); }*/ static int horse_recruiters(const struct race *rc, int qty) { - if (rc->ec_flags & ECF_REC_ETHEREAL) + if (rc->ec_flags & ECF_REC_ETHEREAL) + return -1; + if (rc->ec_flags & ECF_REC_HORSES) + return (int)(qty * 2 * rc->recruit_multi); return -1; - if (rc->ec_flags & ECF_REC_HORSES) - return (int)(qty * 2 * rc->recruit_multi); - return -1; } static int do_recruiting(recruitment * recruits, int available) { - recruitment *rec; - int recruited = 0; + recruitment *rec; + int recruited = 0; - /* try to assign recruits to factions fairly */ - while (available > 0) { - int n = 0; - int rest, mintotal = INT_MAX; + /* try to assign recruits to factions fairly */ + while (available > 0) { + int n = 0; + int rest, mintotal = INT_MAX; - /* find smallest request */ - for (rec = recruits; rec != NULL; rec = rec->next) { - int want = rec->total - rec->assigned; - if (want > 0) { - if (mintotal > want) - mintotal = want; - ++n; - } - } - if (n == 0) - break; - if (mintotal * n > available) { - mintotal = available / n; - } - rest = available - mintotal * n; - - /* assign size of smallest request for everyone if possible; in the end roll dice to assign - * small rest */ - for (rec = recruits; rec != NULL; rec = rec->next) { - int want = rec->total - rec->assigned; - - if (want > 0) { - int get = mintotal; - if (want > mintotal && rest < n && (rng_int() % n) < rest) { - --rest; - ++get; + /* find smallest request */ + for (rec = recruits; rec != NULL; rec = rec->next) { + int want = rec->total - rec->assigned; + if (want > 0) { + if (mintotal > want) + mintotal = want; + ++n; + } + } + if (n == 0) + break; + if (mintotal * n > available) { + mintotal = available / n; + } + rest = available - mintotal * n; + + /* assign size of smallest request for everyone if possible; in the end roll dice to assign + * small rest */ + for (rec = recruits; rec != NULL; rec = rec->next) { + int want = rec->total - rec->assigned; + + if (want > 0) { + int get = mintotal; + if (want > mintotal && rest < n && (rng_int() % n) < rest) { + --rest; + ++get; + } + assert(get <= want); + available -= get; + rec->assigned += get; + } } - assert(get <= want); - available -= get; - rec->assigned += get; - } } - } - /* do actual recruiting */ - for (rec = recruits; rec != NULL; rec = rec->next) { - request *req; - int get = rec->assigned; + /* do actual recruiting */ + for (rec = recruits; rec != NULL; rec = rec->next) { + request *req; + int get = rec->assigned; - for (req = rec->requests; req; req = req->next) { - unit *u = req->unit; - const race *rc = u_race(u); /* race is set in recruit() */ - int number, dec; - float multi = 2.0F * rc->recruit_multi; + for (req = rec->requests; req; req = req->next) { + unit *u = req->unit; + const race *rc = u_race(u); /* race is set in recruit() */ + int number, dec; + float multi = 2.0F * rc->recruit_multi; - number = _min(req->qty, (int)(get / multi)); - if (rc->recruitcost) { - int afford = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - number * rc->recruitcost) / rc->recruitcost; - number = _min(number, afford); - } - if (u->number + number > UNIT_MAXSIZE) { - ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size", - "maxsize", UNIT_MAXSIZE)); - number = UNIT_MAXSIZE - u->number; - assert(number >= 0); - } - if (rc->recruitcost) { - use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - rc->recruitcost * number); - } - if (u->number == 0 && fval(u, UFL_DEAD)) { - /* unit is empty, dead, and cannot recruit */ - number = 0; - } - if (number > 0) { - add_recruits(u, number, req->qty); - dec = (int)(number * multi); - if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { - recruited += dec; - } + number = _min(req->qty, (int)(get / multi)); + if (rc->recruitcost) { + int afford = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + number * rc->recruitcost) / rc->recruitcost; + number = _min(number, afford); + } + if (u->number + number > UNIT_MAXSIZE) { + ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size", + "maxsize", UNIT_MAXSIZE)); + number = UNIT_MAXSIZE - u->number; + assert(number >= 0); + } + if (rc->recruitcost) { + use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + rc->recruitcost * number); + } + if (u->number == 0 && fval(u, UFL_DEAD)) { + /* unit is empty, dead, and cannot recruit */ + number = 0; + } + if (number > 0) { + add_recruits(u, number, req->qty); + dec = (int)(number * multi); + if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { + recruited += dec; + } - get -= dec; - } + get -= dec; + } + } } - } - return recruited; + return recruited; } static void feedback_give_not_allowed(unit * u, order * ord) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", - "")); + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", + "")); } static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask) { - if (u2) { - if (u->faction != u2->faction) { - int rule = rule_give(); - if (itype) { - assert(mask == 0); - if (itype->rtype->ltype) - mask |= GIVE_LUXURIES; - else if (fval(itype, ITF_HERB)) - mask |= GIVE_HERBS; - else - mask |= GIVE_GOODS; - } - return (rule & mask) != 0; + if (u2) { + if (u->faction != u2->faction) { + int rule = rule_give(); + if (itype) { + assert(mask == 0); + if (itype->rtype->ltype) + mask |= GIVE_LUXURIES; + else if (fval(itype, ITF_HERB)) + mask |= GIVE_HERBS; + else + mask |= GIVE_GOODS; + } + return (rule & mask) != 0; + } } - } else { - int rule = rule_give(); - return (rule & GIVE_PEASANTS) != 0; - } - return true; + else { + int rule = rule_give(); + return (rule & GIVE_PEASANTS) != 0; + } + return true; } void free_recruitments(recruitment * recruits) { - while (recruits) { - recruitment *rec = recruits; - recruits = rec->next; - while (rec->requests) { - request *req = rec->requests; - rec->requests = req->next; - free(req); + while (recruits) { + recruitment *rec = recruits; + recruits = rec->next; + while (rec->requests) { + request *req = rec->requests; + rec->requests = req->next; + free(req); + } + free(rec); } - free(rec); - } } /* Rekrutierung */ static void expandrecruit(region * r, request * recruitorders) { - recruitment *recruits = NULL; + recruitment *recruits = NULL; - int orc_total = 0; + int orc_total = 0; - /* centaurs: */ - recruits = select_recruitment(&recruitorders, horse_recruiters, &orc_total); - if (recruits) { - int recruited, horses = rhorses(r) * 2; - if (orc_total < horses) - horses = orc_total; - recruited = do_recruiting(recruits, horses); - rsethorses(r, (horses - recruited) / 2); - free_recruitments(recruits); - } - - /* peasant limited: */ - recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); - if (recruits) { - int orc_recruited, orc_peasants = rpeasants(r) * 2; - int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ - if (orc_total < orc_frac) - orc_frac = orc_total; - orc_recruited = do_recruiting(recruits, orc_frac); - assert(orc_recruited <= orc_frac); - rsetpeasants(r, (orc_peasants - orc_recruited) / 2); - free_recruitments(recruits); - } - - /* no limit: */ - recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); - if (recruits) { - int recruited, peasants = rpeasants(r) * 2; - recruited = do_recruiting(recruits, INT_MAX); - if (recruited > 0) { - rsetpeasants(r, (peasants - recruited) / 2); + /* centaurs: */ + recruits = select_recruitment(&recruitorders, horse_recruiters, &orc_total); + if (recruits) { + int recruited, horses = rhorses(r) * 2; + if (orc_total < horses) + horses = orc_total; + recruited = do_recruiting(recruits, horses); + rsethorses(r, (horses - recruited) / 2); + free_recruitments(recruits); } - free_recruitments(recruits); - } - assert(recruitorders == NULL); + /* peasant limited: */ + recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); + if (recruits) { + int orc_recruited, orc_peasants = rpeasants(r) * 2; + int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ + if (orc_total < orc_frac) + orc_frac = orc_total; + orc_recruited = do_recruiting(recruits, orc_frac); + assert(orc_recruited <= orc_frac); + rsetpeasants(r, (orc_peasants - orc_recruited) / 2); + free_recruitments(recruits); + } + + /* no limit: */ + recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); + if (recruits) { + int recruited, peasants = rpeasants(r) * 2; + recruited = do_recruiting(recruits, INT_MAX); + if (recruited > 0) { + rsetpeasants(r, (peasants - recruited) / 2); + } + free_recruitments(recruits); + } + + assert(recruitorders == NULL); } static int recruit_cost(const faction * f, const race * rc) { - if (is_monsters(f) || f->race == rc) { - return rc->recruitcost; - } else if (valid_race(f, rc)) { - return rc->recruitcost; -/* return get_param_int(f->race->parameters, "other_cost", -1); */ - } - return -1; + if (is_monsters(f) || f->race == rc) { + return rc->recruitcost; + } + else if (valid_race(f, rc)) { + return rc->recruitcost; + /* return get_param_int(f->race->parameters, "other_cost", -1); */ + } + return -1; } static void recruit(unit * u, struct order *ord, request ** recruitorders) { - int n; - region *r = u->region; - plane *pl; - request *o; - int recruitcost = -1; - const faction *f = u->faction; - const struct race *rc = u_race(u); - const char *str; + int n; + region *r = u->region; + plane *pl; + request *o; + int recruitcost = -1; + const faction *f = u->faction; + const struct race *rc = u_race(u); + const char *str; - init_tokens(ord); - skip_token(); - n = getuint(); + init_tokens(ord); + skip_token(); + n = getuint(); - if (u->number == 0) { - str = getstrtoken(); - if (str && str[0]) { - /* Monsters can RECRUIT 15 DRACOID - * also: secondary race */ - rc = findrace(str, f->locale); - if (rc != NULL) { - recruitcost = recruit_cost(f, rc); - } + if (u->number == 0) { + str = getstrtoken(); + if (str && str[0]) { + /* Monsters can RECRUIT 15 DRACOID + * also: secondary race */ + rc = findrace(str, f->locale); + if (rc != NULL) { + recruitcost = recruit_cost(f, rc); + } + } } - } - if (recruitcost < 0) { - rc = u_race(u); - recruitcost = recruit_cost(f, rc); if (recruitcost < 0) { - recruitcost = INT_MAX; + rc = u_race(u); + recruitcost = recruit_cost(f, rc); + if (recruitcost < 0) { + recruitcost = INT_MAX; + } } - } - assert(rc); - u_setrace(u, rc); + assert(rc); + u_setrace(u, rc); #if GUARD_DISABLES_RECRUIT - /* this is a very special case because the recruiting unit may be empty - * at this point and we have to look at the creating unit instead. This - * is done in cansee, which is called indirectly by is_guarded(). */ - if (is_guarded(r, u, GUARD_RECRUIT)) { - cmistake(u, ord, 70, MSG_EVENT); - return; - } -#endif - - if (rc == get_race(RC_INSECT)) { - gamedate date; - get_gamedate(turn, &date); - if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { -#ifdef INSECT_POTION - bool usepotion = false; - unit *u2; - - for (u2 = r->units; u2; u2 = u2->next) - if (fval(u2, UFL_WARMTH)) { - usepotion = true; - break; - } - if (!usepotion) -#endif - { - cmistake(u, ord, 98, MSG_EVENT); + /* this is a very special case because the recruiting unit may be empty + * at this point and we have to look at the creating unit instead. This + * is done in cansee, which is called indirectly by is_guarded(). */ + if (is_guarded(r, u, GUARD_RECRUIT)) { + cmistake(u, ord, 70, MSG_EVENT); return; - } } - /* in Gletschern, Eisbergen gar nicht rekrutieren */ - if (r_insectstalled(r)) { - cmistake(u, ord, 97, MSG_EVENT); - return; - } - } - if (is_cursed(r->attribs, C_RIOT, 0)) { - /* Die Region befindet sich in Aufruhr */ - cmistake(u, ord, 237, MSG_EVENT); - return; - } +#endif - if (!(rc->ec_flags & ECF_REC_HORSES) && fval(r, RF_ORCIFIED)) { - if (rc != get_race(RC_ORC)) { - cmistake(u, ord, 238, MSG_EVENT); - return; - } - } + if (rc == get_race(RC_INSECT)) { + gamedate date; + get_gamedate(turn, &date); + if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { +#ifdef INSECT_POTION + bool usepotion = false; + unit *u2; - if (recruitcost) { - pl = getplane(r); - if (pl && fval(pl, PFL_NORECRUITS)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", "")); - return; + for (u2 = r->units; u2; u2 = u2->next) + if (fval(u2, UFL_WARMTH)) { + usepotion = true; + break; + } + if (!usepotion) +#endif + { + cmistake(u, ord, 98, MSG_EVENT); + return; + } + } + /* in Gletschern, Eisbergen gar nicht rekrutieren */ + if (r_insectstalled(r)) { + cmistake(u, ord, 97, MSG_EVENT); + return; + } + } + if (is_cursed(r->attribs, C_RIOT, 0)) { + /* Die Region befindet sich in Aufruhr */ + cmistake(u, ord, 237, MSG_EVENT); + return; } - if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - recruitcost) < recruitcost) { - cmistake(u, ord, 142, MSG_EVENT); - return; + if (!(rc->ec_flags & ECF_REC_HORSES) && fval(r, RF_ORCIFIED)) { + if (rc != get_race(RC_ORC)) { + cmistake(u, ord, 238, MSG_EVENT); + return; + } } - } - if (!playerrace(rc) || idle(u->faction)) { - cmistake(u, ord, 139, MSG_EVENT); - return; - } - if (has_skill(u, SK_MAGIC)) { - /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten - * grundsätzlich nur alleine! */ - cmistake(u, ord, 158, MSG_EVENT); - return; - } - if (has_skill(u, SK_ALCHEMY) - && count_skill(u->faction, SK_ALCHEMY) + n > - skill_limit(u->faction, SK_ALCHEMY)) { - cmistake(u, ord, 156, MSG_EVENT); - return; - } - if (recruitcost > 0) { - int pooled = - get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n); - n = _min(n, pooled / recruitcost); - } + if (recruitcost) { + pl = getplane(r); + if (pl && fval(pl, PFL_NORECRUITS)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", "")); + return; + } - u->wants = n; + if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + recruitcost) < recruitcost) { + cmistake(u, ord, 142, MSG_EVENT); + return; + } + } + if (!playerrace(rc) || idle(u->faction)) { + cmistake(u, ord, 139, MSG_EVENT); + return; + } - if (!n) { - cmistake(u, ord, 142, MSG_EVENT); - return; - } + if (has_skill(u, SK_MAGIC)) { + /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten + * grundsätzlich nur alleine! */ + cmistake(u, ord, 158, MSG_EVENT); + return; + } + if (has_skill(u, SK_ALCHEMY) + && count_skill(u->faction, SK_ALCHEMY) + n > + skill_limit(u->faction, SK_ALCHEMY)) { + cmistake(u, ord, 156, MSG_EVENT); + return; + } + if (recruitcost > 0) { + int pooled = + get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n); + n = _min(n, pooled / recruitcost); + } - o = (request *) calloc(1, sizeof(request)); - o->qty = n; - o->unit = u; - o->ord = copy_order(ord); - addlist(recruitorders, o); + u->wants = n; + + if (!n) { + cmistake(u, ord, 142, MSG_EVENT); + return; + } + + o = (request *)calloc(1, sizeof(request)); + o->qty = n; + o->unit = u; + o->ord = copy_order(ord); + addlist(recruitorders, o); } static void friendly_takeover(region * r, faction * f) { - int morale = region_get_morale(r); - region_set_owner(r, f, turn); - if (morale > 0) { - morale = _max(0, morale - MORALE_TRANSFER); - region_set_morale(r, morale, turn); - } + int morale = region_get_morale(r); + region_set_owner(r, f, turn); + if (morale > 0) { + morale = _max(0, morale - MORALE_TRANSFER); + region_set_morale(r, morale, turn); + } } void give_control(unit * u, unit * u2) { - if (u->building) { - if (u->faction != u2->faction && rule_region_owners()) { - region *r = u->region; - faction *f = region_get_owner(r); + if (u->building) { + if (u->faction != u2->faction && rule_region_owners()) { + region *r = u->region; + faction *f = region_get_owner(r); - assert(u->building==u2->building); - if (f == u->faction) { - building *b = largestbuilding(r, &cmp_current_owner, false); - if (b == u->building) { - friendly_takeover(r, u2->faction); + assert(u->building == u2->building); + if (f == u->faction) { + building *b = largestbuilding(r, &cmp_current_owner, false); + if (b == u->building) { + friendly_takeover(r, u2->faction); + } + } } - } + building_set_owner(u2); + } + if (u->ship) { + assert(u->ship == u2->ship); + ship_set_owner(u2); } - building_set_owner(u2); - } - if (u->ship) { - assert(u->ship==u2->ship); - ship_set_owner(u2); - } } int give_control_cmd(unit * u, order * ord) { - region *r = u->region; - unit *u2; - const char *s; - param_t p; + region *r = u->region; + unit *u2; + const char *s; + param_t p; - init_tokens(ord); - skip_token(); - u2 = getunit(r, u->faction); - s = getstrtoken(); - p = findparam(s, u->faction->locale); + init_tokens(ord); + skip_token(); + u2 = getunit(r, u->faction); + s = getstrtoken(); + p = findparam(s, u->faction->locale); - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { - message *msg = 0; + /* first, do all the ones that do not require HELP_GIVE or CONTACT */ + if (p == P_CONTROL) { + message *msg = 0; - if (!u2 || u2->number == 0) { - msg = msg_feedback(u, ord, "feedback_unit_not_found", ""); - ADDMSG(&u->faction->msgs, msg); - } else if (!u->building && !u->ship) { - msg = cmistake(u, ord, 140, MSG_EVENT); - } else if (u->building) { - if (u!=building_owner(u->building)) { - msg = cmistake(u, ord, 49, MSG_EVENT); - } else if (u2->building != u->building) { - msg = cmistake(u, ord, 33, MSG_EVENT); - } - } else if (u->ship) { - if (u!=ship_owner(u->ship)) { - msg = cmistake(u, ord, 49, MSG_EVENT); - } else if (u2->ship != u->ship) { - msg = cmistake(u, ord, 32, MSG_EVENT); - } + if (!u2 || u2->number == 0) { + msg = msg_feedback(u, ord, "feedback_unit_not_found", ""); + ADDMSG(&u->faction->msgs, msg); + } + else if (!u->building && !u->ship) { + msg = cmistake(u, ord, 140, MSG_EVENT); + } + else if (u->building) { + if (u != building_owner(u->building)) { + msg = cmistake(u, ord, 49, MSG_EVENT); + } + else if (u2->building != u->building) { + msg = cmistake(u, ord, 33, MSG_EVENT); + } + } + else if (u->ship) { + if (u != ship_owner(u->ship)) { + msg = cmistake(u, ord, 49, MSG_EVENT); + } + else if (u2->ship != u->ship) { + msg = cmistake(u, ord, 32, MSG_EVENT); + } + } + if (!msg) { + give_control(u, u2); + msg = msg_message("givecommand", "unit recipient", u, u2); + add_message(&u->faction->msgs, msg); + if (u->faction != u2->faction) { + add_message(&u2->faction->msgs, msg); + } + msg_release(msg); + } } - if (!msg) { - give_control(u, u2); - msg = msg_message("givecommand", "unit recipient", u, u2); - add_message(&u->faction->msgs, msg); - if (u->faction != u2->faction) { - add_message(&u2->faction->msgs, msg); - } - msg_release(msg); - } - } - return 0; + return 0; } message *check_give(const unit *u, const unit *u2, order * ord) { @@ -710,298 +721,306 @@ message *check_give(const unit *u, const unit *u2, order * ord) { static void give_cmd(unit * u, order * ord) { - region *r = u->region; - unit *u2; - const char *s; - int n; - const item_type *itype; - param_t p; - plane *pl; - message *msg; - - init_tokens(ord); - skip_token(); - u2 = getunit(r, u->faction); - s = getstrtoken(); - n = atoip(s); - p = (n>0) ? NOPARAM : findparam(s, u->faction->locale); - - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { - /* handled in give_control_cmd */ - return; - } - - if (!u2 && !getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - msg = check_give(u, u2, ord); - if (msg) { - ADDMSG(&u->faction->msgs, msg); - return; - } - - /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ - if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) - && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) - && !fval(u2, UFL_TAKEALL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - if (u == u2) { - cmistake(u, ord, 8, MSG_COMMERCE); - return; - } - - /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht - * wirklich einfach. */ - pl = rplane(r); - if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { - cmistake(u, ord, 268, MSG_COMMERCE); - return; - } - - if (u2 && u_race(u2) == get_race(RC_SPELL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { - cmistake(u, ord, 40, MSG_COMMERCE); - return; - } - - else if (p == P_HERBS) { - bool given = false; - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!can_give(u, u2, NULL, GIVE_HERBS)) { - feedback_give_not_allowed(u, ord); - return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - if (!u2) { - if (!getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return; - } - } - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (fval(itype, ITF_HERB) && itm->number > 0) { - /* give_item ändert im fall,das man alles übergibt, die - * item-liste der unit, darum continue vor pointerumsetzten */ - if (give_item(itm->number, itm->type, u, u2, ord) == 0) { - given = true; - if (*itmp != itm) - continue; - continue; - } - } - itmp = &itm->next; - } - } - if (!given) - cmistake(u, ord, 38, MSG_COMMERCE); - return; - } - - else if (p == P_ZAUBER) { - cmistake(u, ord, 7, MSG_COMMERCE); - /* geht nimmer */ - return; - } - - else if (p == P_UNIT) { /* Einheiten uebergeben */ - if (!(u_race(u)->ec_flags & GIVEUNIT)) { - cmistake(u, ord, 167, MSG_COMMERCE); - return; - } - - give_unit(u, u2, ord); - return; - } - - else if (p == P_ANY) { + region *r = u->region; + unit *u2; const char *s; + int n; + const item_type *itype; + param_t p; + plane *pl; + message *msg; - if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { - feedback_give_not_allowed(u, ord); - return; + init_tokens(ord); + skip_token(); + u2 = getunit(r, u->faction); + s = getstrtoken(); + n = atoip(s); + p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale); + + /* first, do all the ones that do not require HELP_GIVE or CONTACT */ + if (p == P_CONTROL) { + /* handled in give_control_cmd */ + return; + } + + if (!u2 && !getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + msg = check_give(u, u2, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; + } + + /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ + if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) + && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) + && !fval(u2, UFL_TAKEALL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + if (u == u2) { + cmistake(u, ord, 8, MSG_COMMERCE); + return; + } + + /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht + * wirklich einfach. */ + pl = rplane(r); + if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { + cmistake(u, ord, 268, MSG_COMMERCE); + return; + } + + if (u2 && u_race(u2) == get_race(RC_SPELL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { + cmistake(u, ord, 40, MSG_COMMERCE); + return; + } + + else if (p == P_HERBS) { + bool given = false; + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!can_give(u, u2, NULL, GIVE_HERBS)) { + feedback_give_not_allowed(u, ord); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + if (!u2) { + if (!getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + return; + } + } + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (fval(itype, ITF_HERB) && itm->number > 0) { + /* give_item ändert im fall,das man alles übergibt, die + * item-liste der unit, darum continue vor pointerumsetzten */ + if (give_item(itm->number, itm->type, u, u2, ord) == 0) { + given = true; + if (*itmp != itm) + continue; + continue; + } + } + itmp = &itm->next; + } + } + if (!given) + cmistake(u, ord, 38, MSG_COMMERCE); + return; + } + + else if (p == P_ZAUBER) { + cmistake(u, ord, 7, MSG_COMMERCE); + /* geht nimmer */ + return; + } + + else if (p == P_UNIT) { /* Einheiten uebergeben */ + if (!(u_race(u)->ec_flags & GIVEUNIT)) { + cmistake(u, ord, 167, MSG_COMMERCE); + return; + } + + give_unit(u, u2, ord); + return; + } + + else if (p == P_ANY) { + const char *s; + + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { + feedback_give_not_allowed(u, ord); + return; + } + s = getstrtoken(); + if (*s == 0) { /* GIVE ALL items that you have */ + + /* do these checks once, not for each item we have: */ + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + + /* für alle items einmal prüfen, ob wir mehr als von diesem Typ + * reserviert ist besitzen und diesen Teil dann übergeben */ + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (itm->number > 0 + && itm->number - get_reservation(u, itype->rtype) > 0) { + n = itm->number - get_reservation(u, itype->rtype); + if (give_item(n, itype, u, u2, ord) == 0) { + if (*itmp != itm) + continue; + } + } + itmp = &itm->next; + } + } + } + else { + if (isparam(s, u->faction->locale, P_PERSON)) { + if (!(u_race(u)->ec_flags & GIVEPERSON)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + } + else { + n = u->number; + give_men(n, u, u2, ord); + } + } + else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + } + else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + } + else { + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + item *i = *i_find(&u->items, itype); + if (i != NULL) { + if (can_give(u, u2, itype, 0)) { + n = i->number - get_reservation(u, itype->rtype); + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + } + } + } + } + return; + } + else if (p == P_EACH) { + if (u2 == NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "peasants_give_invalid", "")); + return; + } + s = getstrtoken(); /* skip one ahead to get the amount. */ + n = atoip(s); /* n: Anzahl */ + n *= u2->number; } s = getstrtoken(); - if (*s == 0) { /* GIVE ALL items that you have */ - /* do these checks once, not for each item we have: */ - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + if (s == NULL) { + cmistake(u, ord, 113, MSG_COMMERCE); return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } + } - /* für alle items einmal prüfen, ob wir mehr als von diesem Typ - * reserviert ist besitzen und diesen Teil dann übergeben */ - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (itm->number > 0 - && itm->number - get_reservation(u, itype->rtype) > 0) { - n = itm->number - get_reservation(u, itype->rtype); - if (give_item(n, itype, u, u2, ord) == 0) { - if (*itmp != itm) - continue; - } - } - itmp = &itm->next; - } - } - } else { - if (isparam(s, u->faction->locale, P_PERSON)) { + if (isparam(s, u->faction->locale, P_PERSON)) { if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - } else { - n = u->number; - give_men(n, u, u2, ord); + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + return; } - } else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - } else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - } else { - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - item *i = *i_find(&u->items, itype); - if (i != NULL) { - if (can_give(u, u2, itype, 0)) { - n = i->number - get_reservation(u, itype->rtype); - give_item(n, itype, u, u2, ord); - } else { - feedback_give_not_allowed(u, ord); - } - } + give_men(n, u, u2, ord); + return; + } + + if (u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; } - } } - return; - } else if (p == P_EACH) { - if (u2 == NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "peasants_give_invalid", "")); - return; - } - s = getstrtoken(); /* skip one ahead to get the amount. */ - n = atoip(s); /* n: Anzahl */ - n *= u2->number; - } - s = getstrtoken(); - if (s == NULL) { - cmistake(u, ord, 113, MSG_COMMERCE); - return; - } - - if (isparam(s, u->faction->locale, P_PERSON)) { - if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - return; + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + if (can_give(u, u2, itype, 0)) { + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + return; } - give_men(n, u, u2, ord); - return; - } - - if (u2 != NULL) { - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - } - - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - if (can_give(u, u2, itype, 0)) { - give_item(n, itype, u, u2, ord); - } else { - feedback_give_not_allowed(u, ord); - } - return; - } - cmistake(u, ord, 123, MSG_COMMERCE); + cmistake(u, ord, 123, MSG_COMMERCE); } static int forget_cmd(unit * u, order * ord) { - skill_t sk; - const char *s; + skill_t sk; + const char *s; - if (is_cursed(u->attribs, C_SLAVE, 0)) { - /* charmed units shouldn't be losing their skills */ + if (is_cursed(u->attribs, C_SLAVE, 0)) { + /* charmed units shouldn't be losing their skills */ + return 0; + } + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + + if ((sk = get_skill(s, u->faction->locale)) != NOSKILL) { + ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); + set_level(u, sk, 0); + } return 0; - } - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - if ((sk = get_skill(s, u->faction->locale)) != NOSKILL) { - ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); - set_level(u, sk, 0); - } - return 0; } void add_spende(faction * f1, faction * f2, int amount, region * r) { - donation *sp; + donation *sp; - sp = r->donations; + sp = r->donations; - while (sp) { - if (sp->f1 == f1 && sp->f2 == f2) { - sp->amount += amount; - return; + while (sp) { + if (sp->f1 == f1 && sp->f2 == f2) { + sp->amount += amount; + return; + } + sp = sp->next; } - sp = sp->next; - } - sp = calloc(1, sizeof(donation)); - sp->f1 = f1; - sp->f2 = f2; - sp->amount = amount; - sp->next = r->donations; - r->donations = sp; + sp = calloc(1, sizeof(donation)); + sp->f1 = f1; + sp->f2 = f2; + sp->amount = amount; + sp->next = r->donations; + r->donations = sp; } static bool maintain(building * b, bool first) @@ -1012,212 +1031,215 @@ static bool maintain(building * b, bool first) region *r = b->region; bool paid = true, work = first; unit *u; - - if (fval(b, BLD_MAINTAINED) || b->type == NULL || b->type->maintenance == NULL - || is_cursed(b->attribs, C_NOCOST, 0)) { - fset(b, BLD_MAINTAINED); - fset(b, BLD_WORKING); - return true; - } - if (fval(b, BLD_DONTPAY)) { - return false; - } - u = building_owner(b); - if (u == NULL) - return false; - for (c = 0; b->type->maintenance[c].number; ++c) { - const maintenance *m = b->type->maintenance + c; - int need = m->number; - if (fval(m, MTF_VARIABLE)) - need = need * b->size; - if (u) { - /* first ist im ersten versuch true, im zweiten aber false! Das - * bedeutet, das in der Runde in die Region geschafften Resourcen - * nicht genutzt werden können, weil die reserviert sind! */ - if (!first) - need -= get_pooled(u, m->rtype, GET_ALL, need); - else - need -= get_pooled(u, m->rtype, GET_DEFAULT, need); - if (!first && need > 0) { - unit *ua; - for (ua = r->units; ua; ua = ua->next) - freset(ua->faction, FFL_SELECT); - fset(u->faction, FFL_SELECT); /* hat schon */ - for (ua = r->units; ua; ua = ua->next) { - if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction - || alliedunit(ua, u->faction, HELP_MONEY))) { - need -= get_pooled(ua, m->rtype, GET_ALL, need); - fset(ua->faction, FFL_SELECT); - if (need <= 0) - break; - } - } - } - if (need > 0) { - work = false; - if (fval(m, MTF_VITAL)) - { - paid = false; - break; - } - } + if (fval(b, BLD_MAINTAINED) || b->type == NULL || b->type->maintenance == NULL + || is_cursed(b->attribs, C_NOCOST, 0)) { + fset(b, BLD_MAINTAINED); + fset(b, BLD_WORKING); + return true; } - } - if (paid && c > 0) { - /* TODO: wieviel von was wurde bezahlt */ - if (first && work) { - ADDMSG(&u->faction->msgs, msg_message("maintenance", "unit building", u, b)); - fset(b, BLD_WORKING); - fset(b, BLD_MAINTAINED); - } - if (!first) { - ADDMSG(&u->faction->msgs, msg_message("maintenance_late", "building", b)); - fset(b, BLD_MAINTAINED); + if (fval(b, BLD_DONTPAY)) { + return false; } - - if (first && !work) { - ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); - return false; - } - + u = building_owner(b); + if (u == NULL) + return false; for (c = 0; b->type->maintenance[c].number; ++c) { - const maintenance *m = b->type->maintenance + c; - int cost = m->number; + const maintenance *m = b->type->maintenance + c; + int need = m->number; - if (!fval(m, MTF_VITAL) && !work) - continue; - if (fval(m, MTF_VARIABLE)) - cost = cost * b->size; - - if (!first) - cost -= use_pooled(u, m->rtype, GET_ALL, cost); - else - cost -= - use_pooled(u, m->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, - cost); - if (!first && cost > 0) { - unit *ua; - for (ua = r->units; ua; ua = ua->next) - freset(ua->faction, FFL_SELECT); - fset(u->faction, FFL_SELECT); /* hat schon */ - for (ua = r->units; ua; ua = ua->next) { - if (!fval(ua->faction, FFL_SELECT) - && alliedunit(ua, u->faction, HELP_MONEY)) { - int give = use_pooled(ua, m->rtype, GET_ALL, cost); - if (!give) - continue; - cost -= give; - fset(ua->faction, FFL_SELECT); - if (m->rtype == rsilver) - add_spende(ua->faction, u->faction, give, r); - if (cost <= 0) - break; - } + if (fval(m, MTF_VARIABLE)) + need = need * b->size; + if (u) { + /* first ist im ersten versuch true, im zweiten aber false! Das + * bedeutet, das in der Runde in die Region geschafften Resourcen + * nicht genutzt werden können, weil die reserviert sind! */ + if (!first) + need -= get_pooled(u, m->rtype, GET_ALL, need); + else + need -= get_pooled(u, m->rtype, GET_DEFAULT, need); + if (!first && need > 0) { + unit *ua; + for (ua = r->units; ua; ua = ua->next) + freset(ua->faction, FFL_SELECT); + fset(u->faction, FFL_SELECT); /* hat schon */ + for (ua = r->units; ua; ua = ua->next) { + if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction + || alliedunit(ua, u->faction, HELP_MONEY))) { + need -= get_pooled(ua, m->rtype, GET_ALL, need); + fset(ua->faction, FFL_SELECT); + if (need <= 0) + break; + } + } + } + if (need > 0) { + work = false; + if (fval(m, MTF_VITAL)) + { + paid = false; + break; + } + } } - } - assert(cost == 0); } - } else { - ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); - return false; - } - return true; + if (paid && c > 0) { + /* TODO: wieviel von was wurde bezahlt */ + if (first && work) { + ADDMSG(&u->faction->msgs, msg_message("maintenance", "unit building", u, b)); + fset(b, BLD_WORKING); + fset(b, BLD_MAINTAINED); + } + if (!first) { + ADDMSG(&u->faction->msgs, msg_message("maintenance_late", "building", b)); + fset(b, BLD_MAINTAINED); + } + + if (first && !work) { + ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); + return false; + } + + for (c = 0; b->type->maintenance[c].number; ++c) { + const maintenance *m = b->type->maintenance + c; + int cost = m->number; + + if (!fval(m, MTF_VITAL) && !work) + continue; + if (fval(m, MTF_VARIABLE)) + cost = cost * b->size; + + if (!first) + cost -= use_pooled(u, m->rtype, GET_ALL, cost); + else + cost -= + use_pooled(u, m->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + cost); + if (!first && cost > 0) { + unit *ua; + for (ua = r->units; ua; ua = ua->next) + freset(ua->faction, FFL_SELECT); + fset(u->faction, FFL_SELECT); /* hat schon */ + for (ua = r->units; ua; ua = ua->next) { + if (!fval(ua->faction, FFL_SELECT) + && alliedunit(ua, u->faction, HELP_MONEY)) { + int give = use_pooled(ua, m->rtype, GET_ALL, cost); + if (!give) + continue; + cost -= give; + fset(ua->faction, FFL_SELECT); + if (m->rtype == rsilver) + add_spende(ua->faction, u->faction, give, r); + if (cost <= 0) + break; + } + } + } + assert(cost == 0); + } + } + else { + ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); + return false; + } + return true; } void maintain_buildings(region * r, bool crash) { - building **bp = &r->buildings; - while (*bp) { - building *b = *bp; - bool maintained = maintain(b, !crash); + building **bp = &r->buildings; + while (*bp) { + building *b = *bp; + bool maintained = maintain(b, !crash); - /* the second time, send a message */ - if (crash) { - if (!fval(b, BLD_WORKING)) { - unit *u = building_owner(b); - const char *msgtype = - maintained ? "maintenance_nowork" : "maintenance_none"; - struct message *msg = msg_message(msgtype, "building", b); + /* the second time, send a message */ + if (crash) { + if (!fval(b, BLD_WORKING)) { + unit *u = building_owner(b); + const char *msgtype = + maintained ? "maintenance_nowork" : "maintenance_none"; + struct message *msg = msg_message(msgtype, "building", b); - if (u) { - add_message(&u->faction->msgs, msg); - r_addmessage(r, u->faction, msg); - } else { - add_message(&r->msgs, msg); + if (u) { + add_message(&u->faction->msgs, msg); + r_addmessage(r, u->faction, msg); + } + else { + add_message(&r->msgs, msg); + } + msg_release(msg); + } } - msg_release(msg); - } + bp = &b->next; } - bp = &b->next; - } } void economics(region * r) { - unit *u; - request *recruitorders = NULL; + unit *u; + request *recruitorders = NULL; - /* Geben vor Selbstmord (doquit)! Hier alle unmittelbaren Befehle. - * Rekrutieren vor allen Einnahmequellen. Bewachen JA vor Steuern - * eintreiben. */ + /* Geben vor Selbstmord (doquit)! Hier alle unmittelbaren Befehle. + * Rekrutieren vor allen Einnahmequellen. Bewachen JA vor Steuern + * eintreiben. */ - for (u = r->units; u; u = u->next) { - order *ord; - if (u->number > 0) { - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_GIVE) { - give_cmd(u, ord); - } else if (kwd == K_FORGET) { - forget_cmd(u, ord); + for (u = r->units; u; u = u->next) { + order *ord; + if (u->number > 0) { + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_GIVE) { + give_cmd(u, ord); + } + else if (kwd == K_FORGET) { + forget_cmd(u, ord); + } + if (u->orders == NULL) { + break; + } + } } - if (u->orders == NULL) { - break; - } - } } - } - /* RECRUIT orders */ + /* RECRUIT orders */ - if (rules_recruit < 0) - recruit_init(); - for (u = r->units; u; u = u->next) { - order *ord; + if (rules_recruit < 0) + recruit_init(); + for (u = r->units; u; u = u->next) { + order *ord; - if ((rules_recruit & RECRUIT_MERGE) || u->number == 0) { - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_RECRUIT) { - recruit(u, ord, &recruitorders); - break; + if ((rules_recruit & RECRUIT_MERGE) || u->number == 0) { + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_RECRUIT) { + recruit(u, ord, &recruitorders); + break; + } + } } - } } - } - if (recruitorders) - expandrecruit(r, recruitorders); - remove_empty_units_in_region(r); + if (recruitorders) + expandrecruit(r, recruitorders); + remove_empty_units_in_region(r); - for (u = r->units; u; u = u->next) { - order *ord; - bool destroyed = false; - if (u->number > 0) { - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_DESTROY) { - if (!destroyed) { - if (destroy_cmd(u, ord) != 0) - ord = NULL; - destroyed = true; - } - } - if (u->orders == NULL) { - break; - } - } - } - } + for (u = r->units; u; u = u->next) { + order *ord; + bool destroyed = false; + if (u->number > 0) { + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_DESTROY) { + if (!destroyed) { + if (destroy_cmd(u, ord) != 0) + ord = NULL; + destroyed = true; + } + } + if (u->orders == NULL) { + break; + } + } + } + } } @@ -1225,205 +1247,207 @@ void economics(region * r) static void manufacture(unit * u, const item_type * itype, int want) { - int n; - int skill; - int minskill = itype->construction->minskill; - skill_t sk = itype->construction->skill; + int n; + int skill; + int minskill = itype->construction->minskill; + skill_t sk = itype->construction->skill; - skill = effskill(u, sk); - skill = - skillmod(itype->rtype->attribs, u, u->region, sk, skill, SMF_PRODUCTION); + skill = effskill(u, sk); + skill = + skillmod(itype->rtype->attribs, u, u->region, sk, skill, SMF_PRODUCTION); - if (skill < 0) { - /* an error occured */ - int err = -skill; - cmistake(u, u->thisorder, err, MSG_PRODUCE); - return; - } + if (skill < 0) { + /* an error occured */ + int err = -skill; + cmistake(u, u->thisorder, err, MSG_PRODUCE); + return; + } - if (want == 0) { - want = maxbuild(u, itype->construction); - } - n = build(u, itype->construction, 0, want); - switch (n) { - case ENEEDSKILL: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); - return; - case EBUILDINGREQ: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "building_needed", "building", - itype->construction->btype->_name)); - return; - case ELOWSKILL: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "manufacture_skills", - "skill minskill product", sk, minskill, itype->rtype, 1)); - return; - case ENOMATERIALS: - ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - itype->construction, want)); - return; - } - if (n > 0) { - i_change(&u->items, itype, n); - if (want == INT_MAX) - want = n; - ADDMSG(&u->faction->msgs, msg_message("manufacture", - "unit region amount wanted resource", u, u->region, n, want, - itype->rtype)); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", - "")); - } + if (want == 0) { + want = maxbuild(u, itype->construction); + } + n = build(u, itype->construction, 0, want); + switch (n) { + case ENEEDSKILL: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); + return; + case EBUILDINGREQ: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "building_needed", "building", + itype->construction->btype->_name)); + return; + case ELOWSKILL: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "manufacture_skills", + "skill minskill product", sk, minskill, itype->rtype, 1)); + return; + case ENOMATERIALS: + ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, + itype->construction, want)); + return; + } + if (n > 0) { + i_change(&u->items, itype, n); + if (want == INT_MAX) + want = n; + ADDMSG(&u->faction->msgs, msg_message("manufacture", + "unit region amount wanted resource", u, u->region, n, want, + itype->rtype)); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", + "")); + } } typedef struct allocation { - struct allocation *next; - int want, get; - double save; - unsigned int flags; - unit *unit; + struct allocation *next; + int want, get; + double save; + unsigned int flags; + unit *unit; } allocation; #define new_allocation() calloc(sizeof(allocation), 1) #define free_allocation(a) free(a) typedef struct allocation_list { - struct allocation_list *next; - allocation *data; - const resource_type *type; + struct allocation_list *next; + allocation *data; + const resource_type *type; } allocation_list; static allocation_list *allocations; static bool can_guard(const unit * guard, const unit * u) { - if (fval(guard, UFL_ISNEW)) - return false; - if (guard->number <= 0 || !cansee(guard->faction, guard->region, u, 0)) - return false; - if (besieged(guard) || !(fval(u_race(guard), RCF_UNARMEDGUARD) - || armedmen(guard, true))) - return false; + if (fval(guard, UFL_ISNEW)) + return false; + if (guard->number <= 0 || !cansee(guard->faction, guard->region, u, 0)) + return false; + if (besieged(guard) || !(fval(u_race(guard), RCF_UNARMEDGUARD) + || armedmen(guard, true))) + return false; - return !alliedunit(guard, u->faction, HELP_GUARD); + return !alliedunit(guard, u->faction, HELP_GUARD); } enum { - AFL_DONE = 1 << 0, - AFL_LOWSKILL = 1 << 1 + AFL_DONE = 1 << 0, + AFL_LOWSKILL = 1 << 1 }; static void allocate_resource(unit * u, const resource_type * rtype, int want) { - const item_type *itype = resource2item(rtype); - region *r = u->region; - int dm = 0; - allocation_list *alist; - allocation *al; - attrib *a = a_find(rtype->attribs, &at_resourcelimit); - resource_limit *rdata = (resource_limit *) a->data.v; + const item_type *itype = resource2item(rtype); + region *r = u->region; + int dm = 0; + allocation_list *alist; + allocation *al; + attrib *a = a_find(rtype->attribs, &at_resourcelimit); + resource_limit *rdata = (resource_limit *)a->data.v; const resource_type *rring; int amount, skill; - /* momentan kann man keine ressourcen abbauen, wenn man dafür - * Materialverbrauch hat: */ - assert(itype != NULL && (itype->construction == NULL - || itype->construction->materials == NULL)); - assert(rdata != NULL); + /* momentan kann man keine ressourcen abbauen, wenn man dafür + * Materialverbrauch hat: */ + assert(itype != NULL && (itype->construction == NULL + || itype->construction->materials == NULL)); + assert(rdata != NULL); - if (rdata->limit != NULL) { - int avail = rdata->limit(r, rtype); - if (avail <= 0) { - cmistake(u, u->thisorder, 121, MSG_PRODUCE); - return; - } - } - - if (besieged(u)) { - cmistake(u, u->thisorder, 60, MSG_PRODUCE); - return; - } - - if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_REQUIREDBUILDING) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - if (mod->btype && mod->btype != btype) { - cmistake(u, u->thisorder, 104, MSG_PRODUCE); - return; + if (rdata->limit != NULL) { + int avail = rdata->limit(r, rtype); + if (avail <= 0) { + cmistake(u, u->thisorder, 121, MSG_PRODUCE); + return; } - } } - } - if (rdata->guard != 0) { - unit *u2; - for (u2 = r->units; u2; u2 = u2->next) { - if (is_guard(u2, rdata->guard) != 0 && can_guard(u2, u)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + if (besieged(u)) { + cmistake(u, u->thisorder, 60, MSG_PRODUCE); return; - } } - } - - /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. - * Als magische Wesen 'sehen' Bergwächter alles und werden durch - * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). - */ - if (itype->rtype && (itype->rtype==get_resourcetype(R_IRON) || itype->rtype==rt_find("laen"))) { - unit *u2; - for (u2 = r->units; u2; u2 = u2->next) { - if (is_guard(u, GUARD_MINING) - && !fval(u2, UFL_ISNEW) - && u2->number && !alliedunit(u2, u->faction, HELP_GUARD)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); - return; - } - } - } - - assert(itype->construction->skill != 0 - || "limited resource needs a required skill for making it"); - skill = eff_skill(u, itype->construction->skill, u->region); - if (skill == 0) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); - return; - } - if (skill < itype->construction->minskill) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "manufacture_skills", - "skill minskill product", sk, itype->construction->minskill, - itype->rtype)); - return; - } else { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SKILL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - skill += mod->value.i; + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_REQUIREDBUILDING) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + if (mod->btype && mod->btype != btype) { + cmistake(u, u->thisorder, 104, MSG_PRODUCE); + return; + } } - } } - } } - } - amount = skill * u->number; - /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ - /* mit Flinkfingerring verzehnfacht sich die Produktion */ + if (rdata->guard != 0) { + unit *u2; + for (u2 = r->units; u2; u2 = u2->next) { + if (is_guard(u2, rdata->guard) != 0 && can_guard(u2, u)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + return; + } + } + } + + /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. + * Als magische Wesen 'sehen' Bergwächter alles und werden durch + * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). + */ + if (itype->rtype && (itype->rtype == get_resourcetype(R_IRON) || itype->rtype == rt_find("laen"))) { + unit *u2; + for (u2 = r->units; u2; u2 = u2->next) { + if (is_guard(u, GUARD_MINING) + && !fval(u2, UFL_ISNEW) + && u2->number && !alliedunit(u2, u->faction, HELP_GUARD)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + return; + } + } + } + + assert(itype->construction->skill != 0 + || "limited resource needs a required skill for making it"); + skill = eff_skill(u, itype->construction->skill, u->region); + if (skill == 0) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); + return; + } + if (skill < itype->construction->minskill) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "manufacture_skills", + "skill minskill product", sk, itype->construction->minskill, + itype->rtype)); + return; + } + else { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + + if (rdata->modifiers) { + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_SKILL) { + if (mod->btype == NULL || mod->btype == btype) { + if (mod->race == NULL || mod->race == u_race(u)) { + skill += mod->value.i; + } + } + } + } + } + } + amount = skill * u->number; + /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ + + /* mit Flinkfingerring verzehnfacht sich die Produktion */ rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); if (rring) { int dm = i_get(u->items, rring->itype); @@ -1437,410 +1461,426 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) amount += dm * skill; /* dm Personen produzieren doppelt */ } - amount /= itype->construction->minskill; + amount /= itype->construction->minskill; - /* Limitierung durch Parameter m. */ - if (want > 0 && want < amount) - amount = want; + /* Limitierung durch Parameter m. */ + if (want > 0 && want < amount) + amount = want; - alist = allocations; - while (alist && alist->type != rtype) - alist = alist->next; - if (!alist) { - alist = calloc(sizeof(struct allocation_list), 1); - alist->next = allocations; - alist->type = rtype; - allocations = alist; - } - al = new_allocation(); - al->want = amount; - al->save = 1.0; - al->next = alist->data; - al->unit = u; - alist->data = al; - - if (rdata->modifiers) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SAVEMATERIAL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - al->save *= mod->value.f; - } - } - } + alist = allocations; + while (alist && alist->type != rtype) + alist = alist->next; + if (!alist) { + alist = calloc(sizeof(struct allocation_list), 1); + alist->next = allocations; + alist->type = rtype; + allocations = alist; + } + al = new_allocation(); + al->want = amount; + al->save = 1.0; + al->next = alist->data; + al->unit = u; + alist->data = al; + + if (rdata->modifiers) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_SAVEMATERIAL) { + if (mod->btype == NULL || mod->btype == btype) { + if (mod->race == NULL || mod->race == u_race(u)) { + al->save *= mod->value.f; + } + } + } + } } - } } static int required(int want, double save) { - int norders = (int)(want * save); - if (norders < want * save) - ++norders; - return norders; + int norders = (int)(want * save); + if (norders < want * save) + ++norders; + return norders; } static void leveled_allocation(const resource_type * rtype, region * r, allocation * alist) { - const item_type *itype = resource2item(rtype); - rawmaterial *rm = rm_get(r, rtype); - int need; - bool first = true; + const item_type *itype = resource2item(rtype); + rawmaterial *rm = rm_get(r, rtype); + int need; + bool first = true; - if (rm != NULL) { - do { - int avail = rm->amount; - int norders = 0; - allocation *al; + if (rm != NULL) { + do { + int avail = rm->amount; + int norders = 0; + allocation *al; - if (avail <= 0) { - for (al = alist; al; al = al->next) { - al->get = 0; - } - break; - } - - assert(avail > 0); - - for (al = alist; al; al = al->next) - if (!fval(al, AFL_DONE)) { - int req = required(al->want - al->get, al->save); - assert(al->get <= al->want && al->get >= 0); - if (eff_skill(al->unit, itype->construction->skill, r) - >= rm->level + itype->construction->minskill - 1) { - if (req) { - norders += req; - } else { - fset(al, AFL_DONE); + if (avail <= 0) { + for (al = alist; al; al = al->next) { + al->get = 0; + } + break; } - } else { - fset(al, AFL_DONE); - if (first) - fset(al, AFL_LOWSKILL); - } - } - need = norders; - avail = _min(avail, norders); - if (need > 0) { - int use = 0; - for (al = alist; al; al = al->next) - if (!fval(al, AFL_DONE)) { - if (avail > 0) { - int want = required(al->want - al->get, al->save); - int x = avail * want / norders; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ - if (rng_int() % norders < (avail * want) % norders) - ++x; - avail -= x; - use += x; - norders -= want; - need -= x; - al->get = _min(al->want, al->get + (int)(x / al->save)); + assert(avail > 0); + + for (al = alist; al; al = al->next) + if (!fval(al, AFL_DONE)) { + int req = required(al->want - al->get, al->save); + assert(al->get <= al->want && al->get >= 0); + if (eff_skill(al->unit, itype->construction->skill, r) + >= rm->level + itype->construction->minskill - 1) { + if (req) { + norders += req; + } + else { + fset(al, AFL_DONE); + } + } + else { + fset(al, AFL_DONE); + if (first) + fset(al, AFL_LOWSKILL); + } + } + need = norders; + + avail = _min(avail, norders); + if (need > 0) { + int use = 0; + for (al = alist; al; al = al->next) + if (!fval(al, AFL_DONE)) { + if (avail > 0) { + int want = required(al->want - al->get, al->save); + int x = avail * want / norders; + /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + if (rng_int() % norders < (avail * want) % norders) + ++x; + avail -= x; + use += x; + norders -= want; + need -= x; + al->get = _min(al->want, al->get + (int)(x / al->save)); + } + } + if (use) { + assert(use <= rm->amount); + rm->type->use(rm, r, use); + } + assert(avail == 0 || norders == 0); } - } - if (use) { - assert(use <= rm->amount); - rm->type->use(rm, r, use); - } - assert(avail == 0 || norders == 0); - } - first = false; - } while (need > 0); - } + first = false; + } while (need > 0); + } } static void attrib_allocation(const resource_type * rtype, region * r, allocation * alist) { - allocation *al; - int norders = 0; - attrib *a = a_find(rtype->attribs, &at_resourcelimit); - resource_limit *rdata = (resource_limit *) a->data.v; - int avail = rdata->value; + allocation *al; + int norders = 0; + attrib *a = a_find(rtype->attribs, &at_resourcelimit); + resource_limit *rdata = (resource_limit *)a->data.v; + int avail = rdata->value; - for (al = alist; al; al = al->next) { - norders += required(al->want, al->save); - } - - if (rdata->limit) { - avail = rdata->limit(r, rtype); - if (avail < 0) - avail = 0; - } - - avail = _min(avail, norders); - for (al = alist; al; al = al->next) { - if (avail > 0) { - int want = required(al->want, al->save); - int x = avail * want / norders; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ - if (rng_int() % norders < (avail * want) % norders) - ++x; - avail -= x; - norders -= want; - al->get = _min(al->want, (int)(x / al->save)); - if (rdata->produce) { - int use = required(al->get, al->save); - if (use) - rdata->produce(r, rtype, use); - } + for (al = alist; al; al = al->next) { + norders += required(al->want, al->save); } - } - assert(avail == 0 || norders == 0); + + if (rdata->limit) { + avail = rdata->limit(r, rtype); + if (avail < 0) + avail = 0; + } + + avail = _min(avail, norders); + for (al = alist; al; al = al->next) { + if (avail > 0) { + int want = required(al->want, al->save); + int x = avail * want / norders; + /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + if (rng_int() % norders < (avail * want) % norders) + ++x; + avail -= x; + norders -= want; + al->get = _min(al->want, (int)(x / al->save)); + if (rdata->produce) { + int use = required(al->get, al->save); + if (use) + rdata->produce(r, rtype, use); + } + } + } + assert(avail == 0 || norders == 0); } -typedef void (*allocate_function) (const resource_type *, struct region *, - struct allocation *); +typedef void(*allocate_function) (const resource_type *, struct region *, +struct allocation *); static allocate_function get_allocator(const struct resource_type *rtype) { - attrib *a = a_find(rtype->attribs, &at_resourcelimit); + attrib *a = a_find(rtype->attribs, &at_resourcelimit); - if (a != NULL) { - resource_limit *rdata = (resource_limit *) a->data.v; - if (rdata->value > 0 || rdata->limit != NULL) { - return attrib_allocation; + if (a != NULL) { + resource_limit *rdata = (resource_limit *)a->data.v; + if (rdata->value > 0 || rdata->limit != NULL) { + return attrib_allocation; + } + return leveled_allocation; } - return leveled_allocation; - } - return NULL; + return NULL; } void split_allocations(region * r) { - allocation_list **p_alist = &allocations; - freset(r, RF_SELECT); - while (*p_alist) { - allocation_list *alist = *p_alist; - const resource_type *rtype = alist->type; - allocate_function alloc = get_allocator(rtype); - const item_type *itype = resource2item(rtype); - allocation **p_al = &alist->data; - + allocation_list **p_alist = &allocations; freset(r, RF_SELECT); - alloc(rtype, r, alist->data); + while (*p_alist) { + allocation_list *alist = *p_alist; + const resource_type *rtype = alist->type; + allocate_function alloc = get_allocator(rtype); + const item_type *itype = resource2item(rtype); + allocation **p_al = &alist->data; - while (*p_al) { - allocation *al = *p_al; - if (al->get) { - assert(itype || !"not implemented for non-items"); - i_change(&al->unit->items, itype, al->get); - produceexp(al->unit, itype->construction->skill, al->unit->number); - fset(r, RF_SELECT); - } - if (al->want == INT_MAX) - al->want = al->get; - ADDMSG(&al->unit->faction->msgs, msg_message("produce", - "unit region amount wanted resource", - al->unit, al->unit->region, al->get, al->want, rtype)); - *p_al = al->next; - free_allocation(al); + freset(r, RF_SELECT); + alloc(rtype, r, alist->data); + + while (*p_al) { + allocation *al = *p_al; + if (al->get) { + assert(itype || !"not implemented for non-items"); + i_change(&al->unit->items, itype, al->get); + produceexp(al->unit, itype->construction->skill, al->unit->number); + fset(r, RF_SELECT); + } + if (al->want == INT_MAX) + al->want = al->get; + ADDMSG(&al->unit->faction->msgs, msg_message("produce", + "unit region amount wanted resource", + al->unit, al->unit->region, al->get, al->want, rtype)); + *p_al = al->next; + free_allocation(al); + } + *p_alist = alist->next; + free(alist); } - *p_alist = alist->next; - free(alist); - } - allocations = NULL; + allocations = NULL; } static void create_potion(unit * u, const potion_type * ptype, int want) { - int built; + int built; - if (want == 0) { - want = maxbuild(u, ptype->itype->construction); - } - built = build(u, ptype->itype->construction, 0, want); - switch (built) { - case ELOWSKILL: - case ENEEDSKILL: - /* no skill, or not enough skill points to build */ - cmistake(u, u->thisorder, 50, MSG_PRODUCE); - break; - case EBUILDINGREQ: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "building_needed", "building", - ptype->itype->construction->btype->_name)); - break; - case ECOMPLETE: - assert(0); - break; - case ENOMATERIALS: - /* something missing from the list of materials */ - ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - ptype->itype->construction, want)); - return; - break; - default: - i_change(&u->items, ptype->itype, built); - if (want == INT_MAX) - want = built; - ADDMSG(&u->faction->msgs, msg_message("manufacture", - "unit region amount wanted resource", u, u->region, built, want, - ptype->itype->rtype)); - break; - } + if (want == 0) { + want = maxbuild(u, ptype->itype->construction); + } + built = build(u, ptype->itype->construction, 0, want); + switch (built) { + case ELOWSKILL: + case ENEEDSKILL: + /* no skill, or not enough skill points to build */ + cmistake(u, u->thisorder, 50, MSG_PRODUCE); + break; + case EBUILDINGREQ: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "building_needed", "building", + ptype->itype->construction->btype->_name)); + break; + case ECOMPLETE: + assert(0); + break; + case ENOMATERIALS: + /* something missing from the list of materials */ + ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, + ptype->itype->construction, want)); + return; + break; + default: + i_change(&u->items, ptype->itype, built); + if (want == INT_MAX) + want = built; + ADDMSG(&u->faction->msgs, msg_message("manufacture", + "unit region amount wanted resource", u, u->region, built, want, + ptype->itype->rtype)); + break; + } } static void create_item(unit * u, const item_type * itype, int want) { - if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { + if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { #if GUARD_DISABLES_PRODUCTION == 1 - if (is_guarded(u->region, u, GUARD_PRODUCE)) { - cmistake(u, u->thisorder, 70, MSG_EVENT); - return; - } + if (is_guarded(u->region, u, GUARD_PRODUCE)) { + cmistake(u, u->thisorder, 70, MSG_EVENT); + return; + } #endif - allocate_resource(u, itype->rtype, want); - } else { - const potion_type *ptype = resource2potion(itype->rtype); - if (ptype != NULL) - create_potion(u, ptype, want); - else if (itype->construction && itype->construction->materials) - manufacture(u, itype, want); - else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_cannotmake", "")); + allocate_resource(u, itype->rtype, want); + } + else { + const potion_type *ptype = resource2potion(itype->rtype); + if (ptype != NULL) + create_potion(u, ptype, want); + else if (itype->construction && itype->construction->materials) + manufacture(u, itype, want); + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_cannotmake", "")); + } } - } } int make_cmd(unit * u, struct order *ord) { - region *r = u->region; - const building_type *btype; - const ship_type *stype; - param_t p; - int m; - const item_type *itype; - const char *s; - const struct locale *lang = u->faction->locale; - char ibuf[16]; + region *r = u->region; + const building_type *btype; + const ship_type *stype; + param_t p; + int m; + const item_type *itype; + const char *s; + const struct locale *lang = u->faction->locale; + char ibuf[16]; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - m = atoi((const char *)s); - sprintf(ibuf, "%d", m); - if (!strcmp(ibuf, (const char *)s)) { - /* first came a want-paramter */ + init_tokens(ord); + skip_token(); s = getstrtoken(); - } else { - m = INT_MAX; - } - p = findparam(s, u->faction->locale); - - /* MACHE TEMP kann hier schon gar nicht auftauchen, weil diese nicht in - * thisorder abgespeichert werden - und auf den ist getstrtoken() beim - * aufruf von make geeicht */ - - if (p == P_ROAD) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 275, MSG_PRODUCE); - } else { - direction_t d = get_direction(getstrtoken(), u->faction->locale); - if (d != NODIRECTION) { - build_road(r, u, m, d); - } else { - /* Die Richtung wurde nicht erkannt */ - cmistake(u, ord, 71, MSG_PRODUCE); - } + m = atoi((const char *)s); + sprintf(ibuf, "%d", m); + if (!strcmp(ibuf, (const char *)s)) { + /* first came a want-paramter */ + s = getstrtoken(); } + else { + m = INT_MAX; + } + + p = findparam(s, u->faction->locale); + + /* MACHE TEMP kann hier schon gar nicht auftauchen, weil diese nicht in + * thisorder abgespeichert werden - und auf den ist getstrtoken() beim + * aufruf von make geeicht */ + + if (p == P_ROAD) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 275, MSG_PRODUCE); + } + else { + direction_t d = get_direction(getstrtoken(), u->faction->locale); + if (d != NODIRECTION) { + build_road(r, u, m, d); + } + else { + /* Die Richtung wurde nicht erkannt */ + cmistake(u, ord, 71, MSG_PRODUCE); + } + } + return 0; + } + else if (p == P_SHIP) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 276, MSG_PRODUCE); + } + else { + continue_ship(r, u, m); + } + return 0; + } + else if (p == P_HERBS) { + herbsearch(r, u, m); + return 0; + } + + /* since the string can match several objects, like in 'academy' and + * 'academy of arts', we need to figure out what the player meant. + * This is not 100% safe. + */ + stype = findshiptype(s, lang); + btype = findbuildingtype(s, lang); + itype = finditemtype(s, lang); + + if (itype != NULL && (btype != NULL || stype != NULL)) { + if (itype->construction == NULL) { + /* if the item cannot be made, we probably didn't mean to make it */ + itype = NULL; + } + else if (stype != NULL) { + const char *sname = LOC(lang, stype->_name); + const char *iname = LOC(lang, resourcename(itype->rtype, 0)); + if (strlen(iname) < strlen(sname)) + stype = NULL; + else + itype = NULL; + } + else { + const char *bname = LOC(lang, btype->_name); + const char *iname = LOC(lang, resourcename(itype->rtype, 0)); + if (strlen(iname) < strlen(bname)) + btype = NULL; + else + itype = NULL; + } + } + + if (btype != NULL && stype != NULL) { + const char *bname = LOC(lang, btype->_name); + const char *sname = LOC(lang, stype->_name); + if (strlen(sname) < strlen(bname)) + btype = NULL; + else + stype = NULL; + } + + if (stype != NOSHIP) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 276, MSG_PRODUCE); + } + else { + create_ship(r, u, stype, m, ord); + } + } + else if (btype != NOBUILDING) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 94, MSG_PRODUCE); + } + else { + int id = getid(); + build_building(u, btype, id, m, ord); + } + } + else if (itype != NULL) { + create_item(u, itype, m); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + } + return 0; - } else if (p == P_SHIP) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 276, MSG_PRODUCE); - } else { - continue_ship(r, u, m); - } - return 0; - } else if (p == P_HERBS) { - herbsearch(r, u, m); - return 0; - } - - /* since the string can match several objects, like in 'academy' and - * 'academy of arts', we need to figure out what the player meant. - * This is not 100% safe. - */ - stype = findshiptype(s, lang); - btype = findbuildingtype(s, lang); - itype = finditemtype(s, lang); - - if (itype != NULL && (btype != NULL || stype != NULL)) { - if (itype->construction == NULL) { - /* if the item cannot be made, we probably didn't mean to make it */ - itype = NULL; - } else if (stype != NULL) { - const char *sname = LOC(lang, stype->_name); - const char *iname = LOC(lang, resourcename(itype->rtype, 0)); - if (strlen(iname) < strlen(sname)) - stype = NULL; - else - itype = NULL; - } else { - const char *bname = LOC(lang, btype->_name); - const char *iname = LOC(lang, resourcename(itype->rtype, 0)); - if (strlen(iname) < strlen(bname)) - btype = NULL; - else - itype = NULL; - } - } - - if (btype != NULL && stype != NULL) { - const char *bname = LOC(lang, btype->_name); - const char *sname = LOC(lang, stype->_name); - if (strlen(sname) < strlen(bname)) - btype = NULL; - else - stype = NULL; - } - - if (stype != NOSHIP) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 276, MSG_PRODUCE); - } else { - create_ship(r, u, stype, m, ord); - } - } else if (btype != NOBUILDING) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 94, MSG_PRODUCE); - } else { - int id = getid(); - build_building(u, btype, id, m, ord); - } - } else if (itype != NULL) { - create_item(u, itype, m); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); - } - - return 0; } /* ------------------------------------------------------------- */ static void free_luxuries(struct attrib *a) { - item *itm = (item *) a->data.v; - a->data.v = NULL; - i_freeall(&itm); + item *itm = (item *)a->data.v; + a->data.v = NULL; + i_freeall(&itm); } const attrib_type at_luxuries = { - "luxuries", NULL, free_luxuries, NULL, NULL, NULL + "luxuries", NULL, free_luxuries, NULL, NULL, NULL }; static void expandbuying(region * r, request * buyorders) @@ -1857,208 +1897,210 @@ static void expandbuying(region * r, request * buyorders) int i, j; const luxury_type *ltype; - if (ntrades == 0) { - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++ntrades; - trades = gc_add(calloc(sizeof(struct trade), ntrades)); - for (i = 0, ltype = luxurytypes; i != ntrades; ++i, ltype = ltype->next) - trades[i].type = ltype; - } - for (i = 0; i != ntrades; ++i) { - trades[i].number = 0; - trades[i].multi = 1; - } - - if (!buyorders) - return; - - /* Initialisation. multiplier ist der Multiplikator auf den - * Verkaufspreis. Für max_products Produkte kauft man das Produkt zum - * einfachen Verkaufspreis, danach erhöht sich der Multiplikator um 1. - * counter ist ein Zähler, der die gekauften Produkte zählt. money - * wird für die debug message gebraucht. */ - - max_products = rpeasants(r) / TRADE_FRACTION; - - /* Kauf - auch so programmiert, daß er leicht erweiterbar auf mehrere - * Güter pro Monat ist. j sind die Befehle, i der Index des - * gehandelten Produktes. */ - if (max_products > 0) { - expandorders(r, buyorders); - if (!norders) - return; - - for (j = 0; j != norders; j++) { - int price, multi; - ltype = oa[j].type.ltype; - trade = trades; - while (trade->type != ltype) - ++trade; - multi = trade->multi; - price = ltype->price * multi; - - if (get_pooled(oa[j].unit, rsilver, GET_DEFAULT, - price) >= price) { - unit *u = oa[j].unit; - item *items; - - /* litems zählt die Güter, die verkauft wurden, u->n das Geld, das - * verdient wurde. Dies muß gemacht werden, weil der Preis ständig sinkt, - * man sich also das verdiente Geld und die verkauften Produkte separat - * merken muß. */ - attrib *a = a_find(u->attribs, &at_luxuries); - if (a == NULL) - a = a_add(&u->attribs, a_new(&at_luxuries)); - - items = a->data.v; - i_change(&items, ltype->itype, 1); - a->data.v = items; - i_change(&oa[j].unit->items, ltype->itype, 1); - use_pooled(u, rsilver, GET_DEFAULT, price); - if (u->n < 0) - u->n = 0; - u->n += price; - - rsetmoney(r, rmoney(r) + price); - - /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt - * der Preis Multiplikator für das Produkt um den Faktor 1. Der Zähler - * wird wieder auf 0 gesetzt. */ - if (++trade->number == max_products) { - trade->number = 0; - ++trade->multi; - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + if (ntrades == 0) { + for (ltype = luxurytypes; ltype; ltype = ltype->next) + ++ntrades; + trades = gc_add(calloc(sizeof(struct trade), ntrades)); + for (i = 0, ltype = luxurytypes; i != ntrades; ++i, ltype = ltype->next) + trades[i].type = ltype; } - free(oa); - - /* Ausgabe an Einheiten */ - - for (u = r->units; u; u = u->next) { - attrib *a = a_find(u->attribs, &at_luxuries); - item *itm; - if (a == NULL) - continue; - ADDMSG(&u->faction->msgs, msg_message("buy", "unit money", u, u->n)); - for (itm = (item *) a->data.v; itm; itm = itm->next) { - if (itm->number) { - ADDMSG(&u->faction->msgs, msg_message("buyamount", - "unit amount resource", u, itm->number, itm->type->rtype)); - } - } - a_remove(&u->attribs, a); + for (i = 0; i != ntrades; ++i) { + trades[i].number = 0; + trades[i].multi = 1; + } + + if (!buyorders) + return; + + /* Initialisation. multiplier ist der Multiplikator auf den + * Verkaufspreis. Für max_products Produkte kauft man das Produkt zum + * einfachen Verkaufspreis, danach erhöht sich der Multiplikator um 1. + * counter ist ein Zähler, der die gekauften Produkte zählt. money + * wird für die debug message gebraucht. */ + + max_products = rpeasants(r) / TRADE_FRACTION; + + /* Kauf - auch so programmiert, daß er leicht erweiterbar auf mehrere + * Güter pro Monat ist. j sind die Befehle, i der Index des + * gehandelten Produktes. */ + if (max_products > 0) { + expandorders(r, buyorders); + if (!norders) + return; + + for (j = 0; j != norders; j++) { + int price, multi; + ltype = oa[j].type.ltype; + trade = trades; + while (trade->type != ltype) + ++trade; + multi = trade->multi; + price = ltype->price * multi; + + if (get_pooled(oa[j].unit, rsilver, GET_DEFAULT, + price) >= price) { + unit *u = oa[j].unit; + item *items; + + /* litems zählt die Güter, die verkauft wurden, u->n das Geld, das + * verdient wurde. Dies muß gemacht werden, weil der Preis ständig sinkt, + * man sich also das verdiente Geld und die verkauften Produkte separat + * merken muß. */ + attrib *a = a_find(u->attribs, &at_luxuries); + if (a == NULL) + a = a_add(&u->attribs, a_new(&at_luxuries)); + + items = a->data.v; + i_change(&items, ltype->itype, 1); + a->data.v = items; + i_change(&oa[j].unit->items, ltype->itype, 1); + use_pooled(u, rsilver, GET_DEFAULT, price); + if (u->n < 0) + u->n = 0; + u->n += price; + + rsetmoney(r, rmoney(r) + price); + + /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt + * der Preis Multiplikator für das Produkt um den Faktor 1. Der Zähler + * wird wieder auf 0 gesetzt. */ + if (++trade->number == max_products) { + trade->number = 0; + ++trade->multi; + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } + } + free(oa); + + /* Ausgabe an Einheiten */ + + for (u = r->units; u; u = u->next) { + attrib *a = a_find(u->attribs, &at_luxuries); + item *itm; + if (a == NULL) + continue; + ADDMSG(&u->faction->msgs, msg_message("buy", "unit money", u, u->n)); + for (itm = (item *)a->data.v; itm; itm = itm->next) { + if (itm->number) { + ADDMSG(&u->faction->msgs, msg_message("buyamount", + "unit amount resource", u, itm->number, itm->type->rtype)); + } + } + a_remove(&u->attribs, a); + } } - } } attrib_type at_trades = { - "trades", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ + "trades", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ }; static void buy(unit * u, request ** buyorders, struct order *ord) { - region *r = u->region; - int n, k; - request *o; - attrib *a; - const item_type *itype = NULL; - const luxury_type *ltype = NULL; - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - /* Im Augenblick kann man nur 1 Produkt kaufen. expandbuying ist aber - * schon dafür ausgerüstet, mehrere Produkte zu kaufen. */ - - init_tokens(ord); - skip_token(); - n = getuint(); - if (!n) { - cmistake(u, ord, 26, MSG_COMMERCE); - return; - } - if (besieged(u)) { - /* Belagerte Einheiten können nichts kaufen. */ - cmistake(u, ord, 60, MSG_COMMERCE); - return; - } - - if (u_race(u) == get_race(RC_INSECT)) { - /* entweder man ist insekt, oder... */ - if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) - && !rbuildings(r)) { - cmistake(u, ord, 119, MSG_COMMERCE); - return; + region *r = u->region; + int n, k; + request *o; + attrib *a; + const item_type *itype = NULL; + const luxury_type *ltype = NULL; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; } - } else { - /* ...oder in der Region muß es eine Burg geben. */ - building *b = 0; - if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); - - for (b = r->buildings; b; b = b->next) { - if (b->type == bt_castle && b->size >= 2) { - break; - } - } - } - if (b == NULL) { - cmistake(u, ord, 119, MSG_COMMERCE); - return; - } - } - - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ - k = u->number * 10 * eff_skill(u, SK_TRADE, r); - - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ - a = a_find(u->attribs, &at_trades); - if (!a) { - a = a_add(&u->attribs, a_new(&at_trades)); - } else { - k -= a->data.i; - } - - n = _min(n, k); - - if (!n) { - cmistake(u, ord, 102, MSG_COMMERCE); - return; - } - - assert(n >= 0); - /* die Menge der verkauften Güter merken */ - a->data.i += n; - - itype = finditemtype(getstrtoken(), u->faction->locale); - if (itype != NULL) { - ltype = resource2luxury(itype->rtype); - if (ltype == NULL) { - cmistake(u, ord, 124, MSG_COMMERCE); - return; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; } - } - if (r_demand(r, ltype)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "luxury_notsold", "")); - return; - } - o = (request *) calloc(1, sizeof(request)); - o->type.ltype = ltype; /* sollte immer gleich sein */ + /* Im Augenblick kann man nur 1 Produkt kaufen. expandbuying ist aber + * schon dafür ausgerüstet, mehrere Produkte zu kaufen. */ - o->unit = u; - o->qty = n; - addlist(buyorders, o); + init_tokens(ord); + skip_token(); + n = getuint(); + if (!n) { + cmistake(u, ord, 26, MSG_COMMERCE); + return; + } + if (besieged(u)) { + /* Belagerte Einheiten können nichts kaufen. */ + cmistake(u, ord, 60, MSG_COMMERCE); + return; + } + + if (u_race(u) == get_race(RC_INSECT)) { + /* entweder man ist insekt, oder... */ + if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) + && !rbuildings(r)) { + cmistake(u, ord, 119, MSG_COMMERCE); + return; + } + } + else { + /* ...oder in der Region muß es eine Burg geben. */ + building *b = 0; + if (r->buildings) { + const struct building_type *bt_castle = bt_find("castle"); + + for (b = r->buildings; b; b = b->next) { + if (b->type == bt_castle && b->size >= 2) { + break; + } + } + } + if (b == NULL) { + cmistake(u, ord, 119, MSG_COMMERCE); + return; + } + } + + /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + k = u->number * 10 * eff_skill(u, SK_TRADE, r); + + /* hat der Händler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften Güter abgezogen werden */ + a = a_find(u->attribs, &at_trades); + if (!a) { + a = a_add(&u->attribs, a_new(&at_trades)); + } + else { + k -= a->data.i; + } + + n = _min(n, k); + + if (!n) { + cmistake(u, ord, 102, MSG_COMMERCE); + return; + } + + assert(n >= 0); + /* die Menge der verkauften Güter merken */ + a->data.i += n; + + itype = finditemtype(getstrtoken(), u->faction->locale); + if (itype != NULL) { + ltype = resource2luxury(itype->rtype); + if (ltype == NULL) { + cmistake(u, ord, 124, MSG_COMMERCE); + return; + } + } + if (r_demand(r, ltype)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "luxury_notsold", "")); + return; + } + o = (request *)calloc(1, sizeof(request)); + o->type.ltype = ltype; /* sollte immer gleich sein */ + + o->unit = u; + o->qty = n; + addlist(buyorders, o); } /* ------------------------------------------------------------- */ @@ -2068,73 +2110,75 @@ static int tax_per_size[7] = { 0, 6, 12, 18, 24, 30, 36 }; static void expandselling(region * r, request * sellorders, int limit) { - int money, price, j, max_products; - /* int m, n = 0; */ - int maxsize = 0, maxeffsize = 0; - int taxcollected = 0; - int hafencollected = 0; - unit *maxowner = (unit *) NULL; - building *maxb = (building *) NULL; - building *b; - unit *u; - unit *hafenowner; - static int *counter; - static int ncounter = 0; + int money, price, j, max_products; + /* int m, n = 0; */ + int maxsize = 0, maxeffsize = 0; + int taxcollected = 0; + int hafencollected = 0; + unit *maxowner = (unit *)NULL; + building *maxb = (building *)NULL; + building *b; + unit *u; + unit *hafenowner; + static int *counter; + static int ncounter = 0; - if (ncounter == 0) { - const luxury_type *ltype; - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++ncounter; - counter = (int *)gc_add(calloc(sizeof(int), ncounter)); - } else { - memset(counter, 0, sizeof(int) * ncounter); - } - - if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ - return; /* Sümpfen und Wüsten auch so handeln */ - } - /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem - * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - - for (b = rbuildings(r); b; b = b->next) { - if (b->size > maxsize && building_owner(b) != NULL - && b->type == bt_find("castle")) { - maxb = b; - maxsize = b->size; - maxowner = building_owner(b); - } else if (b->size == maxsize && b->type == bt_find("castle")) { - maxb = (building *) NULL; - maxowner = (unit *) NULL; + if (ncounter == 0) { + const luxury_type *ltype; + for (ltype = luxurytypes; ltype; ltype = ltype->next) + ++ncounter; + counter = (int *)gc_add(calloc(sizeof(int), ncounter)); } - } - - hafenowner = owner_buildingtyp(r, bt_find("harbour")); - - if (maxb != (building *) NULL && maxowner != (unit *) NULL) { - maxeffsize = buildingeffsize(maxb, false); - if (maxeffsize == 0) { - maxb = (building *) NULL; - maxowner = (unit *) NULL; + else { + memset(counter, 0, sizeof(int) * ncounter); } - } - /* Die Region muss genug Geld haben, um die Produkte kaufen zu können. */ - money = rmoney(r); + if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ + return; /* Sümpfen und Wüsten auch so handeln */ + } + /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem + * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - /* max_products sind 1/100 der Bevölkerung, falls soviele Produkte - * verkauft werden - counter[] - sinkt die Nachfrage um 1 Punkt. - * multiplier speichert r->demand für die debug message ab. */ + for (b = rbuildings(r); b; b = b->next) { + if (b->size > maxsize && building_owner(b) != NULL + && b->type == bt_find("castle")) { + maxb = b; + maxsize = b->size; + maxowner = building_owner(b); + } + else if (b->size == maxsize && b->type == bt_find("castle")) { + maxb = (building *)NULL; + maxowner = (unit *)NULL; + } + } - max_products = rpeasants(r) / TRADE_FRACTION; - if (max_products <= 0) - return; + hafenowner = owner_buildingtyp(r, bt_find("harbour")); - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) { - max_products = rpeasants(r) * 2 / TRADE_FRACTION; - } - /* Verkauf: so programmiert, dass er leicht auf mehrere Gueter pro - * Runde erweitert werden kann. */ + if (maxb != (building *)NULL && maxowner != (unit *)NULL) { + maxeffsize = buildingeffsize(maxb, false); + if (maxeffsize == 0) { + maxb = (building *)NULL; + maxowner = (unit *)NULL; + } + } + /* Die Region muss genug Geld haben, um die Produkte kaufen zu können. */ + + money = rmoney(r); + + /* max_products sind 1/100 der Bevölkerung, falls soviele Produkte + * verkauft werden - counter[] - sinkt die Nachfrage um 1 Punkt. + * multiplier speichert r->demand für die debug message ab. */ + + max_products = rpeasants(r) / TRADE_FRACTION; + if (max_products <= 0) + return; + + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) { + max_products = rpeasants(r) * 2 / TRADE_FRACTION; + } + /* Verkauf: so programmiert, dass er leicht auf mehrere Gueter pro + * Runde erweitert werden kann. */ expandorders(r, sellorders); if (!norders) @@ -2146,7 +2190,7 @@ static void expandselling(region * r, request * sellorders, int limit) int multi = r_demand(r, ltype); int i; int use = 0; - for (i=0,search=luxurytypes; search!=ltype; search=search->next) { + for (i = 0, search = luxurytypes; search != ltype; search = search->next) { ++i; } if (counter[i] >= limit) @@ -2163,13 +2207,13 @@ static void expandselling(region * r, request * sellorders, int limit) attrib *a = a_find(u->attribs, &at_luxuries); if (a == NULL) a = a_add(&u->attribs, a_new(&at_luxuries)); - itm = (item *) a->data.v; + itm = (item *)a->data.v; i_change(&itm, ltype->itype, 1); a->data.v = itm; ++use; if (u->n < 0) u->n = 0; - + if (hafenowner != NULL) { if (hafenowner->faction != u->faction) { abgezogenhafen = price / 10; @@ -2189,14 +2233,14 @@ static void expandselling(region * r, request * sellorders, int limit) u->n += price; change_money(u, price); fset(u, UFL_LONGACTION | UFL_NOTMOVING); - + /* r->money -= price; --- dies wird eben nicht ausgeführt, denn die * Produkte können auch als Steuern eingetrieben werden. In der Region * wurden Silberstücke gegen Luxusgüter des selben Wertes eingetauscht! * Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt * die Nachfrage für das Produkt um 1. Der Zähler wird wieder auf 0 * gesetzt. */ - + if (++counter[i] > max_products) { int d = r_demand(r, ltype); if (d > 1) { @@ -2204,19 +2248,19 @@ static void expandselling(region * r, request * sellorders, int limit) } counter[i] = 0; } - } + } if (use > 0) { #ifdef NDEBUG use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, use); #else /* int i = */ use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, - use); + use); /* assert(i==use); */ #endif } - } + } free(oa); - + /* Steuern. Hier werden die Steuern dem Besitzer der größten Burg gegeben. */ if (maxowner) { if (taxcollected > 0) { @@ -2233,163 +2277,167 @@ static void expandselling(region * r, request * sellorders, int limit) add_income(hafenowner, IC_TRADETAX, hafencollected, hafencollected); } } - /* Berichte an die Einheiten */ - + /* Berichte an die Einheiten */ + for (u = r->units; u; u = u->next) { - + attrib *a = a_find(u->attribs, &at_luxuries); item *itm; if (a == NULL) continue; - for (itm = (item *) a->data.v; itm; itm = itm->next) { + for (itm = (item *)a->data.v; itm; itm = itm->next) { if (itm->number) { ADDMSG(&u->faction->msgs, msg_message("sellamount", - "unit amount resource", u, itm->number, itm->type->rtype)); + "unit amount resource", u, itm->number, itm->type->rtype)); } } a_remove(&u->attribs, a); add_income(u, IC_TRADE, u->n, u->n); } -} + } static bool sell(unit * u, request ** sellorders, struct order *ord) { - bool unlimited = true; - const item_type *itype; - const luxury_type *ltype = NULL; - int n; - region *r = u->region; - const char *s; + bool unlimited = true; + const item_type *itype; + const luxury_type *ltype = NULL; + int n; + region *r = u->region; + const char *s; - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return false; - } - /* sellorders sind KEIN array, weil für alle items DIE SELBE resource - * (das geld der region) aufgebraucht wird. */ - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - if (findparam(s, u->faction->locale) == P_ANY) { - unlimited = false; - n = rpeasants(r) / TRADE_FRACTION; - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) - n *= 2; - if (n == 0) { - cmistake(u, ord, 303, MSG_COMMERCE); - return false; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return false; } - } else { - n = atoi((const char *)s); - if (n == 0) { - cmistake(u, ord, 27, MSG_COMMERCE); - return false; + /* sellorders sind KEIN array, weil für alle items DIE SELBE resource + * (das geld der region) aufgebraucht wird. */ + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + + if (findparam(s, u->faction->locale) == P_ANY) { + unlimited = false; + n = rpeasants(r) / TRADE_FRACTION; + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) + n *= 2; + if (n == 0) { + cmistake(u, ord, 303, MSG_COMMERCE); + return false; + } } - } - /* Belagerte Einheiten können nichts verkaufen. */ - - if (besieged(u)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); - return false; - } - /* In der Region muß es eine Burg geben. */ - - if (u_race(u) == get_race(RC_INSECT)) { - if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) - && !rbuildings(r)) { - cmistake(u, ord, 119, MSG_COMMERCE); - return false; + else { + n = atoi((const char *)s); + if (n == 0) { + cmistake(u, ord, 27, MSG_COMMERCE); + return false; + } } - } else { - /* ...oder in der Region muß es eine Burg geben. */ - building *b = 0; - if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); - for (b = r->buildings; b; b = b->next) { - if (b->type == bt_castle && b->size >= 2) break; - } - } - if (!b) { - cmistake(u, ord, 119, MSG_COMMERCE); - return false; - } - } + /* Belagerte Einheiten können nichts verkaufen. */ - /* Ein Händler kann nur 10 Güter pro Talentpunkt verkaufen. */ - - n = _min(n, u->number * 10 * eff_skill(u, SK_TRADE, r)); - - if (!n) { - cmistake(u, ord, 54, MSG_COMMERCE); - return false; - } - s = getstrtoken(); - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) - ltype = resource2luxury(itype->rtype); - if (ltype == NULL) { - cmistake(u, ord, 126, MSG_COMMERCE); - return false; - } else { - attrib *a; - request *o; - int k, available; - - if (!r_demand(r, ltype)) { - cmistake(u, ord, 263, MSG_COMMERCE); - return false; + if (besieged(u)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); + return false; } - available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX); + /* In der Region muß es eine Burg geben. */ - /* Wenn andere Einheiten das selbe verkaufen, muß ihr Zeug abgezogen - * werden damit es nicht zweimal verkauft wird: */ - for (o = *sellorders; o; o = o->next) { - if (o->type.ltype == ltype && o->unit->faction == u->faction) { - int fpool = - o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX); - available -= _max(0, fpool); - } + if (u_race(u) == get_race(RC_INSECT)) { + if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) + && !rbuildings(r)) { + cmistake(u, ord, 119, MSG_COMMERCE); + return false; + } + } + else { + /* ...oder in der Region muß es eine Burg geben. */ + building *b = 0; + if (r->buildings) { + const struct building_type *bt_castle = bt_find("castle"); + for (b = r->buildings; b; b = b->next) { + if (b->type == bt_castle && b->size >= 2) break; + } + } + if (!b) { + cmistake(u, ord, 119, MSG_COMMERCE); + return false; + } } - n = _min(n, available); + /* Ein Händler kann nur 10 Güter pro Talentpunkt verkaufen. */ - if (n <= 0) { - cmistake(u, ord, 264, MSG_COMMERCE); - return false; + n = _min(n, u->number * 10 * eff_skill(u, SK_TRADE, r)); + + if (!n) { + cmistake(u, ord, 54, MSG_COMMERCE); + return false; } - /* Hier wird request->type verwendet, weil die obere limit durch - * das silber gegeben wird (region->money), welches für alle - * (!) produkte als summe gilt, als nicht wie bei der - * produktion, wo für jedes produkt einzeln eine obere limite - * existiert, so dass man arrays von orders machen kann. */ - - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ - k = u->number * 10 * eff_skill(u, SK_TRADE, r); - - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ - a = a_find(u->attribs, &at_trades); - if (!a) { - a = a_add(&u->attribs, a_new(&at_trades)); - } else { - k -= a->data.i; + s = getstrtoken(); + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) + ltype = resource2luxury(itype->rtype); + if (ltype == NULL) { + cmistake(u, ord, 126, MSG_COMMERCE); + return false; } + else { + attrib *a; + request *o; + int k, available; - n = _min(n, k); - assert(n >= 0); - /* die Menge der verkauften Güter merken */ - a->data.i += n; - o = (request *) calloc(1, sizeof(request)); - o->unit = u; - o->qty = n; - o->type.ltype = ltype; - addlist(sellorders, o); + if (!r_demand(r, ltype)) { + cmistake(u, ord, 263, MSG_COMMERCE); + return false; + } + available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX); - return unlimited; - } + /* Wenn andere Einheiten das selbe verkaufen, muß ihr Zeug abgezogen + * werden damit es nicht zweimal verkauft wird: */ + for (o = *sellorders; o; o = o->next) { + if (o->type.ltype == ltype && o->unit->faction == u->faction) { + int fpool = + o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX); + available -= _max(0, fpool); + } + } + + n = _min(n, available); + + if (n <= 0) { + cmistake(u, ord, 264, MSG_COMMERCE); + return false; + } + /* Hier wird request->type verwendet, weil die obere limit durch + * das silber gegeben wird (region->money), welches für alle + * (!) produkte als summe gilt, als nicht wie bei der + * produktion, wo für jedes produkt einzeln eine obere limite + * existiert, so dass man arrays von orders machen kann. */ + + /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + k = u->number * 10 * eff_skill(u, SK_TRADE, r); + + /* hat der Händler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften Güter abgezogen werden */ + a = a_find(u->attribs, &at_trades); + if (!a) { + a = a_add(&u->attribs, a_new(&at_trades)); + } + else { + k -= a->data.i; + } + + n = _min(n, k); + assert(n >= 0); + /* die Menge der verkauften Güter merken */ + a->data.i += n; + o = (request *)calloc(1, sizeof(request)); + o->unit = u; + o->qty = n; + o->type.ltype = ltype; + addlist(sellorders, o); + + return unlimited; + } } /* ------------------------------------------------------------- */ @@ -2398,54 +2446,54 @@ static void expandstealing(region * r, request * stealorders) { const resource_type *rsilver = get_resourcetype(R_SILVER); int i; - + assert(rsilver); expandorders(r, stealorders); if (!norders) return; - /* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines - * Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden. - * - * u ist die beklaute unit. oa.unit ist die klauende unit. - */ + /* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines + * Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden. + * + * u ist die beklaute unit. oa.unit ist die klauende unit. + */ - for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) { - unit *u = findunitg(oa[i].no, r); - int n = 0; - if (u && u->region == r) { - n = get_pooled(u, rsilver, GET_ALL, INT_MAX); - } -#ifndef GOBLINKILL - if (oa[i].type.goblin) { /* Goblin-Spezialklau */ - int uct = 0; - unit *u2; - assert(effskill(oa[i].unit, SK_STEALTH) >= 4 - || !"this goblin\'s skill is too low"); - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->faction == u->faction) { - uct += maintenance_cost(u2); + for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) { + unit *u = findunitg(oa[i].no, r); + int n = 0; + if (u && u->region == r) { + n = get_pooled(u, rsilver, GET_ALL, INT_MAX); } - } - n -= uct * 2; +#ifndef GOBLINKILL + if (oa[i].type.goblin) { /* Goblin-Spezialklau */ + int uct = 0; + unit *u2; + assert(effskill(oa[i].unit, SK_STEALTH) >= 4 + || !"this goblin\'s skill is too low"); + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction == u->faction) { + uct += maintenance_cost(u2); } +} + n -= uct * 2; +} #endif - if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { - /* In Questen nur reduziertes Klauen */ - n = 10; - } - if (n > 0) { - n = _min(n, oa[i].unit->wants); - use_pooled(u, rsilver, GET_ALL, n); - oa[i].unit->n = n; - change_money(oa[i].unit, n); - ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", - u, u->region, n)); - } - add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); - fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); + if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { + /* In Questen nur reduziertes Klauen */ + n = 10; + } + if (n > 0) { + n = _min(n, oa[i].unit->wants); + use_pooled(u, rsilver, GET_ALL, n); + oa[i].unit->n = n; + change_money(oa[i].unit, n); + ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", + u, u->region, n)); + } + add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); + fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); } - free(oa); + free(oa); } /* ------------------------------------------------------------- */ @@ -2463,31 +2511,31 @@ static void plant(region * r, unit * u, int raw) cmistake(u, u->thisorder, 108, MSG_PRODUCE); return; } - + /* Skill prüfen */ skill = eff_skill(u, SK_HERBALISM, r); itype = rherbtype(r); if (skill < 6) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 6, itype->rtype, 1)); + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 6, itype->rtype, 1)); return; } /* Wasser des Lebens prüfen */ if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water)); + msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water)); return; } n = get_pooled(u, itype->rtype, GET_DEFAULT, skill * u->number); /* Kräuter prüfen */ if (n == 0) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", - itype->rtype)); + msg_feedback(u, u->thisorder, "resource_missing", "missing", + itype->rtype)); return; } - + n = _min(skill * u->number, n); n = _min(raw, n); /* Für jedes Kraut Talent*10% Erfolgschance. */ @@ -2496,126 +2544,126 @@ static void plant(region * r, unit * u, int raw) planted++; } produceexp(u, SK_HERBALISM, u->number); - + /* Alles ok. Abziehen. */ use_pooled(u, rt_water, GET_DEFAULT, 1); use_pooled(u, itype->rtype, GET_DEFAULT, n); rsetherbs(r, rherbs(r) + planted); ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb", - u, r, planted, itype->rtype)); + u, r, planted, itype->rtype)); } static void planttrees(region * r, unit * u, int raw) { - int n, i, skill, planted = 0; - const resource_type *rtype; + int n, i, skill, planted = 0; + const resource_type *rtype; - if (!fval(r->terrain, LAND_REGION)) { - return; - } + if (!fval(r->terrain, LAND_REGION)) { + return; + } - /* Mallornbäume kann man nur in Mallornregionen züchten */ - rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); + /* Mallornbäume kann man nur in Mallornregionen züchten */ + rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ - skill = eff_skill(u, SK_HERBALISM, r); - if (skill < 6) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 6, rtype, 1)); - return; - } - if (fval(r, RF_MALLORN) && skill < 7) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 7, rtype, 1)); - return; - } + /* Skill prüfen */ + skill = eff_skill(u, SK_HERBALISM, r); + if (skill < 6) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 6, rtype, 1)); + return; + } + if (fval(r, RF_MALLORN) && skill < 7) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 7, rtype, 1)); + return; + } - /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ - raw = _min(raw, skill * u->number); - n = get_pooled(u, rtype, GET_DEFAULT, raw); - if (n == 0) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); - return; - } - n = _min(raw, n); + /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ + raw = _min(raw, skill * u->number); + n = get_pooled(u, rtype, GET_DEFAULT, raw); + if (n == 0) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); + return; + } + n = _min(raw, n); - /* Für jeden Samen Talent*10% Erfolgschance. */ - for (i = n; i > 0; i--) { - if (rng_int() % 10 < skill) - planted++; - } - rsettrees(r, 0, rtrees(r, 0) + planted); + /* Für jeden Samen Talent*10% Erfolgschance. */ + for (i = n; i > 0; i--) { + if (rng_int() % 10 < skill) + planted++; + } + rsettrees(r, 0, rtrees(r, 0) + planted); - /* Alles ok. Abziehen. */ - produceexp(u, SK_HERBALISM, u->number); - use_pooled(u, rtype, GET_DEFAULT, n); + /* Alles ok. Abziehen. */ + produceexp(u, SK_HERBALISM, u->number); + use_pooled(u, rtype, GET_DEFAULT, n); - ADDMSG(&u->faction->msgs, msg_message("plant", - "unit region amount herb", u, r, planted, rtype)); + ADDMSG(&u->faction->msgs, msg_message("plant", + "unit region amount herb", u, r, planted, rtype)); } /* züchte bäume */ static void breedtrees(region * r, unit * u, int raw) { - int n, i, skill, planted = 0; - const resource_type *rtype; - static int gamecookie = -1; - static int current_season; + int n, i, skill, planted = 0; + const resource_type *rtype; + static int gamecookie = -1; + static int current_season; - if (gamecookie != global.cookie) { - gamedate date; - get_gamedate(turn, &date); - current_season = date.season; - gamecookie = global.cookie; - } + if (gamecookie != global.cookie) { + gamedate date; + get_gamedate(turn, &date); + current_season = date.season; + gamecookie = global.cookie; + } - /* Bäume züchten geht nur im Frühling */ - if (current_season != SEASON_SPRING) { - planttrees(r, u, raw); - return; - } + /* Bäume züchten geht nur im Frühling */ + if (current_season != SEASON_SPRING) { + planttrees(r, u, raw); + return; + } - if (!fval(r->terrain, LAND_REGION)) { - return; - } + if (!fval(r->terrain, LAND_REGION)) { + return; + } - /* Mallornbäume kann man nur in Mallornregionen züchten */ - rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); + /* Mallornbäume kann man nur in Mallornregionen züchten */ + rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ - skill = eff_skill(u, SK_HERBALISM, r); - if (skill < 12) { - planttrees(r, u, raw); - return; - } + /* Skill prüfen */ + skill = eff_skill(u, SK_HERBALISM, r); + if (skill < 12) { + planttrees(r, u, raw); + return; + } - /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ - raw = _min(skill * u->number, raw); - n = get_pooled(u, rtype, GET_DEFAULT, raw); - /* Samen prüfen */ - if (n == 0) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); - return; - } - n = _min(raw, n); + /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ + raw = _min(skill * u->number, raw); + n = get_pooled(u, rtype, GET_DEFAULT, raw); + /* Samen prüfen */ + if (n == 0) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); + return; + } + n = _min(raw, n); - /* Für jeden Samen Talent*5% Erfolgschance. */ - for (i = n; i > 0; i--) { - if (rng_int() % 100 < skill * 5) - planted++; - } - rsettrees(r, 1, rtrees(r, 1) + planted); + /* Für jeden Samen Talent*5% Erfolgschance. */ + for (i = n; i > 0; i--) { + if (rng_int() % 100 < skill * 5) + planted++; + } + rsettrees(r, 1, rtrees(r, 1) + planted); - /* Alles ok. Abziehen. */ - produceexp(u, SK_HERBALISM, u->number); - use_pooled(u, rtype, GET_DEFAULT, n); + /* Alles ok. Abziehen. */ + produceexp(u, SK_HERBALISM, u->number); + use_pooled(u, rtype, GET_DEFAULT, n); - ADDMSG(&u->faction->msgs, msg_message("plant", - "unit region amount herb", u, r, planted, rtype)); + ADDMSG(&u->faction->msgs, msg_message("plant", + "unit region amount herb", u, r, planted, rtype)); } /* züchte pferde */ @@ -2653,124 +2701,132 @@ static void breedhorses(region * r, unit * u) static void breed_cmd(unit * u, struct order *ord) { - int m; - const char *s; - param_t p; - region *r = u->region; - const resource_type *rtype = NULL; + int m; + const char *s; + param_t p; + region *r = u->region; + const resource_type *rtype = NULL; - if (r->land == NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", "")); - return; - } + if (r->land == NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", "")); + return; + } - /* züchte [] */ - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - m = atoi((const char *)s); - if (m != 0) { - /* first came a want-paramter */ + /* züchte [] */ + init_tokens(ord); + skip_token(); s = getstrtoken(); - } else { - m = INT_MAX; - } - if (!s[0]) { - p = P_ANY; - } else { - p = findparam(s, u->faction->locale); - } + m = atoi((const char *)s); + if (m != 0) { + /* first came a want-paramter */ + s = getstrtoken(); + } + else { + m = INT_MAX; + } - switch (p) { - case P_HERBS: - plant(r, u, m); - break; - case P_TREES: - breedtrees(r, u, m); - break; - default: - if (p != P_ANY) { - rtype = findresourcetype(s, u->faction->locale); - if (rtype == get_resourcetype(R_SEED) || rtype == get_resourcetype(R_MALLORNSEED)) { + if (!s[0]) { + p = P_ANY; + } + else { + p = findparam(s, u->faction->locale); + } + + switch (p) { + case P_HERBS: + plant(r, u, m); + break; + case P_TREES: breedtrees(r, u, m); break; - } else if (rtype != get_resourcetype(R_HORSE)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + default: + if (p != P_ANY) { + rtype = findresourcetype(s, u->faction->locale); + if (rtype == get_resourcetype(R_SEED) || rtype == get_resourcetype(R_MALLORNSEED)) { + breedtrees(r, u, m); + break; + } + else if (rtype != get_resourcetype(R_HORSE)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + break; + } + } + breedhorses(r, u); break; - } } - breedhorses(r, u); - break; - } } static const char *rough_amount(int a, int m) { - int p = (a * 100) / m; + int p = (a * 100) / m; - if (p < 10) { - return "sehr wenige"; - } else if (p < 30) { - return "wenige"; - } else if (p < 60) { - return "relativ viele"; - } else if (p < 90) { - return "viele"; - } - return "sehr viele"; + if (p < 10) { + return "sehr wenige"; + } + else if (p < 30) { + return "wenige"; + } + else if (p < 60) { + return "relativ viele"; + } + else if (p < 90) { + return "viele"; + } + return "sehr viele"; } static void research_cmd(unit * u, struct order *ord) { - region *r = u->region; + region *r = u->region; - init_tokens(ord); - skip_token(); - /* - const char *s = getstrtoken(); + init_tokens(ord); + skip_token(); + /* + const char *s = getstrtoken(); - if (findparam(s, u->faction->locale) == P_HERBS) { */ + if (findparam(s, u->faction->locale) == P_HERBS) { */ - if (eff_skill(u, SK_HERBALISM, r) < 7) { - cmistake(u, ord, 227, MSG_EVENT); - return; - } - - produceexp(u, SK_HERBALISM, u->number); - - if (rherbs(r) > 0) { - const item_type *itype = rherbtype(r); - - if (itype != NULL) { - ADDMSG(&u->faction->msgs, msg_message("researchherb", - "unit region amount herb", - u, r, rough_amount(rherbs(r), 100), itype->rtype)); - } else { - ADDMSG(&u->faction->msgs, msg_message("researchherb_none", - "unit region", u, r)); + if (eff_skill(u, SK_HERBALISM, r) < 7) { + cmistake(u, ord, 227, MSG_EVENT); + return; + } + + produceexp(u, SK_HERBALISM, u->number); + + if (rherbs(r) > 0) { + const item_type *itype = rherbtype(r); + + if (itype != NULL) { + ADDMSG(&u->faction->msgs, msg_message("researchherb", + "unit region amount herb", + u, r, rough_amount(rherbs(r), 100), itype->rtype)); + } + else { + ADDMSG(&u->faction->msgs, msg_message("researchherb_none", + "unit region", u, r)); + } + } + else { + ADDMSG(&u->faction->msgs, msg_message("researchherb_none", + "unit region", u, r)); } - } else { - ADDMSG(&u->faction->msgs, msg_message("researchherb_none", - "unit region", u, r)); - } } static int max_skill(region * r, faction * f, skill_t sk) { - unit *u; - int w = 0; + unit *u; + int w = 0; - for (u = r->units; u; u = u->next) { - if (u->faction == f) { - if (eff_skill(u, sk, r) > w) { - w = eff_skill(u, sk, r); - } + for (u = r->units; u; u = u->next) { + if (u->faction == f) { + if (eff_skill(u, sk, r) > w) { + w = eff_skill(u, sk, r); + } + } } - } - return w; + return w; } message * check_steal(const unit * u, struct order *ord) { @@ -2793,589 +2849,596 @@ message * check_steal(const unit * u, struct order *ord) { static void steal_cmd(unit * u, struct order *ord, request ** stealorders) { - const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); - int n, i, id; - bool goblin = false; - request *o; - unit *u2 = NULL; - region *r = u->region; - faction *f = NULL; - message * msg; + const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); + int n, i, id; + bool goblin = false; + request *o; + unit *u2 = NULL; + region *r = u->region; + faction *f = NULL; + message * msg; - assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); + assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); - msg = check_steal(u, ord); - if (msg) { - ADDMSG(&u->faction->msgs, msg); - return; - } - init_tokens(ord); - skip_token(); - id = read_unitid(u->faction, r); - u2 = findunitr(r, id); - - if (u2 && u2->region == u->region) { - f = u2->faction; - } else { - f = dfindhash(id); - } - - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->faction == f && cansee(u->faction, r, u2, 0)) - break; - } - - if (!u2) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - if (IsImmune(u2->faction)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity())); - return; - } - - if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) { - cmistake(u, ord, 47, MSG_INCOME); - return; - } - - assert(u->region == u2->region); - if (!can_contact(r, u, u2)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); - return; - } - - n = eff_skill(u, SK_STEALTH, r) - max_skill(r, f, SK_PERCEPTION); - - if (n <= 0) { - /* Wahrnehmung == Tarnung */ - if (u_race(u) != get_race(RC_GOBLIN) || eff_skill(u, SK_STEALTH, r) <= 3) { - ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2)); - if (n == 0) { - ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2)); - } else { - ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", - u, u2)); - } - return; - } else { - ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u, - u2)); - ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u, - u2)); - n = 1; - goblin = true; + msg = check_steal(u, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; } - } + init_tokens(ord); + skip_token(); + id = read_unitid(u->faction, r); + u2 = findunitr(r, id); - i = _min(u->number, i_get(u->items, rring->itype)); - if (i > 0) { - n *= STEALINCOME * (u->number + i * (roqf_factor() - 1)); - } else { - n *= u->number * STEALINCOME; - } + if (u2 && u2->region == u->region) { + f = u2->faction; + } + else { + f = dfindhash(id); + } - u->wants = n; + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction == f && cansee(u->faction, r, u2, 0)) + break; + } - /* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein - * guter dieb sein, schliesslich macht man immer noch sehr viel laerm */ + if (!u2) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } - o = (request *) calloc(1, sizeof(request)); - o->unit = u; - o->qty = 1; /* Betrag steht in u->wants */ - o->no = u2->no; - o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */ - addlist(stealorders, o); + if (IsImmune(u2->faction)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity())); + return; + } - /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ + if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) { + cmistake(u, ord, 47, MSG_INCOME); + return; + } - produceexp(u, SK_STEALTH, _min(n, u->number)); + assert(u->region == u2->region); + if (!can_contact(r, u, u2)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); + return; + } + + n = eff_skill(u, SK_STEALTH, r) - max_skill(r, f, SK_PERCEPTION); + + if (n <= 0) { + /* Wahrnehmung == Tarnung */ + if (u_race(u) != get_race(RC_GOBLIN) || eff_skill(u, SK_STEALTH, r) <= 3) { + ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2)); + if (n == 0) { + ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2)); + } + else { + ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", + u, u2)); + } + return; + } + else { + ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u, + u2)); + ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u, + u2)); + n = 1; + goblin = true; + } + } + + i = _min(u->number, i_get(u->items, rring->itype)); + if (i > 0) { + n *= STEALINCOME * (u->number + i * (roqf_factor() - 1)); + } + else { + n *= u->number * STEALINCOME; + } + + u->wants = n; + + /* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein + * guter dieb sein, schliesslich macht man immer noch sehr viel laerm */ + + o = (request *)calloc(1, sizeof(request)); + o->unit = u; + o->qty = 1; /* Betrag steht in u->wants */ + o->no = u2->no; + o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */ + addlist(stealorders, o); + + /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ + + produceexp(u, SK_STEALTH, _min(n, u->number)); } /* ------------------------------------------------------------- */ static void expandentertainment(region * r) { - unit *u; - int m = entertainmoney(r); - request *o; + unit *u; + int m = entertainmoney(r); + request *o; - for (o = &entertainers[0]; o != nextentertainer; ++o) { - double part = m / (double)entertaining; - u = o->unit; - if (entertaining <= m) - u->n = o->qty; - else - u->n = (int)(o->qty * part); - change_money(u, u->n); - rsetmoney(r, rmoney(r) - u->n); - m -= u->n; - entertaining -= o->qty; + for (o = &entertainers[0]; o != nextentertainer; ++o) { + double part = m / (double)entertaining; + u = o->unit; + if (entertaining <= m) + u->n = o->qty; + else + u->n = (int)(o->qty * part); + change_money(u, u->n); + rsetmoney(r, rmoney(r) - u->n); + m -= u->n; + entertaining -= o->qty; - /* Nur soviel PRODUCEEXP wie auch tatsächlich gemacht wurde */ - produceexp(u, SK_ENTERTAINMENT, _min(u->n, u->number)); - add_income(u, IC_ENTERTAIN, o->qty, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + /* Nur soviel PRODUCEEXP wie auch tatsächlich gemacht wurde */ + produceexp(u, SK_ENTERTAINMENT, _min(u->n, u->number)); + add_income(u, IC_ENTERTAIN, o->qty, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } } void entertain_cmd(unit * u, struct order *ord) { - region *r = u->region; - int max_e; - request *o; - static int entertainbase = 0; - static int entertainperlevel = 0; + region *r = u->region; + int max_e; + request *o; + static int entertainbase = 0; + static int entertainperlevel = 0; - if (!entertainbase) { - const char *str = get_param(global.parameters, "entertain.base"); - entertainbase = str ? atoi(str) : 0; - } - if (!entertainperlevel) { - const char *str = get_param(global.parameters, "entertain.perlevel"); - entertainperlevel = str ? atoi(str) : 0; - } - if (fval(u, UFL_WERE)) { - cmistake(u, ord, 58, MSG_INCOME); - return; - } - if (!effskill(u, SK_ENTERTAINMENT)) { - cmistake(u, ord, 58, MSG_INCOME); - return; - } - if (besieged(u)) { - cmistake(u, ord, 60, MSG_INCOME); - return; - } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - if (is_cursed(r->attribs, C_DEPRESSION, 0)) { - cmistake(u, ord, 28, MSG_INCOME); - return; - } + if (!entertainbase) { + const char *str = get_param(global.parameters, "entertain.base"); + entertainbase = str ? atoi(str) : 0; + } + if (!entertainperlevel) { + const char *str = get_param(global.parameters, "entertain.perlevel"); + entertainperlevel = str ? atoi(str) : 0; + } + if (fval(u, UFL_WERE)) { + cmistake(u, ord, 58, MSG_INCOME); + return; + } + if (!effskill(u, SK_ENTERTAINMENT)) { + cmistake(u, ord, 58, MSG_INCOME); + return; + } + if (besieged(u)) { + cmistake(u, ord, 60, MSG_INCOME); + return; + } + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; + } + if (is_cursed(r->attribs, C_DEPRESSION, 0)) { + cmistake(u, ord, 28, MSG_INCOME); + return; + } - u->wants = u->number * (entertainbase + effskill(u, SK_ENTERTAINMENT) - * entertainperlevel); + u->wants = u->number * (entertainbase + effskill(u, SK_ENTERTAINMENT) + * entertainperlevel); - init_tokens(ord); - skip_token(); - max_e = getuint(); - if (max_e != 0) { - u->wants = _min(u->wants, max_e); - } - o = nextentertainer++; - o->unit = u; - o->qty = u->wants; - entertaining += o->qty; + init_tokens(ord); + skip_token(); + max_e = getuint(); + if (max_e != 0) { + u->wants = _min(u->wants, max_e); + } + o = nextentertainer++; + o->unit = u; + o->qty = u->wants; + entertaining += o->qty; } /** - * \return number of working spaces taken by players + * \return number of working spaces taken by players */ static void expandwork(region * r, request * work_begin, request * work_end, int maxwork) { - int earnings; - /* n: verbleibende Einnahmen */ - /* fishes: maximale Arbeiter */ - int jobs = maxwork; - int p_wage = wage(r, NULL, NULL, turn); - int money = rmoney(r); - request *o; + int earnings; + /* n: verbleibende Einnahmen */ + /* fishes: maximale Arbeiter */ + int jobs = maxwork; + int p_wage = wage(r, NULL, NULL, turn); + int money = rmoney(r); + request *o; - for (o = work_begin; o != work_end; ++o) { - unit *u = o->unit; - int workers; + for (o = work_begin; o != work_end; ++o) { + unit *u = o->unit; + int workers; - if (u->number == 0) - continue; + if (u->number == 0) + continue; - if (jobs >= working) - workers = u->number; - else { - workers = u->number * jobs / working; - if (rng_int() % working < (u->number * jobs) % working) - workers++; + if (jobs >= working) + workers = u->number; + else { + workers = u->number * jobs / working; + if (rng_int() % working < (u->number * jobs) % working) + workers++; + } + + assert(workers >= 0); + + u->n = workers * wage(u->region, u->faction, u_race(u), turn); + + jobs -= workers; + assert(jobs >= 0); + + change_money(u, u->n); + working -= o->unit->number; + add_income(u, IC_WORK, o->qty, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); } - assert(workers >= 0); - - u->n = workers * wage(u->region, u->faction, u_race(u), turn); - - jobs -= workers; - assert(jobs >= 0); - - change_money(u, u->n); - working -= o->unit->number; - add_income(u, IC_WORK, o->qty, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } - - if (jobs > rpeasants(r)) { - jobs = rpeasants(r); - } - earnings = jobs * p_wage; - if (rule_blessed_harvest() == HARVEST_TAXES) { - /* E3 rules */ - static const curse_type *blessedharvest_ct; - if (!blessedharvest_ct) { - blessedharvest_ct = ct_find("blessedharvest"); + if (jobs > rpeasants(r)) { + jobs = rpeasants(r); } - if (blessedharvest_ct && r->attribs) { - int happy = - (int)curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); - happy = _min(happy, jobs); - earnings += happy; + earnings = jobs * p_wage; + if (rule_blessed_harvest() == HARVEST_TAXES) { + /* E3 rules */ + static const curse_type *blessedharvest_ct; + if (!blessedharvest_ct) { + blessedharvest_ct = ct_find("blessedharvest"); + } + if (blessedharvest_ct && r->attribs) { + int happy = + (int)curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); + happy = _min(happy, jobs); + earnings += happy; + } } - } - rsetmoney(r, money + earnings); + rsetmoney(r, money + earnings); } static int do_work(unit * u, order * ord, request * o) { - if (playerrace(u_race(u))) { - region *r = u->region; - int w; + if (playerrace(u_race(u))) { + region *r = u->region; + int w; - if (fval(u, UFL_WERE)) { - if (ord) - cmistake(u, ord, 313, MSG_INCOME); - return -1; + if (fval(u, UFL_WERE)) { + if (ord) + cmistake(u, ord, 313, MSG_INCOME); + return -1; + } + if (besieged(u)) { + if (ord) + cmistake(u, ord, 60, MSG_INCOME); + return -1; + } + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + if (ord) + cmistake(u, ord, 69, MSG_INCOME); + return -1; + } + w = wage(r, u->faction, u_race(u), turn); + u->wants = u->number * w; + o->unit = u; + o->qty = u->number * w; + working += u->number; + return 0; } - if (besieged(u)) { - if (ord) - cmistake(u, ord, 60, MSG_INCOME); - return -1; + else if (ord && !is_monsters(u->faction)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_cantwork", "race", u_race(u))); } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - if (ord) - cmistake(u, ord, 69, MSG_INCOME); - return -1; - } - w = wage(r, u->faction, u_race(u), turn); - u->wants = u->number * w; - o->unit = u; - o->qty = u->number * w; - working += u->number; - return 0; - } else if (ord && !is_monsters(u->faction)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_cantwork", "race", u_race(u))); - } - return -1; + return -1; } static void expandtax(region * r, request * taxorders) { - unit *u; - int i; + unit *u; + int i; - expandorders(r, taxorders); - if (!norders) - return; + expandorders(r, taxorders); + if (!norders) + return; - for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { - change_money(oa[i].unit, TAXFRACTION); - oa[i].unit->n += TAXFRACTION; - rsetmoney(r, rmoney(r) - TAXFRACTION); - } - free(oa); - - for (u = r->units; u; u = u->next) { - if (u->n >= 0) { - add_income(u, IC_TAX, u->wants, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); + for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { + change_money(oa[i].unit, TAXFRACTION); + oa[i].unit->n += TAXFRACTION; + rsetmoney(r, rmoney(r) - TAXFRACTION); + } + free(oa); + + for (u = r->units; u; u = u->next) { + if (u->n >= 0) { + add_income(u, IC_TAX, u->wants, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } } - } } void tax_cmd(unit * u, struct order *ord, request ** taxorders) { - /* Steuern werden noch vor der Forschung eingetrieben */ - region *r = u->region; - unit *u2; - int n; - request *o; - int max; + /* Steuern werden noch vor der Forschung eingetrieben */ + region *r = u->region; + unit *u2; + int n; + request *o; + int max; - if (!humanoidrace(u_race(u)) && !is_monsters(u->faction)) { - cmistake(u, ord, 228, MSG_INCOME); + if (!humanoidrace(u_race(u)) && !is_monsters(u->faction)) { + cmistake(u, ord, 228, MSG_INCOME); + return; + } + + if (fval(u, UFL_WERE)) { + cmistake(u, ord, 228, MSG_INCOME); + return; + } + + if (besieged(u)) { + cmistake(u, ord, 60, MSG_INCOME); + return; + } + n = armedmen(u, false); + + if (!n) { + cmistake(u, ord, 48, MSG_INCOME); + return; + } + + init_tokens(ord); + skip_token(); + max = getuint(); + + if (max == 0) + max = INT_MAX; + if (!playerrace(u_race(u))) { + u->wants = _min(income(u), max); + } + else { + u->wants = _min(n * eff_skill(u, SK_TAXING, r) * 20, max); + } + + u2 = is_guarded(r, u, GUARD_TAX); + if (u2) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "region_guarded", "guard", u2)); + return; + } + + /* die einnahmen werden in fraktionen von 10 silber eingeteilt: diese + * fraktionen werden dann bei eintreiben unter allen eintreibenden + * einheiten aufgeteilt. */ + + o = (request *)calloc(1, sizeof(request)); + o->qty = u->wants / TAXFRACTION; + o->unit = u; + addlist(taxorders, o); return; - } - - if (fval(u, UFL_WERE)) { - cmistake(u, ord, 228, MSG_INCOME); - return; - } - - if (besieged(u)) { - cmistake(u, ord, 60, MSG_INCOME); - return; - } - n = armedmen(u, false); - - if (!n) { - cmistake(u, ord, 48, MSG_INCOME); - return; - } - - init_tokens(ord); - skip_token(); - max = getuint(); - - if (max == 0) - max = INT_MAX; - if (!playerrace(u_race(u))) { - u->wants = _min(income(u), max); - } else { - u->wants = _min(n * eff_skill(u, SK_TAXING, r) * 20, max); - } - - u2 = is_guarded(r, u, GUARD_TAX); - if (u2) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "region_guarded", "guard", u2)); - return; - } - - /* die einnahmen werden in fraktionen von 10 silber eingeteilt: diese - * fraktionen werden dann bei eintreiben unter allen eintreibenden - * einheiten aufgeteilt. */ - - o = (request *) calloc(1, sizeof(request)); - o->qty = u->wants / TAXFRACTION; - o->unit = u; - addlist(taxorders, o); - return; } #define MAX_WORKERS 2048 void auto_work(region * r) { - request workers[MAX_WORKERS]; - request *nextworker = workers; - unit *u; + request workers[MAX_WORKERS]; + request *nextworker = workers; + unit *u; - for (u = r->units; u; u = u->next) { - if (!(u->flags & UFL_LONGACTION) && !is_monsters(u->faction)) { - if (do_work(u, NULL, nextworker) == 0) { - assert(nextworker - workers < MAX_WORKERS); - ++nextworker; - } + for (u = r->units; u; u = u->next) { + if (!(u->flags & UFL_LONGACTION) && !is_monsters(u->faction)) { + if (do_work(u, NULL, nextworker) == 0) { + assert(nextworker - workers < MAX_WORKERS); + ++nextworker; + } + } + } + if (nextworker != workers) { + expandwork(r, workers, nextworker, maxworkingpeasants(r)); } - } - if (nextworker != workers) { - expandwork(r, workers, nextworker, maxworkingpeasants(r)); - } } static void peasant_taxes(region * r) { - faction *f; - unit *u; - building *b; - int money; - int maxsize; + faction *f; + unit *u; + building *b; + int money; + int maxsize; - f = region_get_owner(r); - if (f == NULL || is_mourning(r, turn)) { - return; - } - money = rmoney(r); - if (money <= 0) - return; - - b = largestbuilding(r, cmp_taxes, false); - if (b == NULL) - return; - - u = building_owner(b); - if (u == NULL || u->faction != f) - return; - - maxsize = buildingeffsize(b, false); - if (maxsize > 0) { - double taxfactor = money * b->type->taxes(b, maxsize); - double morale = money * region_get_morale(r) * MORALE_TAX_FACTOR; - if (taxfactor > morale) - taxfactor = morale; - if (taxfactor > 0) { - int taxmoney = (int)taxfactor; - change_money(u, taxmoney); - rsetmoney(r, money - taxmoney); - ADDMSG(&u->faction->msgs, msg_message("income_tax", - "unit region amount", u, r, taxmoney)); + f = region_get_owner(r); + if (f == NULL || is_mourning(r, turn)) { + return; + } + money = rmoney(r); + if (money <= 0) + return; + + b = largestbuilding(r, cmp_taxes, false); + if (b == NULL) + return; + + u = building_owner(b); + if (u == NULL || u->faction != f) + return; + + maxsize = buildingeffsize(b, false); + if (maxsize > 0) { + double taxfactor = money * b->type->taxes(b, maxsize); + double morale = money * region_get_morale(r) * MORALE_TAX_FACTOR; + if (taxfactor > morale) + taxfactor = morale; + if (taxfactor > 0) { + int taxmoney = (int)taxfactor; + change_money(u, taxmoney); + rsetmoney(r, money - taxmoney); + ADDMSG(&u->faction->msgs, msg_message("income_tax", + "unit region amount", u, r, taxmoney)); + } } - } } void produce(struct region *r) { - request workers[MAX_WORKERS]; - request *taxorders, *sellorders, *stealorders, *buyorders; - unit *u; - int todo; - static int rule_autowork = -1; - bool limited = true; - request *nextworker = workers; - assert(r); + request workers[MAX_WORKERS]; + request *taxorders, *sellorders, *stealorders, *buyorders; + unit *u; + int todo; + static int rule_autowork = -1; + bool limited = true; + request *nextworker = workers; + assert(r); - /* das sind alles befehle, die 30 tage brauchen, und die in thisorder - * stehen! von allen 30-tage befehlen wird einfach der letzte verwendet - * (dosetdefaults). - * - * kaufen vor einnahmequellen. da man in einer region dasselbe produkt - * nicht kaufen und verkaufen kann, ist die reihenfolge wegen der - * produkte egal. nicht so wegen dem geld. - * - * lehren vor lernen. */ + /* das sind alles befehle, die 30 tage brauchen, und die in thisorder + * stehen! von allen 30-tage befehlen wird einfach der letzte verwendet + * (dosetdefaults). + * + * kaufen vor einnahmequellen. da man in einer region dasselbe produkt + * nicht kaufen und verkaufen kann, ist die reihenfolge wegen der + * produkte egal. nicht so wegen dem geld. + * + * lehren vor lernen. */ - if (rule_autowork < 0) { - rule_autowork = get_param_int(global.parameters, "work.auto", 0); - } - - assert(rmoney(r) >= 0); - assert(rpeasants(r) >= 0); - - if (r->land && rule_auto_taxation()) { - /* new taxation rules, region owners make money based on morale and building */ - peasant_taxes(r); - } - - buyorders = 0; - sellorders = 0; - working = 0; - nextentertainer = &entertainers[0]; - entertaining = 0; - taxorders = 0; - stealorders = 0; - - for (u = r->units; u; u = u->next) { - order *ord; - bool trader = false; - - if (u_race(u) == get_race(RC_SPELL) || fval(u, UFL_LONGACTION)) - continue; - - if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - continue; - - if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { - /* this message was already given in laws.setdefaults - cmistake(u, u->thisorder, 52, MSG_PRODUCE); - */ - continue; + if (rule_autowork < 0) { + rule_autowork = get_param_int(global.parameters, "work.auto", 0); } - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_BUY) { - buy(u, &buyorders, ord); - trader = true; - } else if (kwd == K_SELL) { - /* sell returns true if the sale is not limited - * by the region limit */ - limited &= !sell(u, &sellorders, ord); - trader = true; - } - } - if (trader) { - attrib *a = a_find(u->attribs, &at_trades); - if (a && a->data.i) { - produceexp(u, SK_TRADE, u->number); - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - continue; + assert(rmoney(r) >= 0); + assert(rpeasants(r) >= 0); + + if (r->land && rule_auto_taxation()) { + /* new taxation rules, region owners make money based on morale and building */ + peasant_taxes(r); } - todo = getkeyword(u->thisorder); - if (todo == NOKEYWORD) - continue; + buyorders = 0; + sellorders = 0; + working = 0; + nextentertainer = &entertainers[0]; + entertaining = 0; + taxorders = 0; + stealorders = 0; - if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN) - && !(u_race(u)->flags & RCF_SWIM) - && todo != K_STEAL && todo != K_SPY && todo != K_SABOTAGE) - continue; + for (u = r->units; u; u = u->next) { + order *ord; + bool trader = false; - switch (todo) { + if (u_race(u) == get_race(RC_SPELL) || fval(u, UFL_LONGACTION)) + continue; - case K_ENTERTAIN: - entertain_cmd(u, u->thisorder); - break; + if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && + !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + continue; - case K_WORK: - if (!rule_autowork && do_work(u, u->thisorder, nextworker) == 0) { - assert(nextworker - workers < MAX_WORKERS); - ++nextworker; - } - break; + if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { + /* this message was already given in laws.setdefaults + cmistake(u, u->thisorder, 52, MSG_PRODUCE); + */ + continue; + } - case K_TAX: - tax_cmd(u, u->thisorder, &taxorders); - break; + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_BUY) { + buy(u, &buyorders, ord); + trader = true; + } + else if (kwd == K_SELL) { + /* sell returns true if the sale is not limited + * by the region limit */ + limited &= !sell(u, &sellorders, ord); + trader = true; + } + } + if (trader) { + attrib *a = a_find(u->attribs, &at_trades); + if (a && a->data.i) { + produceexp(u, SK_TRADE, u->number); + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + continue; + } - case K_STEAL: - steal_cmd(u, u->thisorder, &stealorders); - break; + todo = getkeyword(u->thisorder); + if (todo == NOKEYWORD) + continue; - case K_SPY: - spy_cmd(u, u->thisorder); - break; + if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN) + && !(u_race(u)->flags & RCF_SWIM) + && todo != K_STEAL && todo != K_SPY && todo != K_SABOTAGE) + continue; - case K_SABOTAGE: - sabotage_cmd(u, u->thisorder); - break; + switch (todo) { - case K_PLANT: - case K_BREED: - breed_cmd(u, u->thisorder); - break; + case K_ENTERTAIN: + entertain_cmd(u, u->thisorder); + break; - case K_RESEARCH: - research_cmd(u, u->thisorder); - break; + case K_WORK: + if (!rule_autowork && do_work(u, u->thisorder, nextworker) == 0) { + assert(nextworker - workers < MAX_WORKERS); + ++nextworker; + } + break; + + case K_TAX: + tax_cmd(u, u->thisorder, &taxorders); + break; + + case K_STEAL: + steal_cmd(u, u->thisorder, &stealorders); + break; + + case K_SPY: + spy_cmd(u, u->thisorder); + break; + + case K_SABOTAGE: + sabotage_cmd(u, u->thisorder); + break; + + case K_PLANT: + case K_BREED: + breed_cmd(u, u->thisorder); + break; + + case K_RESEARCH: + research_cmd(u, u->thisorder); + break; + } } - } - /* Entertainment (expandentertainment) und Besteuerung (expandtax) vor den - * Befehlen, die den Bauern mehr Geld geben, damit man aus den Zahlen der - * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung - * auszugeben bereit sind. */ - if (entertaining) - expandentertainment(r); - if (!rule_autowork) { - expandwork(r, workers, nextworker, maxworkingpeasants(r)); - } - if (taxorders) - expandtax(r, taxorders); + /* Entertainment (expandentertainment) und Besteuerung (expandtax) vor den + * Befehlen, die den Bauern mehr Geld geben, damit man aus den Zahlen der + * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung + * auszugeben bereit sind. */ + if (entertaining) + expandentertainment(r); + if (!rule_autowork) { + expandwork(r, workers, nextworker, maxworkingpeasants(r)); + } + if (taxorders) + expandtax(r, taxorders); - /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um - * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu - * können. */ + /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um + * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu + * können. */ - if (buyorders) - expandbuying(r, buyorders); + if (buyorders) + expandbuying(r, buyorders); - if (sellorders) { - int limit = rpeasants(r) / TRADE_FRACTION; - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) - limit *= 2; - expandselling(r, sellorders, limited ? limit : INT_MAX); - } + if (sellorders) { + int limit = rpeasants(r) / TRADE_FRACTION; + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) + limit *= 2; + expandselling(r, sellorders, limited ? limit : INT_MAX); + } - /* Die Spieler sollen alles Geld verdienen, bevor sie beklaut werden - * (expandstealing). */ + /* Die Spieler sollen alles Geld verdienen, bevor sie beklaut werden + * (expandstealing). */ - if (stealorders) - expandstealing(r, stealorders); + if (stealorders) + expandstealing(r, stealorders); - assert(rmoney(r) >= 0); - assert(rpeasants(r) >= 0); + assert(rmoney(r) >= 0); + assert(rpeasants(r) >= 0); } diff --git a/src/give.c b/src/give.c index e03241bbb..56e113c2d 100644 --- a/src/give.c +++ b/src/give.c @@ -2,11 +2,11 @@ +-------------------+ Christian Schlittchen | | Enno Rehling | Eressea PBEM host | Katja Zedel - | (c) 1998 - 2003 | Henning Peters + | (c) 1998 - 2014 | Henning Peters | | Ingo Wilken +-------------------+ Stefan Reich - This program may not be used, modified or distributed + This program may not be used, modified or distributed without prior permission by the authors of Eressea. */ @@ -53,379 +53,408 @@ static int GiveRestriction(void) { - static int value = -1; - if (value < 0) { - const char *str = get_param(global.parameters, "GiveRestriction"); - value = str ? atoi(str) : 0; - } - return value; + static int value = -1; + if (value < 0) { + const char *str = get_param(global.parameters, "GiveRestriction"); + value = str ? atoi(str) : 0; + } + return value; } static void add_give(unit * u, unit * u2, int given, int received, - const resource_type * rtype, struct order *ord, int error) +const resource_type * rtype, struct order *ord, int error) { - if (error) { - cmistake(u, ord, error, MSG_COMMERCE); - } else if (u2 == NULL) { - ADDMSG(&u->faction->msgs, - msg_message("give_peasants", "unit resource amount", u, rtype, given)); - } else if (u2->faction != u->faction) { - message *msg; + if (error) { + cmistake(u, ord, error, MSG_COMMERCE); + } + else if (u2 == NULL) { + ADDMSG(&u->faction->msgs, + msg_message("give_peasants", "unit resource amount", u, rtype, given)); + } + else if (u2->faction != u->faction) { + message *msg; - msg = - msg_message("give", "unit target resource amount", u, u2, rtype, given); - add_message(&u->faction->msgs, msg); - msg_release(msg); + msg = + msg_message("give", "unit target resource amount", u, u2, rtype, given); + add_message(&u->faction->msgs, msg); + msg_release(msg); - msg = - msg_message("receive", "unit target resource amount", u, u2, rtype, - received); - add_message(&u2->faction->msgs, msg); - msg_release(msg); - } + msg = + msg_message("receive", "unit target resource amount", u, u2, rtype, + received); + add_message(&u2->faction->msgs, msg); + msg_release(msg); + } } static bool limited_give(const item_type * type) { - /* trade only money 2:1, if at all */ - return (type->rtype == get_resourcetype(R_SILVER)); + /* trade only money 2:1, if at all */ + return (type->rtype == get_resourcetype(R_SILVER)); } int give_quota(const unit * src, const unit * dst, const item_type * type, - int n) + int n) { - float divisor; + float divisor; - if (!limited_give(type)) { + if (!limited_give(type)) { + return n; + } + if (dst && src && src->faction != dst->faction) { + divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1); + assert(divisor == 0 || divisor >= 1); + if (divisor >= 1) { + /* predictable > correct: */ + int x = (int)(n / divisor); + return x; + } + } return n; - } - if (dst && src && src->faction != dst->faction) { - divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1); - assert(divisor == 0 || divisor >= 1); - if (divisor >= 1) { - /* predictable > correct: */ - int x = (int)(n / divisor); - return x; - } - } - return n; } int give_item(int want, const item_type * itype, unit * src, unit * dest, - struct order *ord) +struct order *ord) { - short error = 0; - int n, r; + short error = 0; + int n, r; - assert(itype != NULL); - n = get_pooled(src, item2resource(itype), GET_SLACK | GET_POOLED_SLACK, want); - n = _min(want, n); - r = n; - if (dest && src->faction != dest->faction - && src->faction->age < GiveRestriction()) { - if (ord != NULL) { - ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "giverestriction", - "turns", GiveRestriction())); + assert(itype != NULL); + n = get_pooled(src, item2resource(itype), GET_SLACK | GET_POOLED_SLACK, want); + n = _min(want, n); + r = n; + if (dest && src->faction != dest->faction + && src->faction->age < GiveRestriction()) { + if (ord != NULL) { + ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "giverestriction", + "turns", GiveRestriction())); + } + return -1; } - return -1; - } else if (n == 0) { - int reserve = get_reservation(src, itype->rtype); - if (reserve) { - msg_feedback(src, ord, "nogive_reserved", "resource reservation", - itype->rtype, reserve); - return -1; + else if (n == 0) { + int reserve = get_reservation(src, itype->rtype); + if (reserve) { + msg_feedback(src, ord, "nogive_reserved", "resource reservation", + itype->rtype, reserve); + return -1; + } + error = 36; } - error = 36; - } else if (itype->flags & ITF_CURSED) { - error = 25; - } else if (itype->give == NULL || itype->give(src, dest, itype, n, ord) != 0) { - int use = use_pooled(src, item2resource(itype), GET_SLACK, n); - if (use < n) - use += - use_pooled(src, item2resource(itype), GET_POOLED_SLACK, - n - use); - if (dest) { - r = give_quota(src, dest, itype, n); - i_change(&dest->items, itype, r); + else if (itype->flags & ITF_CURSED) { + error = 25; + } + else if (itype->give == NULL || itype->give(src, dest, itype, n, ord) != 0) { + int use = use_pooled(src, item2resource(itype), GET_SLACK, n); + if (use < n) + use += + use_pooled(src, item2resource(itype), GET_POOLED_SLACK, + n - use); + if (dest) { + r = give_quota(src, dest, itype, n); + i_change(&dest->items, itype, r); #ifdef RESERVE_GIVE #ifdef RESERVE_DONATIONS - change_reservation(dest, item2resource(itype), r); + change_reservation(dest, item2resource(itype), r); #else - if (src->faction == dest->faction) { - change_reservation(dest, item2resource(itype), r); - } + if (src->faction == dest->faction) { + change_reservation(dest, item2resource(itype), r); + } #endif #endif #if MUSEUM_MODULE && defined(TODO) - /* TODO: use a trigger for the museum warden! */ - if (a_find(dest->attribs, &at_warden)) { - warden_add_give(src, dest, itype, r); - } + /* TODO: use a trigger for the museum warden! */ + if (a_find(dest->attribs, &at_warden)) { + warden_add_give(src, dest, itype, r); + } #endif - handle_event(dest->attribs, "receive", src); + handle_event(dest->attribs, "receive", src); + } + handle_event(src->attribs, "give", dest); } - handle_event(src->attribs, "give", dest); - } - add_give(src, dest, n, r, item2resource(itype), ord, error); - if (error) - return -1; - return 0; + add_give(src, dest, n, r, item2resource(itype), ord, error); + if (error) + return -1; + return 0; } void give_men(int n, unit * u, unit * u2, struct order *ord) { - ship *sh; - int k = 0; - int error = 0; + ship *sh; + int k = 0; + int error = 0; - if (u2 && u->faction != u2->faction && u->faction->age < GiveRestriction()) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "giverestriction", - "turns", GiveRestriction())); - return; - } else if (u == u2) { - error = 10; - } - else if (!u2 && u_race(u) == get_race(RC_SNOTLING)) { - /* snotlings may not be given to the peasants. */ - error = 307; - } else if (u2 && u2->number && (fval(u, UFL_HERO) != fval(u2, UFL_HERO))) { - /* heroes may not be given to non-heroes and vice versa */ - error = 75; - } else if (unit_has_cursed_item(u) || (u2 && unit_has_cursed_item(u2))) { - error = 78; - } else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, C_SLAVE, 0)) { - error = 74; - } else if (u2 && fval(u, UFL_HUNGER)) { - /* hungry people cannot be given away */ - error = 73; - } else if (u2 && (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, C_SLAVE, 0))) { - error = 75; - } else if (u2 && !ucontact(u2, u)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", - "target", u2)); - error = -1; - } else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) { - /* cannot give units to and from magicians */ - error = 158; - } else if (u2 && (fval(u, UFL_WERE) != fval(u2, UFL_WERE))) { - /* werewolves can't be given to non-werewolves and vice-versa */ - error = 312; - } else if (u2 && u2->number != 0 && u_race(u2) != u_race(u)) { - log_warning("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[1]); - error = 139; - } else if (u2 != NULL && (get_racename(u2->attribs) - || get_racename(u->attribs))) { - error = 139; - } else if (u2 && u2->faction != u->faction && !rule_transfermen()) { - error = 74; - } else { - if (n > u->number) - n = u->number; - if (u2 && n + u2->number > UNIT_MAXSIZE) { - n = UNIT_MAXSIZE - u2->number; - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_unit_size", - "maxsize", UNIT_MAXSIZE)); - assert(n >= 0); + if (u2 && u->faction != u2->faction && u->faction->age < GiveRestriction()) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "giverestriction", + "turns", GiveRestriction())); + return; } - if (n == 0) { - error = 96; - } else if (u2 && u->faction != u2->faction) { - if (u2->faction->newbies + n > MAXNEWBIES) { - error = 129; - } else if (u_race(u) != u2->faction->race) { - if (u2->faction->race != get_race(RC_HUMAN)) { - error = 120; - } else if (count_migrants(u2->faction) + n > - count_maxmigrants(u2->faction)) { - error = 128; - } else if (has_limited_skills(u) || has_limited_skills(u2)) { - error = 154; - } else if (u2->number != 0) { - error = 139; + else if (u == u2) { + error = 10; + } + else if (!u2 && u_race(u) == get_race(RC_SNOTLING)) { + /* snotlings may not be given to the peasants. */ + error = 307; + } + else if (u2 && u2->number && (fval(u, UFL_HERO) != fval(u2, UFL_HERO))) { + /* heroes may not be given to non-heroes and vice versa */ + error = 75; + } + else if (unit_has_cursed_item(u) || (u2 && unit_has_cursed_item(u2))) { + error = 78; + } + else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, C_SLAVE, 0)) { + error = 74; + } + else if (u2 && fval(u, UFL_HUNGER)) { + /* hungry people cannot be given away */ + error = 73; + } + else if (u2 && (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, C_SLAVE, 0))) { + error = 75; + } + else if (u2 && !ucontact(u2, u)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", + "target", u2)); + error = -1; + } + else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) { + /* cannot give units to and from magicians */ + error = 158; + } + else if (u2 && (fval(u, UFL_WERE) != fval(u2, UFL_WERE))) { + /* werewolves can't be given to non-werewolves and vice-versa */ + error = 312; + } + else if (u2 && u2->number != 0 && u_race(u2) != u_race(u)) { + log_warning("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[1]); + error = 139; + } + else if (u2 != NULL && (get_racename(u2->attribs) + || get_racename(u->attribs))) { + error = 139; + } + else if (u2 && u2->faction != u->faction && !rule_transfermen()) { + error = 74; + } + else { + if (n > u->number) + n = u->number; + if (u2 && n + u2->number > UNIT_MAXSIZE) { + n = UNIT_MAXSIZE - u2->number; + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_unit_size", + "maxsize", UNIT_MAXSIZE)); + assert(n >= 0); + } + if (n == 0) { + error = 96; + } + else if (u2 && u->faction != u2->faction) { + if (u2->faction->newbies + n > MAXNEWBIES) { + error = 129; + } + else if (u_race(u) != u2->faction->race) { + if (u2->faction->race != get_race(RC_HUMAN)) { + error = 120; + } + else if (count_migrants(u2->faction) + n > + count_maxmigrants(u2->faction)) { + error = 128; + } + else if (has_limited_skills(u) || has_limited_skills(u2)) { + error = 154; + } + else if (u2->number != 0) { + error = 139; + } + } } - } - } - } - - if (u2 && (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY))) { - k = count_skill(u2->faction, SK_ALCHEMY); - - /* Falls die Zieleinheit keine Alchemisten sind, werden sie nun - * welche. */ - if (!has_skill(u2, SK_ALCHEMY) && has_skill(u, SK_ALCHEMY)) - k += u2->number; - - /* Wenn in eine Alchemisteneinheit Personen verschoben werden */ - if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) - k += n; - - /* Wenn Parteigrenzen überschritten werden */ - if (u2->faction != u->faction) - k += n; - - /* wird das Alchemistenmaximum ueberschritten ? */ - - if (k > skill_limit(u2->faction, SK_ALCHEMY)) { - error = 156; - } - } - - if (error == 0) { - if (u2 && u2->number == 0) { - set_racename(&u2->attribs, get_racename(u->attribs)); - u_setrace(u2, u_race(u)); - u2->irace = u->irace; - if (fval(u, UFL_HERO)) - fset(u2, UFL_HERO); - else - freset(u2, UFL_HERO); } - if (u2) { - /* Einheiten von Schiffen können nicht NACH in von - * Nicht-alliierten bewachten Regionen ausführen */ - sh = leftship(u); - if (sh) { - set_leftship(u2, sh); - } - transfermen(u, u2, n); - if (u->faction != u2->faction) { - u2->faction->newbies += n; - } - } else { - if (getunitpeasants) { + if (u2 && (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY))) { + k = count_skill(u2->faction, SK_ALCHEMY); + + /* Falls die Zieleinheit keine Alchemisten sind, werden sie nun + * welche. */ + if (!has_skill(u2, SK_ALCHEMY) && has_skill(u, SK_ALCHEMY)) + k += u2->number; + + /* Wenn in eine Alchemisteneinheit Personen verschoben werden */ + if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) + k += n; + + /* Wenn Parteigrenzen überschritten werden */ + if (u2->faction != u->faction) + k += n; + + /* wird das Alchemistenmaximum ueberschritten ? */ + + if (k > skill_limit(u2->faction, SK_ALCHEMY)) { + error = 156; + } + } + + if (error == 0) { + if (u2 && u2->number == 0) { + set_racename(&u2->attribs, get_racename(u->attribs)); + u_setrace(u2, u_race(u)); + u2->irace = u->irace; + if (fval(u, UFL_HERO)) + fset(u2, UFL_HERO); + else + freset(u2, UFL_HERO); + } + + if (u2) { + /* Einheiten von Schiffen können nicht NACH in von + * Nicht-alliierten bewachten Regionen ausführen */ + sh = leftship(u); + if (sh) { + set_leftship(u2, sh); + } + transfermen(u, u2, n); + if (u->faction != u2->faction) { + u2->faction->newbies += n; + } + } + else { + if (getunitpeasants) { #ifdef ORCIFICATION - if (u_race(u) == get_race(RC_SNOTLING) && !fval(u->region, RF_ORCIFIED)) { - attrib *a = a_find(u->region->attribs, &at_orcification); - if (!a) - a = a_add(&u->region->attribs, a_new(&at_orcification)); - a->data.i += n; - } + if (u_race(u) == get_race(RC_SNOTLING) && !fval(u->region, RF_ORCIFIED)) { + attrib *a = a_find(u->region->attribs, &at_orcification); + if (!a) + a = a_add(&u->region->attribs, a_new(&at_orcification)); + a->data.i += n; + } #endif - transfermen(u, NULL, n); - } else { - error = 159; - } + transfermen(u, NULL, n); + } + else { + error = 159; + } + } + } + if (error > 0) { + cmistake(u, ord, error, MSG_COMMERCE); + } + else if (!u2) { + ADDMSG(&u->faction->msgs, + msg_message("give_person_peasants", "unit amount", u, n)); + } + else if (u2->faction != u->faction) { + message *msg = msg_message("give_person", "unit target amount", u, u2, n); + add_message(&u->faction->msgs, msg); + add_message(&u2->faction->msgs, msg); + msg_release(msg); } - } - if (error > 0) { - cmistake(u, ord, error, MSG_COMMERCE); - } else if (!u2) { - ADDMSG(&u->faction->msgs, - msg_message("give_person_peasants", "unit amount", u, n)); - } else if (u2->faction != u->faction) { - message *msg = msg_message("give_person", "unit target amount", u, u2, n); - add_message(&u->faction->msgs, msg); - add_message(&u2->faction->msgs, msg); - msg_release(msg); - } } void give_unit(unit * u, unit * u2, order * ord) { - region *r = u->region; - int n = u->number; + region *r = u->region; + int n = u->number; - if (!rule_transfermen() && u->faction != u2->faction) { - cmistake(u, ord, 74, MSG_COMMERCE); - return; - } + if (!rule_transfermen() && u->faction != u2->faction) { + cmistake(u, ord, 74, MSG_COMMERCE); + return; + } - if (u && unit_has_cursed_item(u)) { - cmistake(u, ord, 78, MSG_COMMERCE); - return; - } + if (u && unit_has_cursed_item(u)) { + cmistake(u, ord, 78, MSG_COMMERCE); + return; + } - if (fval(u, UFL_HERO)) { - cmistake(u, ord, 75, MSG_COMMERCE); - return; - } - if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { - cmistake(u, ord, 74, MSG_COMMERCE); - return; - } + if (fval(u, UFL_HERO)) { + cmistake(u, ord, 75, MSG_COMMERCE); + return; + } + if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { + cmistake(u, ord, 74, MSG_COMMERCE); + return; + } - if (u2 == NULL) { - if (fval(r->terrain, SEA_REGION)) { - cmistake(u, ord, 152, MSG_COMMERCE); - } else if (getunitpeasants) { - unit *u3; - - for (u3 = r->units; u3; u3 = u3->next) - if (u3->faction == u->faction && u != u3) - break; - - if (u3) { - while (u->items) { - item *iold = i_remove(&u->items, u->items); - item *inew = *i_find(&u3->items, iold->type); - if (inew == NULL) - i_add(&u3->items, iold); - else { - inew->number += iold->number; - i_free(iold); - } + if (u2 == NULL) { + if (fval(r->terrain, SEA_REGION)) { + cmistake(u, ord, 152, MSG_COMMERCE); } - } - give_men(u->number, u, NULL, ord); - cmistake(u, ord, 153, MSG_COMMERCE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - } - return; - } + else if (getunitpeasants) { + unit *u3; - if (!alliedunit(u2, u->faction, HELP_GIVE) && ucontact(u2, u) == 0) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", - "target", u2)); - return; - } - if (u->number == 0) { - cmistake(u, ord, 105, MSG_COMMERCE); - return; - } - if (u2->faction->newbies + n > MAXNEWBIES) { - cmistake(u, ord, 129, MSG_COMMERCE); - return; - } - if (u_race(u) != u2->faction->race) { - if (u2->faction->race != get_race(RC_HUMAN)) { - cmistake(u, ord, 120, MSG_COMMERCE); - return; + for (u3 = r->units; u3; u3 = u3->next) + if (u3->faction == u->faction && u != u3) + break; + + if (u3) { + while (u->items) { + item *iold = i_remove(&u->items, u->items); + item *inew = *i_find(&u3->items, iold->type); + if (inew == NULL) + i_add(&u3->items, iold); + else { + inew->number += iold->number; + i_free(iold); + } + } + } + give_men(u->number, u, NULL, ord); + cmistake(u, ord, 153, MSG_COMMERCE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + } + return; } - if (count_migrants(u2->faction) + u->number > - count_maxmigrants(u2->faction)) { - cmistake(u, ord, 128, MSG_COMMERCE); - return; + + if (!alliedunit(u2, u->faction, HELP_GIVE) && ucontact(u2, u) == 0) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", + "target", u2)); + return; } - if (has_limited_skills(u)) { - cmistake(u, ord, 154, MSG_COMMERCE); - return; + if (u->number == 0) { + cmistake(u, ord, 105, MSG_COMMERCE); + return; } - } - if (has_skill(u, SK_MAGIC)) { - sc_mage *mage; - if (count_skill(u2->faction, SK_MAGIC) + u->number > - skill_limit(u2->faction, SK_MAGIC)) { - cmistake(u, ord, 155, MSG_COMMERCE); - return; + if (u2->faction->newbies + n > MAXNEWBIES) { + cmistake(u, ord, 129, MSG_COMMERCE); + return; } - mage = get_mage(u); - if (!mage || u2->faction->magiegebiet != mage->magietyp) { - cmistake(u, ord, 157, MSG_COMMERCE); - return; + if (u_race(u) != u2->faction->race) { + if (u2->faction->race != get_race(RC_HUMAN)) { + cmistake(u, ord, 120, MSG_COMMERCE); + return; + } + if (count_migrants(u2->faction) + u->number > + count_maxmigrants(u2->faction)) { + cmistake(u, ord, 128, MSG_COMMERCE); + return; + } + if (has_limited_skills(u)) { + cmistake(u, ord, 154, MSG_COMMERCE); + return; + } } - } - if (has_skill(u, SK_ALCHEMY) - && count_skill(u2->faction, SK_ALCHEMY) + u->number > - skill_limit(u2->faction, SK_ALCHEMY)) { - cmistake(u, ord, 156, MSG_COMMERCE); - return; - } - add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0); - u_setfaction(u, u2->faction); - u2->faction->newbies += n; + if (has_skill(u, SK_MAGIC)) { + sc_mage *mage; + if (count_skill(u2->faction, SK_MAGIC) + u->number > + skill_limit(u2->faction, SK_MAGIC)) { + cmistake(u, ord, 155, MSG_COMMERCE); + return; + } + mage = get_mage(u); + if (!mage || u2->faction->magiegebiet != mage->magietyp) { + cmistake(u, ord, 157, MSG_COMMERCE); + return; + } + } + if (has_skill(u, SK_ALCHEMY) + && count_skill(u2->faction, SK_ALCHEMY) + u->number > + skill_limit(u2->faction, SK_ALCHEMY)) { + cmistake(u, ord, 156, MSG_COMMERCE); + return; + } + add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0); + u_setfaction(u, u2->faction); + u2->faction->newbies += n; } diff --git a/src/kernel/magic.c b/src/kernel/magic.c index da119742d..45af0aacf 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -1,7 +1,8 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, +Enno Rehling +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 @@ -77,28 +78,28 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include const char *magic_school[MAXMAGIETYP] = { - "gray", - "illaun", - "tybied", - "cerddor", - "gwyrrd", - "draig", - "common" + "gray", + "illaun", + "tybied", + "cerddor", + "gwyrrd", + "draig", + "common" }; static void a_init_reportspell(struct attrib *a) { - a->data.v = calloc(1, sizeof(spellbook_entry)); + a->data.v = calloc(1, sizeof(spellbook_entry)); } static void a_finalize_reportspell(struct attrib *a) { - free(a->data.v); + free(a->data.v); } attrib_type at_reportspell = { - "reportspell", - a_init_reportspell, - a_finalize_reportspell, - 0, NO_WRITE, NO_READ + "reportspell", + a_init_reportspell, + a_finalize_reportspell, + 0, NO_WRITE, NO_READ }; /** ** at_icastle @@ -107,82 +108,83 @@ attrib_type at_reportspell = { static float MagicRegeneration(void) { - static float value = -1.0; - if (value < 0) { - const char *str = get_param(global.parameters, "magic.regeneration"); - value = str ? (float)atof(str) : 1.0F; - } - return value; + static float value = -1.0; + if (value < 0) { + const char *str = get_param(global.parameters, "magic.regeneration"); + value = str ? (float)atof(str) : 1.0F; + } + return value; } float MagicPower(void) { - static float value = -1.0; - if (value < 0) { - const char *str = get_param(global.parameters, "magic.power"); - value = str ? (float)atof(str) : 1.0f; - } - return value; + static float value = -1.0; + if (value < 0) { + const char *str = get_param(global.parameters, "magic.power"); + value = str ? (float)atof(str) : 1.0f; + } + return value; } static int a_readicastle(attrib * a, void *owner, struct storage *store) { - icastle_data *data = (icastle_data *) a->data.v; - variant bno; - char token[32]; - READ_TOK(store, token, sizeof(token)); - READ_INT(store, &bno.i); - READ_INT(store, &data->time); - data->building = findbuilding(bno.i); - if (!data->building) { - /* this shouldn't happen, but just in case it does: */ - ur_add(bno, &data->building, resolve_building); - } - data->type = bt_find(token); - return AT_READ_OK; + icastle_data *data = (icastle_data *)a->data.v; + variant bno; + char token[32]; + READ_TOK(store, token, sizeof(token)); + READ_INT(store, &bno.i); + READ_INT(store, &data->time); + data->building = findbuilding(bno.i); + if (!data->building) { + /* this shouldn't happen, but just in case it does: */ + ur_add(bno, &data->building, resolve_building); + } + data->type = bt_find(token); + return AT_READ_OK; } static void a_writeicastle(const attrib * a, const void *owner, struct storage *store) { - icastle_data *data = (icastle_data *) a->data.v; - WRITE_TOK(store, data->type->_name); - WRITE_INT(store, data->building->no); - WRITE_INT(store, data->time); + icastle_data *data = (icastle_data *)a->data.v; + WRITE_TOK(store, data->type->_name); + WRITE_INT(store, data->building->no); + WRITE_INT(store, data->time); } static int a_ageicastle(struct attrib *a) { - icastle_data *data = (icastle_data *) a->data.v; - if (data->time <= 0) { - building *b = data->building; - region *r = b->region; - ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b)); - /* remove_building lets units leave the building */ - remove_building(&r->buildings, b); - return AT_AGE_REMOVE; - } else - data->time--; - return AT_AGE_KEEP; + icastle_data *data = (icastle_data *)a->data.v; + if (data->time <= 0) { + building *b = data->building; + region *r = b->region; + ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b)); + /* remove_building lets units leave the building */ + remove_building(&r->buildings, b); + return AT_AGE_REMOVE; + } + else + data->time--; + return AT_AGE_KEEP; } static void a_initicastle(struct attrib *a) { - a->data.v = calloc(sizeof(icastle_data), 1); + a->data.v = calloc(sizeof(icastle_data), 1); } static void a_finalizeicastle(struct attrib *a) { - free(a->data.v); + free(a->data.v); } attrib_type at_icastle = { - "zauber_icastle", - a_initicastle, - a_finalizeicastle, - a_ageicastle, - a_writeicastle, - a_readicastle + "zauber_icastle", + a_initicastle, + a_finalizeicastle, + a_ageicastle, + a_writeicastle, + a_readicastle }; /* ------------------------------------------------------------- */ @@ -196,170 +198,173 @@ extern int dice(int count, int value); static void init_mage(attrib * a) { - a->data.v = calloc(sizeof(sc_mage), 1); + a->data.v = calloc(sizeof(sc_mage), 1); } static void free_mage(attrib * a) { - sc_mage *mage = (sc_mage *) a->data.v; - if (mage->spellbook) { - spellbook_clear(mage->spellbook); - free(mage->spellbook); - } - free(mage); + sc_mage *mage = (sc_mage *)a->data.v; + if (mage->spellbook) { + spellbook_clear(mage->spellbook); + free(mage->spellbook); + } + free(mage); } int FactionSpells(void) { - static int rules_factionspells = -1; - if (rules_factionspells < 0) { - rules_factionspells = - get_param_int(global.parameters, "rules.magic.factionlist", 0); - } - return rules_factionspells; + static int rules_factionspells = -1; + if (rules_factionspells < 0) { + rules_factionspells = + get_param_int(global.parameters, "rules.magic.factionlist", 0); + } + return rules_factionspells; } void read_spells(struct quicklist **slistp, magic_t mtype, - struct storage *store) +struct storage *store) { - for (;;) { - spell *sp; - char spname[64]; + for (;;) { + spell *sp; + char spname[64]; - if (global.data_version < SPELLNAME_VERSION) { - int i; - READ_INT(store, &i); - if (i < 0) - break; - sp = find_spellbyid((unsigned int) i); - } else { - READ_TOK(store, spname, sizeof(spname)); - if (strcmp(spname, "end") == 0) - break; - sp = find_spell(spname); - if (!sp) { - log_error("read_spells: could not find spell '%s' in school '%s'\n", spname, magic_school[mtype]); - } + if (global.data_version < SPELLNAME_VERSION) { + int i; + READ_INT(store, &i); + if (i < 0) + break; + sp = find_spellbyid((unsigned int)i); + } + else { + READ_TOK(store, spname, sizeof(spname)); + if (strcmp(spname, "end") == 0) + break; + sp = find_spell(spname); + if (!sp) { + log_error("read_spells: could not find spell '%s' in school '%s'\n", spname, magic_school[mtype]); + } + } + if (sp) { + add_spell(slistp, sp); + } } - if (sp) { - add_spell(slistp, sp); - } - } } int get_spell_level_mage(const spell * sp, void * cbdata) { - sc_mage *mage = (sc_mage *)cbdata; - spellbook *book = get_spellbook(magic_school[mage->magietyp]); - spellbook_entry *sbe = spellbook_get(book, sp); - return sbe ? sbe->level : 0; + sc_mage *mage = (sc_mage *)cbdata; + spellbook *book = get_spellbook(magic_school[mage->magietyp]); + spellbook_entry *sbe = spellbook_get(book, sp); + return sbe ? sbe->level : 0; } static int read_mage(attrib * a, void *owner, struct storage *store) { - int i, mtype; - sc_mage *mage = (sc_mage *) a->data.v; - char spname[64]; + int i, mtype; + sc_mage *mage = (sc_mage *)a->data.v; + char spname[64]; - READ_INT(store, &mtype); - mage->magietyp = (magic_t)mtype; - READ_INT(store, &mage->spellpoints); - READ_INT(store, &mage->spchange); - for (i = 0; i != MAXCOMBATSPELLS; ++i) { - spell *sp = NULL; - int level = 0; - if (global.data_version < SPELLNAME_VERSION) { - int spid; - READ_INT(store, &spid); - READ_INT(store, &level); - if (spid >= 0) { - sp = find_spellbyid((unsigned int) spid); - } - } else { - READ_TOK(store, spname, sizeof(spname)); - READ_INT(store, &level); - - if (strcmp("none", spname) != 0) { - sp = find_spell(spname); - if (!sp) { - log_error("read_mage: could not find combat spell '%s' in school '%s'\n", spname, magic_school[mage->magietyp]); + READ_INT(store, &mtype); + mage->magietyp = (magic_t)mtype; + READ_INT(store, &mage->spellpoints); + READ_INT(store, &mage->spchange); + for (i = 0; i != MAXCOMBATSPELLS; ++i) { + spell *sp = NULL; + int level = 0; + if (global.data_version < SPELLNAME_VERSION) { + int spid; + READ_INT(store, &spid); + READ_INT(store, &level); + if (spid >= 0) { + sp = find_spellbyid((unsigned int)spid); + } + } + else { + READ_TOK(store, spname, sizeof(spname)); + READ_INT(store, &level); + + if (strcmp("none", spname) != 0) { + sp = find_spell(spname); + if (!sp) { + log_error("read_mage: could not find combat spell '%s' in school '%s'\n", spname, magic_school[mage->magietyp]); + } + } + } + if (sp && level >= 0) { + int slot = -1; + if (sp->sptyp & PRECOMBATSPELL) + slot = 0; + else if (sp->sptyp & COMBATSPELL) + slot = 1; + else if (sp->sptyp & POSTCOMBATSPELL) + slot = 2; + if (slot >= 0) { + mage->combatspells[slot].level = level; + mage->combatspells[slot].sp = sp; + } } - } } - if (sp && level >= 0) { - int slot = -1; - if (sp->sptyp & PRECOMBATSPELL) - slot = 0; - else if (sp->sptyp & COMBATSPELL) - slot = 1; - else if (sp->sptyp & POSTCOMBATSPELL) - slot = 2; - if (slot >= 0) { - mage->combatspells[slot].level = level; - mage->combatspells[slot].sp = sp; - } + if (mage->magietyp == M_GRAY) { + read_spellbook(&mage->spellbook, store, get_spell_level_mage, mage); } - } - if (mage->magietyp==M_GRAY) { - read_spellbook(&mage->spellbook, store, get_spell_level_mage, mage); - } else { - read_spellbook(0, store, 0, mage); - } - return AT_READ_OK; + else { + read_spellbook(0, store, 0, mage); + } + return AT_READ_OK; } void write_spells(struct quicklist *slist, struct storage *store) { - quicklist *ql; - int qi; + quicklist *ql; + int qi; - for (ql = slist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { - spell *sp = (spell *) ql_get(ql, qi); - WRITE_TOK(store, sp->sname); - } - WRITE_TOK(store, "end"); + for (ql = slist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + spell *sp = (spell *)ql_get(ql, qi); + WRITE_TOK(store, sp->sname); + } + WRITE_TOK(store, "end"); } static void write_mage(const attrib * a, const void *owner, struct storage *store) { - int i; - sc_mage *mage = (sc_mage *) a->data.v; + int i; + sc_mage *mage = (sc_mage *)a->data.v; - WRITE_INT(store, mage->magietyp); - WRITE_INT(store, mage->spellpoints); - WRITE_INT(store, mage->spchange); - for (i = 0; i != MAXCOMBATSPELLS; ++i) { - WRITE_TOK(store, - mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none"); - WRITE_INT(store, mage->combatspells[i].level); - } - write_spellbook(mage->spellbook, store); + WRITE_INT(store, mage->magietyp); + WRITE_INT(store, mage->spellpoints); + WRITE_INT(store, mage->spchange); + for (i = 0; i != MAXCOMBATSPELLS; ++i) { + WRITE_TOK(store, + mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none"); + WRITE_INT(store, mage->combatspells[i].level); + } + write_spellbook(mage->spellbook, store); } attrib_type at_mage = { - "mage", - init_mage, - free_mage, - NULL, - write_mage, - read_mage, - ATF_UNIQUE + "mage", + init_mage, + free_mage, + NULL, + write_mage, + read_mage, + ATF_UNIQUE }; bool is_mage(const unit * u) { - return i2b(get_mage(u) != NULL); + return i2b(get_mage(u) != NULL); } sc_mage *get_mage(const unit * u) { - if (has_skill(u, SK_MAGIC)) { - attrib *a = a_find(u->attribs, &at_mage); - if (a) - return a->data.v; - } - return (sc_mage *) NULL; + if (has_skill(u, SK_MAGIC)) { + attrib *a = a_find(u->attribs, &at_mage); + if (a) + return a->data.v; + } + return (sc_mage *)NULL; } /* ------------------------------------------------------------- */ @@ -372,76 +377,77 @@ sc_mage *get_mage(const unit * u) static int read_seenspell(attrib * a, void *owner, struct storage *store) { - int i; - spell *sp = 0; - char token[32]; + int i; + spell *sp = 0; + char token[32]; - READ_TOK(store, token, sizeof(token)); - i = atoi(token); - if (i != 0) { - sp = find_spellbyid((unsigned int) i); - } else { - if (global.data_versiondata.v = sp; - return AT_READ_OK; + a->data.v = sp; + return AT_READ_OK; } static void write_seenspell(const attrib * a, const void *owner, struct storage *store) { - const spell *sp = (const spell *)a->data.v; - WRITE_TOK(store, sp->sname); + const spell *sp = (const spell *)a->data.v; + WRITE_TOK(store, sp->sname); } attrib_type at_seenspell = { - "seenspell", NULL, NULL, NULL, write_seenspell, read_seenspell + "seenspell", NULL, NULL, NULL, write_seenspell, read_seenspell }; #define MAXSPELLS 256 static bool already_seen(const faction * f, const spell * sp) { - attrib *a; + attrib *a; - for (a = a_find(f->attribs, &at_seenspell); a && a->type == &at_seenspell; - a = a->next) { - if (a->data.v == sp) - return true; - } - return false; + for (a = a_find(f->attribs, &at_seenspell); a && a->type == &at_seenspell; + a = a->next) { + if (a->data.v == sp) + return true; + } + return false; } void show_new_spells(faction * f, int level, const spellbook *book) { - if (book) { - quicklist *ql = book->spells; - int qi; + if (book) { + quicklist *ql = book->spells; + int qi; - for (qi = 0; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *) ql_get(ql, qi); - if (sbe->level <= level) { + for (qi = 0; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); + if (sbe->level <= level) { - if (!already_seen(f, sbe->sp)) { - attrib * a = a_new(&at_reportspell); - spellbook_entry * entry = (spellbook_entry *)a->data.v; - entry->level = sbe->level; - entry->sp = sbe->sp; - a_add(&f->attribs, a); - a_add(&f->attribs, a_new(&at_seenspell))->data.v = sbe->sp; + if (!already_seen(f, sbe->sp)) { + attrib * a = a_new(&at_reportspell); + spellbook_entry * entry = (spellbook_entry *)a->data.v; + entry->level = sbe->level; + entry->sp = sbe->sp; + a_add(&f->attribs, a); + a_add(&f->attribs, a_new(&at_seenspell))->data.v = sbe->sp; + } + } } - } } - } } /** update the spellbook with a new level @@ -449,72 +455,73 @@ void show_new_spells(faction * f, int level, const spellbook *book) */ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells) { - spellbook_entry *commonspells[MAXSPELLS]; - int qi, numspells = 0; - quicklist *ql; + spellbook_entry *commonspells[MAXSPELLS]; + int qi, numspells = 0; + quicklist *ql; - if (level <= f->max_spelllevel) { - return; - } - - for (qi = 0, ql = book->spells; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *) ql_get(ql, qi); - if (sbe->level <= level) { - commonspells[numspells++] = sbe; + if (level <= f->max_spelllevel) { + return; } - } - while (numspells > 0 && level > f->max_spelllevel) { - int i; - - ++f->max_spelllevel; - for (i = 0; i < num_spells; ++i) { - int maxspell = numspells; - int spellno = -1; - spellbook_entry *sbe = 0; - while (!sbe && maxspell>0) { - spellno = rng_int() % maxspell; - sbe = commonspells[spellno]; - if (sbe->level>f->max_spelllevel) { - commonspells[spellno] = commonspells[--maxspell]; - commonspells[maxspell] = sbe; - sbe = 0; - } else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { - commonspells[spellno] = commonspells[--numspells]; - if (maxspell>numspells) { - maxspell = numspells; - } - sbe = 0; + for (qi = 0, ql = book->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry * sbe = (spellbook_entry *)ql_get(ql, qi); + if (sbe->level <= level) { + commonspells[numspells++] = sbe; + } + } + + while (numspells > 0 && level > f->max_spelllevel) { + int i; + + ++f->max_spelllevel; + for (i = 0; i < num_spells; ++i) { + int maxspell = numspells; + int spellno = -1; + spellbook_entry *sbe = 0; + while (!sbe && maxspell>0) { + spellno = rng_int() % maxspell; + sbe = commonspells[spellno]; + if (sbe->level > f->max_spelllevel) { + commonspells[spellno] = commonspells[--maxspell]; + commonspells[maxspell] = sbe; + sbe = 0; + } + else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { + commonspells[spellno] = commonspells[--numspells]; + if (maxspell > numspells) { + maxspell = numspells; + } + sbe = 0; + } + } + + if (spellno < maxspell) { + if (!f->spellbook) { + f->spellbook = create_spellbook(0); + } + spellbook_add(f->spellbook, sbe->sp, sbe->level); + commonspells[spellno] = commonspells[--numspells]; + } } - } - - if (spellnospellbook) { - f->spellbook = create_spellbook(0); - } - spellbook_add(f->spellbook, sbe->sp, sbe->level); - commonspells[spellno] = commonspells[--numspells]; - } } - } } /* ------------------------------------------------------------- */ /* Erzeugen eines neuen Magiers */ sc_mage *create_mage(unit * u, magic_t mtyp) { - sc_mage *mage; - attrib *a; + sc_mage *mage; + attrib *a; - a = a_find(u->attribs, &at_mage); - if (a != NULL) { - a_remove(&u->attribs, a); - } - a = a_add(&u->attribs, a_new(&at_mage)); - mage = a->data.v; + a = a_find(u->attribs, &at_mage); + if (a != NULL) { + a_remove(&u->attribs, a); + } + a = a_add(&u->attribs, a_new(&at_mage)); + mage = a->data.v; - mage->magietyp = mtyp; - return mage; + mage->magietyp = mtyp; + return mage; } /* ------------------------------------------------------------- */ @@ -522,12 +529,12 @@ sc_mage *create_mage(unit * u, magic_t mtyp) int u_hasspell(const unit *u, const struct spell *sp) { - spellbook * book = unit_get_spellbook(u); - spellbook_entry * sbe = book ? spellbook_get(book, sp) : 0; - if (sbe) { - return sbe->level<=effskill(u, SK_MAGIC); - } - return 0; + spellbook * book = unit_get_spellbook(u); + spellbook_entry * sbe = book ? spellbook_get(book, sp) : 0; + if (sbe) { + return sbe->level <= effskill(u, SK_MAGIC); + } + return 0; } /* ------------------------------------------------------------- */ @@ -535,14 +542,14 @@ int u_hasspell(const unit *u, const struct spell *sp) int get_combatspelllevel(const unit * u, int nr) { - sc_mage *m = get_mage(u); + sc_mage *m = get_mage(u); - assert(nr < MAXCOMBATSPELLS); - if (m) { - int level = eff_skill(u, SK_MAGIC, u->region); - return _min(m->combatspells[nr].level, level); - } - return -1; + assert(nr < MAXCOMBATSPELLS); + if (m) { + int level = eff_skill(u, SK_MAGIC, u->region); + return _min(m->combatspells[nr].level, level); + } + return -1; } /* ------------------------------------------------------------- */ @@ -550,112 +557,116 @@ int get_combatspelllevel(const unit * u, int nr) const spell *get_combatspell(const unit * u, int nr) { - sc_mage *m; + sc_mage *m; - assert(nr < MAXCOMBATSPELLS); - m = get_mage(u); - if (m) { - return m->combatspells[nr].sp; - } else if (u_race(u)->precombatspell != NULL) { - return u_race(u)->precombatspell; - } + assert(nr < MAXCOMBATSPELLS); + m = get_mage(u); + if (m) { + return m->combatspells[nr].sp; + } + else if (u_race(u)->precombatspell != NULL) { + return u_race(u)->precombatspell; + } - return NULL; + return NULL; } void set_combatspell(unit * u, spell * sp, struct order *ord, int level) { - sc_mage *mage = get_mage(u); - int i = -1; + sc_mage *mage = get_mage(u); + int i = -1; - assert(mage || !"trying to set a combat spell for non-mage"); + assert(mage || !"trying to set a combat spell for non-mage"); - /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ - if (!knowsspell(u->region, u, sp)) { - /* Fehler 'Spell not found' */ - cmistake(u, ord, 173, MSG_MAGIC); - return; - } - if (!u_hasspell(u, sp)) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, ord, 169, MSG_MAGIC); - return; - } - if (!(sp->sptyp & ISCOMBATSPELL)) { - /* Diesen Kampfzauber gibt es nicht */ - cmistake(u, ord, 171, MSG_MAGIC); - return; - } + /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ + if (!knowsspell(u->region, u, sp)) { + /* Fehler 'Spell not found' */ + cmistake(u, ord, 173, MSG_MAGIC); + return; + } + if (!u_hasspell(u, sp)) { + /* Diesen Zauber kennt die Einheit nicht */ + cmistake(u, ord, 169, MSG_MAGIC); + return; + } + if (!(sp->sptyp & ISCOMBATSPELL)) { + /* Diesen Kampfzauber gibt es nicht */ + cmistake(u, ord, 171, MSG_MAGIC); + return; + } - if (sp->sptyp & PRECOMBATSPELL) - i = 0; - else if (sp->sptyp & COMBATSPELL) - i = 1; - else if (sp->sptyp & POSTCOMBATSPELL) - i = 2; - assert(i >= 0); - mage->combatspells[i].sp = sp; - mage->combatspells[i].level = level; - return; + if (sp->sptyp & PRECOMBATSPELL) + i = 0; + else if (sp->sptyp & COMBATSPELL) + i = 1; + else if (sp->sptyp & POSTCOMBATSPELL) + i = 2; + assert(i >= 0); + mage->combatspells[i].sp = sp; + mage->combatspells[i].level = level; + return; } void unset_combatspell(unit * u, spell * sp) { - sc_mage *m; - int nr = 0; - int i; + sc_mage *m; + int nr = 0; + int i; - m = get_mage(u); - if (!m) + m = get_mage(u); + if (!m) + return; + + if (!sp) { + for (i = 0; i < MAXCOMBATSPELLS; i++) { + m->combatspells[i].sp = NULL; + } + } + else if (sp->sptyp & PRECOMBATSPELL) { + if (sp != get_combatspell(u, 0)) + return; + } + else if (sp->sptyp & COMBATSPELL) { + if (sp != get_combatspell(u, 1)) { + return; + } + nr = 1; + } + else if (sp->sptyp & POSTCOMBATSPELL) { + if (sp != get_combatspell(u, 2)) { + return; + } + nr = 2; + } + m->combatspells[nr].sp = NULL; + m->combatspells[nr].level = 0; return; - - if (!sp) { - for (i = 0; i < MAXCOMBATSPELLS; i++) { - m->combatspells[i].sp = NULL; - } - } else if (sp->sptyp & PRECOMBATSPELL) { - if (sp != get_combatspell(u, 0)) - return; - } else if (sp->sptyp & COMBATSPELL) { - if (sp != get_combatspell(u, 1)) { - return; - } - nr = 1; - } else if (sp->sptyp & POSTCOMBATSPELL) { - if (sp != get_combatspell(u, 2)) { - return; - } - nr = 2; - } - m->combatspells[nr].sp = NULL; - m->combatspells[nr].level = 0; - return; } /* ------------------------------------------------------------- */ /* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */ int get_spellpoints(const unit * u) { - sc_mage *m; + sc_mage *m; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; - return m->spellpoints; + return m->spellpoints; } void set_spellpoints(unit * u, int sp) { - sc_mage *m; + sc_mage *m; + + m = get_mage(u); + if (!m) + return; + + m->spellpoints = sp; - m = get_mage(u); - if (!m) return; - - m->spellpoints = sp; - - return; } /* @@ -663,19 +674,19 @@ void set_spellpoints(unit * u, int sp) */ int change_spellpoints(unit * u, int mp) { - sc_mage *m; - int sp; + sc_mage *m; + int sp; - m = get_mage(u); - if (!m) { - return 0; - } + m = get_mage(u); + if (!m) { + return 0; + } - /* verhindere negative Magiepunkte */ - sp = _max(m->spellpoints + mp, 0); - m->spellpoints = sp; + /* verhindere negative Magiepunkte */ + sp = _max(m->spellpoints + mp, 0); + m->spellpoints = sp; - return sp; + return sp; } /* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit @@ -683,13 +694,13 @@ int change_spellpoints(unit * u, int mp) */ static int get_spchange(const unit * u) { - sc_mage *m; + sc_mage *m; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; - return m->spchange; + return m->spchange; } /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte @@ -705,12 +716,12 @@ static int get_spchange(const unit * u) /** TODO: at_skillmod daraus machen */ static int use_item_aura(const region * r, const unit * u) { - int sk, n; + int sk, n; - sk = eff_skill(u, SK_MAGIC, r); - n = (int)(sk * sk * u_race(u)->maxaura / 4); + sk = eff_skill(u, SK_MAGIC, r); + n = (int)(sk * sk * u_race(u)->maxaura / 4); - return n; + return n; } int max_spellpoints(const region * r, const unit * u) @@ -723,7 +734,7 @@ int max_spellpoints(const region * r, const unit * u) sk = eff_skill(u, SK_MAGIC, r); msp = u_race(u)->maxaura * (pow(sk, potenz) / divisor + 1) + get_spchange(u); - + rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { msp += use_item_aura(r, u); @@ -754,22 +765,22 @@ int change_maxspellpoints(unit * u, int csp) */ int countspells(unit * u, int step) { - sc_mage *m; - int count; + sc_mage *m; + int count; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; + + if (step == 0) + return m->spellcount; + + count = m->spellcount + step; + + /* negative Werte abfangen. */ + m->spellcount = _max(0, count); - if (step == 0) return m->spellcount; - - count = m->spellcount + step; - - /* negative Werte abfangen. */ - m->spellcount = _max(0, count); - - return m->spellcount; } /* ------------------------------------------------------------- */ @@ -783,13 +794,13 @@ int spellcost(unit * u, const spell * sp) int count = countspells(u, 0); const resource_type *r_aura = get_resourcetype(R_AURA); - for (k = 0; sp->components[k].type; k++) { - if (sp->components[k].type == r_aura) { - aura = sp->components[k].amount; + for (k = 0; sp->components[k].type; k++) { + if (sp->components[k].type == r_aura) { + aura = sp->components[k].amount; + } } - } - aura *= (1 << count); - return aura; + aura *= (1 << count); + return aura; } /* ------------------------------------------------------------- */ @@ -801,23 +812,23 @@ int spellcost(unit * u, const spell * sp) * überschrieben werden */ static int spl_costtyp(const spell * sp) { - int k; - int costtyp = SPC_FIX; + int k; + int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { - if (costtyp == SPC_LINEAR) - return SPC_LINEAR; + for (k = 0; sp->components[k].type; k++) { + if (costtyp == SPC_LINEAR) + return SPC_LINEAR; - if (sp->components[k].cost == SPC_LINEAR) { - return SPC_LINEAR; + if (sp->components[k].cost == SPC_LINEAR) { + return SPC_LINEAR; + } + + /* wenn keine Fixkosten, Typ übernehmen */ + if (sp->components[k].cost != SPC_FIX) { + costtyp = sp->components[k].cost; + } } - - /* wenn keine Fixkosten, Typ übernehmen */ - if (sp->components[k].cost != SPC_FIX) { - costtyp = sp->components[k].cost; - } - } - return costtyp; + return costtyp; } /* ------------------------------------------------------------- */ @@ -833,54 +844,57 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) int k, maxlevel, needplevel; int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { - if (cast_level == 0) - return 0; + for (k = 0; sp->components[k].type; k++) { + if (cast_level == 0) + return 0; - if (sp->components[k].amount > 0) { - /* Die Kosten für Aura sind auch von der Zahl der bereits - * gezauberten Sprüche abhängig */ - if (sp->components[k].type == r_aura) { - needplevel = spellcost(u, sp) * range; - } else { - needplevel = sp->components[k].amount * range; - } - maxlevel = - get_pooled(u, sp->components[k].type, GET_DEFAULT, - needplevel * cast_level) / needplevel; + if (sp->components[k].amount > 0) { + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ + if (sp->components[k].type == r_aura) { + needplevel = spellcost(u, sp) * range; + } + else { + needplevel = sp->components[k].amount * range; + } + maxlevel = + get_pooled(u, sp->components[k].type, GET_DEFAULT, + needplevel * cast_level) / needplevel; - /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden - * sein und der cast_level ändert sich nicht */ - if (sp->components[k].cost == SPC_FIX) { - if (maxlevel < 1) - cast_level = 0; - /* ansonsten wird das Minimum aus maximal möglicher Stufe und der - * gewünschten gebildet */ - } else if (sp->components[k].cost == SPC_LEVEL) { - costtyp = SPC_LEVEL; - cast_level = _min(cast_level, maxlevel); - /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden - * sein, ansonsten schlägt der Spruch fehl */ - } else if (sp->components[k].cost == SPC_LINEAR) { - costtyp = SPC_LINEAR; - if (maxlevel < cast_level) - cast_level = 0; - } + /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden + * sein und der cast_level ändert sich nicht */ + if (sp->components[k].cost == SPC_FIX) { + if (maxlevel < 1) + cast_level = 0; + /* ansonsten wird das Minimum aus maximal möglicher Stufe und der + * gewünschten gebildet */ + } + else if (sp->components[k].cost == SPC_LEVEL) { + costtyp = SPC_LEVEL; + cast_level = _min(cast_level, maxlevel); + /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden + * sein, ansonsten schlägt der Spruch fehl */ + } + else if (sp->components[k].cost == SPC_LINEAR) { + costtyp = SPC_LINEAR; + if (maxlevel < cast_level) + cast_level = 0; + } + } } - } - /* Ein Spruch mit Fixkosten wird immer mit der Stufe des Spruchs und - * nicht auf der Stufe des Magiers gezaubert */ - if (costtyp == SPC_FIX) { - spellbook * spells = unit_get_spellbook(u); - if (spells) { - spellbook_entry * sbe = spellbook_get(spells, sp); - if (sbe) { - return _min(cast_level, sbe->level); - } + /* Ein Spruch mit Fixkosten wird immer mit der Stufe des Spruchs und + * nicht auf der Stufe des Magiers gezaubert */ + if (costtyp == SPC_FIX) { + spellbook * spells = unit_get_spellbook(u); + if (spells) { + spellbook_entry * sbe = spellbook_get(spells, sp); + if (sbe) { + return _min(cast_level, sbe->level); + } + } + log_error("spell %s is not in the spellbook for %s\n", sp->sname, unitname(u)); } - log_error("spell %s is not in the spellbook for %s\n", sp->sname, unitname(u)); - } - return cast_level; + return cast_level; } /* ------------------------------------------------------------- */ @@ -896,21 +910,22 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) int k; int resuse; - assert(cast_level>0); - for (k = 0; sp->components[k].type; k++) { - if (sp->components[k].type == r_aura) { - resuse = spellcost(u, sp) * range; - } else { - resuse = sp->components[k].amount * range; - } + assert(cast_level > 0); + for (k = 0; sp->components[k].type; k++) { + if (sp->components[k].type == r_aura) { + resuse = spellcost(u, sp) * range; + } + else { + resuse = sp->components[k].amount * range; + } - if (sp->components[k].cost == SPC_LINEAR - || sp->components[k].cost == SPC_LEVEL) { - resuse *= cast_level; - } + if (sp->components[k].cost == SPC_LINEAR + || sp->components[k].cost == SPC_LEVEL) { + resuse *= cast_level; + } - use_pooled(u, sp->components[k].type, GET_DEFAULT, resuse); - } + use_pooled(u, sp->components[k].type, GET_DEFAULT, resuse); + } } /* ------------------------------------------------------------- */ @@ -921,12 +936,12 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) */ bool knowsspell(const region * r, const unit * u, const spell * sp) { - /* Ist überhaupt ein gültiger Spruch angegeben? */ - if (!sp || sp->id == 0) { - return false; - } - /* steht der Spruch in der Spruchliste? */ - return u_hasspell(u, sp)!=0; + /* Ist überhaupt ein gültiger Spruch angegeben? */ + if (!sp || sp->id == 0) { + return false; + } + /* steht der Spruch in der Spruchliste? */ + return u_hasspell(u, sp) != 0; } /* Um einen Spruch zu beherrschen, muss der Magier die Stufe des @@ -944,59 +959,60 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) int itemanz; resource *reslist = NULL; - if (!knowsspell(u->region, u, sp)) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, ord, 173, MSG_MAGIC); - return false; - } - /* reicht die Stufe aus? */ - if (eff_skill(u, SK_MAGIC, u->region) < level) { - /* die Einheit ist nicht erfahren genug für diesen Zauber */ - cmistake(u, ord, 169, MSG_MAGIC); - return false; - } - - for (k = 0; sp->components[k].type; ++k) { - if (sp->components[k].amount > 0) { - const resource_type *rtype = sp->components[k].type; - int itemhave; - - /* Die Kosten für Aura sind auch von der Zahl der bereits - * gezauberten Sprüche abhängig */ - if (rtype == r_aura) { - itemanz = spellcost(u, sp) * range; - } else { - itemanz = sp->components[k].amount * range; - } - - /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem - * level multipliziert werden */ - switch (sp->components[k].cost) { - case SPC_LEVEL: - case SPC_LINEAR: - itemanz *= level; - break; - case SPC_FIX: - default: - break; - } - - itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); - if (itemhave < itemanz) { - resource *res = malloc(sizeof(resource)); - res->number = itemanz - itemhave; - res->type = rtype; - res->next = reslist; - reslist = res; - } + if (!knowsspell(u->region, u, sp)) { + /* Diesen Zauber kennt die Einheit nicht */ + cmistake(u, ord, 173, MSG_MAGIC); + return false; } - } - if (reslist != NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "missing_components_list", - "list", reslist)); - return false; - } - return true; + /* reicht die Stufe aus? */ + if (eff_skill(u, SK_MAGIC, u->region) < level) { + /* die Einheit ist nicht erfahren genug für diesen Zauber */ + cmistake(u, ord, 169, MSG_MAGIC); + return false; + } + + for (k = 0; sp->components[k].type; ++k) { + if (sp->components[k].amount > 0) { + const resource_type *rtype = sp->components[k].type; + int itemhave; + + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ + if (rtype == r_aura) { + itemanz = spellcost(u, sp) * range; + } + else { + itemanz = sp->components[k].amount * range; + } + + /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem + * level multipliziert werden */ + switch (sp->components[k].cost) { + case SPC_LEVEL: + case SPC_LINEAR: + itemanz *= level; + break; + case SPC_FIX: + default: + break; + } + + itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); + if (itemhave < itemanz) { + resource *res = malloc(sizeof(resource)); + res->number = itemanz - itemhave; + res->type = rtype; + res->next = reslist; + reslist = res; + } + } + } + if (reslist != NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "missing_components_list", + "list", reslist)); + return false; + } + return true; } /* ------------------------------------------------------------- */ @@ -1020,7 +1036,8 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order if (sp == NULL) { return 0; - } else { + } + else { /* Bonus durch Magieturm und gesegneten Steinkreis */ struct building *b = inside_building(u); const struct building_type *btype = b ? b->type : NULL; @@ -1037,45 +1054,47 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order ++force; } - /* Antimagie in der Zielregion */ - c = get_curse(r->attribs, ct_find("antimagiczone")); - if (curse_active(c)) { - unit *mage = c->magician; - force -= curse_geteffect(c); - curse_changevigour(&r->attribs, c, (float)-cast_level); - cmistake(u, ord, 185, MSG_MAGIC); - if (mage != NULL && mage->faction != NULL) { - if (force > 0) { - ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", - "self mage region", mage, u, r)); - } else { - ADDMSG(&mage->faction->msgs, msg_message("block_spell", - "self mage region", mage, u, r)); - } + /* Antimagie in der Zielregion */ + c = get_curse(r->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + unit *mage = c->magician; + force -= curse_geteffect(c); + curse_changevigour(&r->attribs, c, (float)-cast_level); + cmistake(u, ord, 185, MSG_MAGIC); + if (mage != NULL && mage->faction != NULL) { + if (force > 0) { + ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", + "self mage region", mage, u, r)); + } + else { + ADDMSG(&mage->faction->msgs, msg_message("block_spell", + "self mage region", mage, u, r)); + } + } } - } - /* Patzerfluch-Effekt: */ - c = get_curse(r->attribs, ct_find("fumble")); - if (curse_active(c)) { - unit *mage = c->magician; - force -= curse_geteffect(c); - curse_changevigour(&u->attribs, c, -1); - cmistake(u, ord, 185, MSG_MAGIC); - if (mage != NULL && mage->faction != NULL) { - if (force > 0) { - ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", - "self mage region", mage, u, r)); - } else { - ADDMSG(&mage->faction->msgs, msg_message("block_spell", - "self mage region", mage, u, r)); - } + /* Patzerfluch-Effekt: */ + c = get_curse(r->attribs, ct_find("fumble")); + if (curse_active(c)) { + unit *mage = c->magician; + force -= curse_geteffect(c); + curse_changevigour(&u->attribs, c, -1); + cmistake(u, ord, 185, MSG_MAGIC); + if (mage != NULL && mage->faction != NULL) { + if (force > 0) { + ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", + "self mage region", mage, u, r)); + } + else { + ADDMSG(&mage->faction->msgs, msg_message("block_spell", + "self mage region", mage, u, r)); + } + } } - } - force = force * MagicPower(); + force = force * MagicPower(); - return _max(force, 0); + return _max(force, 0); } /* ------------------------------------------------------------- */ @@ -1083,25 +1102,25 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order * rechnen kann */ static int farcasting(unit * magician, region * r) { - int dist; - int mult; + int dist; + int mult; - if (!r) { - return INT_MAX; - } + if (!r) { + return INT_MAX; + } - dist = koor_distance(r->x, r->y, magician->region->x, magician->region->y); + dist = koor_distance(r->x, r->y, magician->region->x, magician->region->y); - if (dist > 24) - return INT_MAX; + if (dist > 24) + return INT_MAX; - mult = 1 << dist; - if (dist > 1) { - if (!path_exists(magician->region, r, dist * 2, allowed_fly)) - mult = INT_MAX; - } + mult = 1 << dist; + if (dist > 1) { + if (!path_exists(magician->region, r, dist * 2, allowed_fly)) + mult = INT_MAX; + } - return mult; + return mult; } /* ------------------------------------------------------------- */ @@ -1115,7 +1134,7 @@ double magic_resistance(unit * target) attrib *a; curse *c; int n; - const curse_type * ct_goodresist = 0, * ct_badresist = 0; + const curse_type * ct_goodresist = 0, *ct_badresist = 0; const resource_type *rtype; double probability = u_race(target)->magres; @@ -1135,7 +1154,7 @@ double magic_resistance(unit * target) if (n) { probability += n * 0.1 / target->number; } - + /* Auswirkungen von Zaubern auf der Region */ a = a_find(target->region->attribs, &at_curse); if (a) { @@ -1143,16 +1162,17 @@ double magic_resistance(unit * target) ct_goodresist = ct_find("goodmagicresistancezone"); } while (a && a->type == &at_curse) { - curse *c = (curse *) a->data.v; + curse *c = (curse *)a->data.v; unit *mage = c->magician; - + if (mage != NULL) { if (ct_goodresist && c->type == ct_goodresist) { if (alliedunit(mage, target->faction, HELP_GUARD)) { probability += curse_geteffect(c) * 0.01; ct_goodresist = 0; /* only one effect per region */ } - } else if (ct_badresist && c->type == ct_badresist) { + } + else if (ct_badresist && c->type == ct_badresist) { if (!alliedunit(mage, target->faction, HELP_GUARD)) { probability -= curse_geteffect(c) * 0.01; ct_badresist = 0; /* only one effect per region */ @@ -1163,12 +1183,12 @@ double magic_resistance(unit * target) } /* Bonus durch Artefakte */ /* TODO (noch gibs keine) */ - + /* Bonus durch Gebäude */ { struct building *b = inside_building(target); const struct building_type *btype = b ? b->type : NULL; - + /* gesegneter Steinkreis gibt 30% dazu */ if (btype) probability += btype->magresbonus * 0.01; @@ -1190,73 +1210,73 @@ double magic_resistance(unit * target) bool target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus) { - double probability = 0.0; + double probability = 0.0; - if (magician == NULL) - return true; - if (obj == NULL) - return true; + if (magician == NULL) + return true; + if (obj == NULL) + return true; - switch (objtyp) { - case TYP_UNIT: - { - int at, pa = 0; - skill *sv; - unit *u = (unit *) obj; + switch (objtyp) { + case TYP_UNIT: + { + int at, pa = 0; + skill *sv; + unit *u = (unit *)obj; - at = effskill(magician, SK_MAGIC); + at = effskill(magician, SK_MAGIC); - for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { - int sk = effskill(u, sv->id); - if (pa < sk) - pa = sk; + for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { + int sk = effskill(u, sv->id); + if (pa < sk) + pa = sk; + } + + /* Contest */ + probability = 0.05 * (10 + pa - at); + + probability += magic_resistance((unit *)obj); + break; } - /* Contest */ - probability = 0.05 * (10 + pa - at); + case TYP_REGION: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((region *)obj)->attribs, C_RESIST_MAGIC, 0); + break; - probability += magic_resistance((unit *) obj); - break; - } + case TYP_BUILDING: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((building *)obj)->attribs, C_RESIST_MAGIC, 0); - case TYP_REGION: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((region *) obj)->attribs, C_RESIST_MAGIC, 0); - break; + /* Bonus durch Typ */ + probability += 0.01 * ((building *)obj)->type->magres; - case TYP_BUILDING: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((building *) obj)->attribs, C_RESIST_MAGIC, 0); + break; - /* Bonus durch Typ */ - probability += 0.01 * ((building *) obj)->type->magres; + case TYP_SHIP: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((ship *)obj)->attribs, C_RESIST_MAGIC, 0); + break; + } - break; + probability = _max(0.02, probability + t_bonus * 0.01); + probability = _min(0.98, probability); - case TYP_SHIP: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((ship *) obj)->attribs, C_RESIST_MAGIC, 0); - break; - } - - probability = _max(0.02, probability + t_bonus * 0.01); - probability = _min(0.98, probability); - - /* gibt true, wenn die Zufallszahl kleiner als die chance ist und - * false, wenn sie gleich oder größer ist, dh je größer die - * Magieresistenz (chance) desto eher gibt die Funktion true zurück */ - return chance(probability); + /* gibt true, wenn die Zufallszahl kleiner als die chance ist und + * false, wenn sie gleich oder größer ist, dh je größer die + * Magieresistenz (chance) desto eher gibt die Funktion true zurück */ + return chance(probability); } /* ------------------------------------------------------------- */ bool is_magic_resistant(unit * magician, unit * target, int resist_bonus) { - return (bool) target_resists_magic(magician, target, TYP_UNIT, - resist_bonus); + return (bool)target_resists_magic(magician, target, TYP_UNIT, + resist_bonus); } /* ------------------------------------------------------------- */ @@ -1272,46 +1292,46 @@ bool is_magic_resistant(unit * magician, unit * target, int resist_bonus) bool fumble(region * r, unit * u, const spell * sp, int cast_grade) { -/* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. - * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch - * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit - * 20% Warscheinlichkeit nicht - * */ + /* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. + * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch + * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit + * 20% Warscheinlichkeit nicht + * */ - int rnd = 0; - double x = (double)cast_grade / (double)eff_skill(u, SK_MAGIC, r); - int fumble_chance = (int)(((double)x * 40.0) - 20.0); - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - int fumble_enabled = get_param_int(global.parameters, "magic.fumble.enable", 1); - sc_mage * mage; + int rnd = 0; + double x = (double)cast_grade / (double)eff_skill(u, SK_MAGIC, r); + int fumble_chance = (int)(((double)x * 40.0) - 20.0); + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + int fumble_enabled = get_param_int(global.parameters, "magic.fumble.enable", 1); + sc_mage * mage; - if (!fumble_enabled) { - return false; - } - if (btype) - fumble_chance -= btype->fumblebonus; + if (!fumble_enabled) { + return false; + } + if (btype) + fumble_chance -= btype->fumblebonus; - /* CHAOSPATZERCHANCE 10 : +10% Chance zu Patzern */ - mage = get_mage(u); - if (mage->magietyp == M_DRAIG) { - fumble_chance += CHAOSPATZERCHANCE; - } - if (is_cursed(u->attribs, C_MBOOST, 0)) { - fumble_chance += CHAOSPATZERCHANCE; - } - if (is_cursed(u->attribs, C_FUMBLE, 0)) { - fumble_chance += CHAOSPATZERCHANCE; - } + /* CHAOSPATZERCHANCE 10 : +10% Chance zu Patzern */ + mage = get_mage(u); + if (mage->magietyp == M_DRAIG) { + fumble_chance += CHAOSPATZERCHANCE; + } + if (is_cursed(u->attribs, C_MBOOST, 0)) { + fumble_chance += CHAOSPATZERCHANCE; + } + if (is_cursed(u->attribs, C_FUMBLE, 0)) { + fumble_chance += CHAOSPATZERCHANCE; + } - /* wenn die Chance kleiner als 0 ist, können wir gleich false - * zurückgeben */ - if (fumble_chance <= 0) { - return false; - } - rnd = rng_int() % 100; + /* wenn die Chance kleiner als 0 ist, können wir gleich false + * zurückgeben */ + if (fumble_chance <= 0) { + return false; + } + rnd = rng_int() % 100; - return (rnd <= fumble_chance); + return (rnd <= fumble_chance); } /* ------------------------------------------------------------- */ @@ -1319,11 +1339,11 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) * zugeschnittene Patzer */ static void fumble_default(castorder * co) { - unit *mage = co->magician.u; + unit *mage = co->magician.u; - cmistake(mage, co->order, 180, MSG_MAGIC); + cmistake(mage, co->order, 180, MSG_MAGIC); - return; + return; } /* Die normalen Spruchkosten müssen immer bezahlt werden, hier noch @@ -1339,50 +1359,50 @@ static void do_fumble(castorder * co) int level = co->level; int duration; float effect; - - ADDMSG(&u->faction->msgs, - msg_message("patzer", "unit region spell", u, r, sp)); + + ADDMSG(&u->faction->msgs, + msg_message("patzer", "unit region spell", u, r, sp)); switch (rng_int() % 10) { case 0: /* wenn vorhanden spezieller Patzer, ansonsten nix */ if (sp->fumble) { sp->fumble(co); - } + } else { fumble_default(co); } break; - + case 1: /* toad */ - { - /* one or two things will happen: the toad changes her race back, - * and may or may not get toadslime. - * The list of things to happen are attached to a timeout - * trigger and that's added to the triggerlit of the mage gone toad. - */ - trigger *trestore = trigger_changerace(u, u_race(u), u->irace); - if (chance(0.7)) { - const resource_type *rtype = rt_find("toadslime"); - if (rtype) { - t_add(&trestore, trigger_giveitem(u, rtype->itype, 1)); - } + { + /* one or two things will happen: the toad changes her race back, + * and may or may not get toadslime. + * The list of things to happen are attached to a timeout + * trigger and that's added to the triggerlit of the mage gone toad. + */ + trigger *trestore = trigger_changerace(u, u_race(u), u->irace); + if (chance(0.7)) { + const resource_type *rtype = rt_find("toadslime"); + if (rtype) { + t_add(&trestore, trigger_giveitem(u, rtype->itype, 1)); } - duration = rng_int() % level / 2; - if (duration < 2) duration = 2; - add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); - u_setrace(u, get_race(RC_TOAD)); - u->irace = NULL; - ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", u, r, sp)); - break; } + duration = rng_int() % level / 2; + if (duration < 2) duration = 2; + add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); + u_setrace(u, get_race(RC_TOAD)); + u->irace = NULL; + ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", u, r, sp)); + break; + } /* fall-through is intentional! */ - + case 2: /* temporary skill loss */ duration = _max(rng_int() % level / 2, 2); - effect = -(float)level/2; + effect = -(float)level / 2; c = create_curse(u, &u->attribs, ct_find("skillmod"), (float)level, - duration, effect, 1); + duration, effect, 1); c->data.i = SK_MAGIC; ADDMSG(&u->faction->msgs, msg_message("patzer2", "unit region", u, r)); break; @@ -1391,18 +1411,18 @@ static void do_fumble(castorder * co) /* Spruch schlägt fehl, alle Magiepunkte weg */ set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer3", "unit region spell", - u, r, sp)); + u, r, sp)); break; - + case 5: case 6: /* Spruch gelingt, aber alle Magiepunkte weg */ co->level = sp->cast(co); set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer4", "unit region spell", - u, r, sp)); + u, r, sp)); break; - + case 7: case 8: case 9: @@ -1410,7 +1430,7 @@ static void do_fumble(castorder * co) /* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */ co->level = sp->cast(co); ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell", - u, r, sp)); + u, r, sp)); countspells(u, 3); } } @@ -1424,183 +1444,184 @@ static void do_fumble(castorder * co) */ static double regeneration(unit * u) { - int sk; - double aura, d; - double potenz = 1.5; - double divisor = 2.0; + int sk; + double aura, d; + double potenz = 1.5; + double divisor = 2.0; - sk = effskill(u, SK_MAGIC); - /* Rassenbonus/-malus */ - d = pow(sk, potenz) * u_race(u)->regaura / divisor; - d++; + sk = effskill(u, SK_MAGIC); + /* Rassenbonus/-malus */ + d = pow(sk, potenz) * u_race(u)->regaura / divisor; + d++; - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ - /* Würfeln */ - aura = (rng_double() * d + rng_double() * d) / 2 + 1; + /* Würfeln */ + aura = (rng_double() * d + rng_double() * d) / 2 + 1; - aura *= MagicRegeneration(); + aura *= MagicRegeneration(); - return aura; + return aura; } void regenerate_aura(void) { - region *r; - unit *u; - int aura, auramax; - double reg_aura; - int regen; - double mod; - int regen_enabled = get_param_int(global.parameters, "magic.regeneration.enable", 1); + region *r; + unit *u; + int aura, auramax; + double reg_aura; + int regen; + double mod; + int regen_enabled = get_param_int(global.parameters, "magic.regeneration.enable", 1); - if (!regen_enabled) return; + if (!regen_enabled) return; - for (r = regions; r; r = r->next) { - for (u = r->units; u; u = u->next) { - if (u->number && is_mage(u)) { - aura = get_spellpoints(u); - auramax = max_spellpoints(r, u); - if (aura < auramax) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - reg_aura = regeneration(u); + for (r = regions; r; r = r->next) { + for (u = r->units; u; u = u->next) { + if (u->number && is_mage(u)) { + aura = get_spellpoints(u); + auramax = max_spellpoints(r, u); + if (aura < auramax) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + reg_aura = regeneration(u); - /* Magierturm erhöht die Regeneration um 75% */ - /* Steinkreis erhöht die Regeneration um 50% */ - if (btype) - reg_aura *= btype->auraregen; + /* Magierturm erhöht die Regeneration um 75% */ + /* Steinkreis erhöht die Regeneration um 50% */ + if (btype) + reg_aura *= btype->auraregen; - /* Bonus/Malus durch Zauber */ - mod = get_curseeffect(u->attribs, C_AURA, 0); - if (mod > 0) { - reg_aura = (reg_aura * mod) / 100.0; - } + /* Bonus/Malus durch Zauber */ + mod = get_curseeffect(u->attribs, C_AURA, 0); + if (mod > 0) { + reg_aura = (reg_aura * mod) / 100.0; + } - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ - /* maximal Differenz bis Maximale-Aura regenerieren - * mindestens 1 Aura pro Monat */ - regen = (int)reg_aura; - reg_aura -= regen; - if (chance(reg_aura)) - ++regen; - regen = _max(1, regen); - regen = _min((auramax - aura), regen); + /* maximal Differenz bis Maximale-Aura regenerieren + * mindestens 1 Aura pro Monat */ + regen = (int)reg_aura; + reg_aura -= regen; + if (chance(reg_aura)) + ++regen; + regen = _max(1, regen); + regen = _min((auramax - aura), regen); - aura += regen; - ADDMSG(&u->faction->msgs, msg_message("regenaura", - "unit region amount", u, r, regen)); + aura += regen; + ADDMSG(&u->faction->msgs, msg_message("regenaura", + "unit region amount", u, r, regen)); + } + set_spellpoints(u, _min(aura, auramax)); + } } - set_spellpoints(u, _min(aura, auramax)); - } } - } } static bool verify_ship(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - ship *sh = findship(spobj->data.i); + ship *sh = findship(spobj->data.i); - if (sh != NULL && sh->region != r && (sp->sptyp & SEARCHLOCAL)) { - /* Burg muss in gleicher Region sein */ - sh = NULL; - } + if (sh != NULL && sh->region != r && (sp->sptyp & SEARCHLOCAL)) { + /* Burg muss in gleicher Region sein */ + sh = NULL; + } - if (sh == NULL) { - /* Burg nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_message("spellshipnotfound", - "unit region command id", mage, mage->region, ord, spobj->data.i)); - return false; - } - spobj->flag = 0; - spobj->data.sh = sh; - return true; + if (sh == NULL) { + /* Burg nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_message("spellshipnotfound", + "unit region command id", mage, mage->region, ord, spobj->data.i)); + return false; + } + spobj->flag = 0; + spobj->data.sh = sh; + return true; } static bool verify_building(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - building *b = findbuilding(spobj->data.i); + building *b = findbuilding(spobj->data.i); - if (b != NULL && b->region != r && (sp->sptyp & SEARCHLOCAL)) { - /* Burg muss in gleicher Region sein */ - b = NULL; - } + if (b != NULL && b->region != r && (sp->sptyp & SEARCHLOCAL)) { + /* Burg muss in gleicher Region sein */ + b = NULL; + } - if (b == NULL) { - /* Burg nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_message("spellbuildingnotfound", - "unit region command id", mage, mage->region, ord, spobj->data.i)); - return false; - } - spobj->flag = 0; - spobj->data.b = b; - return true; + if (b == NULL) { + /* Burg nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_message("spellbuildingnotfound", + "unit region command id", mage, mage->region, ord, spobj->data.i)); + return false; + } + spobj->flag = 0; + spobj->data.b = b; + return true; } message *msg_unitnotfound(const struct unit * mage, struct order * ord, - const struct spllprm * spobj) + const struct spllprm * spobj) { - /* Einheit nicht gefunden */ - char tbuf[20]; - const char *uid; + /* Einheit nicht gefunden */ + char tbuf[20]; + const char *uid; - if (spobj->typ == SPP_UNIT) { - uid = itoa36(spobj->data.i); - } else { - sprintf(tbuf, "%s %s", LOC(mage->faction->locale, - parameters[P_TEMP]), itoa36(spobj->data.i)); - uid = tbuf; - } - return msg_message("unitnotfound_id", - "unit region command id", mage, mage->region, ord, uid); + if (spobj->typ == SPP_UNIT) { + uid = itoa36(spobj->data.i); + } + else { + sprintf(tbuf, "%s %s", LOC(mage->faction->locale, + parameters[P_TEMP]), itoa36(spobj->data.i)); + uid = tbuf; + } + return msg_message("unitnotfound_id", + "unit region command id", mage, mage->region, ord, uid); } static bool verify_unit(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - unit *u = NULL; - switch (spobj->typ) { - case SPP_UNIT: - u = findunit(spobj->data.i); - break; - case SPP_TEMP: - u = findnewunit(r, mage->faction, spobj->data.i); - if (u == NULL) - u = findnewunit(mage->region, mage->faction, spobj->data.i); - break; - default: - assert(!"shouldn't happen, this"); - } - if (u != NULL && (sp->sptyp & SEARCHLOCAL)) { - if (u->region != r) - u = NULL; - else if (sp->sptyp & TESTCANSEE) { - if (!cansee(mage->faction, r, u, 0) && !ucontact(u, mage)) { - u = NULL; - } + unit *u = NULL; + switch (spobj->typ) { + case SPP_UNIT: + u = findunit(spobj->data.i); + break; + case SPP_TEMP: + u = findnewunit(r, mage->faction, spobj->data.i); + if (u == NULL) + u = findnewunit(mage->region, mage->faction, spobj->data.i); + break; + default: + assert(!"shouldn't happen, this"); + } + if (u != NULL && (sp->sptyp & SEARCHLOCAL)) { + if (u->region != r) + u = NULL; + else if (sp->sptyp & TESTCANSEE) { + if (!cansee(mage->faction, r, u, 0) && !ucontact(u, mage)) { + u = NULL; + } + } } - } - if (u == NULL) { - /* Einheit nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_unitnotfound(mage, ord, spobj)); - return false; - } - /* Einheit wurde gefunden, pointer setzen */ - spobj->flag = 0; - spobj->data.u = u; - return true; + if (u == NULL) { + /* Einheit nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_unitnotfound(mage, ord, spobj)); + return false; + } + /* Einheit wurde gefunden, pointer setzen */ + spobj->flag = 0; + spobj->data.u = u; + return true; } /* ------------------------------------------------------------- */ @@ -1617,160 +1638,164 @@ verify_unit(region * r, unit * mage, const spell * sp, spllprm * spobj, static void verify_targets(castorder * co, int *invalid, int *resist, int *success) { - unit *mage = co->magician.u; - const spell *sp = co->sp; - region *target_r = co_get_region(co); - spellparameter *sa = co->par; - int i; + unit *mage = co->magician.u; + const spell *sp = co->sp; + region *target_r = co_get_region(co); + spellparameter *sa = co->par; + int i; - *invalid = 0; - *resist = 0; - *success = 0; + *invalid = 0; + *resist = 0; + *success = 0; - if (sa && sa->length) { - /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. - * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber - * gar nicht global hätte suchen dürften, setzen wir das Objekt - * zurück. */ - for (i = 0; i < sa->length; i++) { - spllprm *spobj = sa->param[i]; + if (sa && sa->length) { + /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. + * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber + * gar nicht global hätte suchen dürften, setzen wir das Objekt + * zurück. */ + for (i = 0; i < sa->length; i++) { + spllprm *spobj = sa->param[i]; - switch (spobj->typ) { - case SPP_TEMP: - case SPP_UNIT: - if (!verify_unit(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - case SPP_BUILDING: - if (!verify_building(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - case SPP_SHIP: - if (!verify_ship(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - default: - break; - } + switch (spobj->typ) { + case SPP_TEMP: + case SPP_UNIT: + if (!verify_unit(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + case SPP_BUILDING: + if (!verify_building(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + case SPP_SHIP: + if (!verify_ship(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + default: + break; + } + } + + /* Nun folgen die Tests auf cansee und Magieresistenz */ + for (i = 0; i < sa->length; i++) { + spllprm *spobj = sa->param[i]; + unit *u; + building *b; + ship *sh; + region *tr; + + if (spobj->flag == TARGET_NOTFOUND) + continue; + switch (spobj->typ) { + case SPP_TEMP: + case SPP_UNIT: + u = spobj->data.u; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, u, TYP_UNIT, 0)) { + /* Fehlermeldung */ + spobj->data.i = u->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellunitresists", + "unit region command target", mage, mage->region, co->order, u)); + break; + } + + /* TODO: Test auf Parteieigenschaft Magieresistsenz */ + ++*success; + break; + case SPP_BUILDING: + b = spobj->data.b; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, b, TYP_BUILDING, 0)) { /* Fehlermeldung */ + spobj->data.i = b->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellbuildingresists", + "unit region command id", + mage, mage->region, co->order, spobj->data.i)); + break; + } + ++*success; + break; + case SPP_SHIP: + sh = spobj->data.sh; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, sh, TYP_SHIP, 0)) { /* Fehlermeldung */ + spobj->data.i = sh->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, + "spellshipresists", "ship", sh)); + break; + } + ++*success; + break; + + case SPP_REGION: + /* haben wir ein Regionsobjekt, dann wird auch dieses und + nicht target_r überprüft. */ + tr = spobj->data.r; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, tr, TYP_REGION, 0)) { /* Fehlermeldung */ + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", + "unit region command", mage, mage->region, co->order)); + break; + } + ++*success; + break; + case SPP_INT: + case SPP_STRING: + ++*success; + break; + + default: + break; + } + } } + else { + /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich + * aber um einen Regionszauber handeln. Wenn notwendig hier die + * Magieresistenz der Region prüfen. */ + if ((sp->sptyp & REGIONSPELL)) { + /* Zielobjekt Region anlegen */ + spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = target_r; - /* Nun folgen die Tests auf cansee und Magieresistenz */ - for (i = 0; i < sa->length; i++) { - spllprm *spobj = sa->param[i]; - unit *u; - building *b; - ship *sh; - region *tr; + sa = calloc(1, sizeof(spellparameter)); + sa->length = 1; + sa->param = calloc(sa->length, sizeof(spllprm *)); + sa->param[0] = spobj; + co->par = sa; - if (spobj->flag == TARGET_NOTFOUND) - continue; - switch (spobj->typ) { - case SPP_TEMP: - case SPP_UNIT: - u = spobj->data.u; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, u, TYP_UNIT, 0)) { - /* Fehlermeldung */ - spobj->data.i = u->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellunitresists", - "unit region command target", mage, mage->region, co->order, u)); - break; + if ((sp->sptyp & TESTRESISTANCE)) { + if (target_resists_magic(mage, target_r, TYP_REGION, 0)) { + /* Fehlermeldung */ + ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", + "unit region command", mage, mage->region, co->order)); + spobj->flag = TARGET_RESISTS; + ++*resist; + } + else { + ++*success; + } + } + else { + ++*success; + } } - - /* TODO: Test auf Parteieigenschaft Magieresistsenz */ - ++*success; - break; - case SPP_BUILDING: - b = spobj->data.b; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, b, TYP_BUILDING, 0)) { /* Fehlermeldung */ - spobj->data.i = b->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellbuildingresists", - "unit region command id", - mage, mage->region, co->order, spobj->data.i)); - break; + else { + ++*success; } - ++*success; - break; - case SPP_SHIP: - sh = spobj->data.sh; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, sh, TYP_SHIP, 0)) { /* Fehlermeldung */ - spobj->data.i = sh->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, - "spellshipresists", "ship", sh)); - break; - } - ++*success; - break; - - case SPP_REGION: - /* haben wir ein Regionsobjekt, dann wird auch dieses und - nicht target_r überprüft. */ - tr = spobj->data.r; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, tr, TYP_REGION, 0)) { /* Fehlermeldung */ - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", - "unit region command", mage, mage->region, co->order)); - break; - } - ++*success; - break; - case SPP_INT: - case SPP_STRING: - ++*success; - break; - - default: - break; - } } - } else { - /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich - * aber um einen Regionszauber handeln. Wenn notwendig hier die - * Magieresistenz der Region prüfen. */ - if ((sp->sptyp & REGIONSPELL)) { - /* Zielobjekt Region anlegen */ - spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = target_r; - - sa = calloc(1, sizeof(spellparameter)); - sa->length = 1; - sa->param = calloc(sa->length, sizeof(spllprm *)); - sa->param[0] = spobj; - co->par = sa; - - if ((sp->sptyp & TESTRESISTANCE)) { - if (target_resists_magic(mage, target_r, TYP_REGION, 0)) { - /* Fehlermeldung */ - ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", - "unit region command", mage, mage->region, co->order)); - spobj->flag = TARGET_RESISTS; - ++*resist; - } else { - ++*success; - } - } else { - ++*success; - } - } else { - ++*success; - } - } } /* ------------------------------------------------------------- */ @@ -1779,331 +1804,333 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) static void free_spellparameter(spellparameter * pa) { - int i; + int i; - /* Elemente free'en */ - for (i = 0; i < pa->length; i++) { + /* Elemente free'en */ + for (i = 0; i < pa->length; i++) { - switch (pa->param[i]->typ) { - case SPP_STRING: - free(pa->param[i]->data.s); - break; - default: - break; + switch (pa->param[i]->typ) { + case SPP_STRING: + free(pa->param[i]->data.s); + break; + default: + break; + } + free(pa->param[i]); } - free(pa->param[i]); - } - if (pa->param) - free(pa->param); - /* struct free'en */ - free(pa); + if (pa->param) + free(pa->param); + /* struct free'en */ + free(pa); } static int addparam_string(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - assert(param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + assert(param[0]); - spobj->flag = 0; - spobj->typ = SPP_STRING; - spobj->data.xs = _strdup(param[0]); - return 1; + spobj->flag = 0; + spobj->typ = SPP_STRING; + spobj->data.xs = _strdup(param[0]); + return 1; } static int addparam_int(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - assert(param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + assert(param[0]); - spobj->flag = 0; - spobj->typ = SPP_INT; - spobj->data.i = atoi((char *)param[0]); - return 1; + spobj->flag = 0; + spobj->typ = SPP_INT; + spobj->data.i = atoi((char *)param[0]); + return 1; } static int addparam_ship(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - int id = atoi36((const char *)param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + int id = atoi36((const char *)param[0]); - spobj->flag = 0; - spobj->typ = SPP_SHIP; - spobj->data.i = id; - return 1; + spobj->flag = 0; + spobj->typ = SPP_SHIP; + spobj->data.i = id; + return 1; } static int addparam_building(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - int id = atoi36((const char *)param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + int id = atoi36((const char *)param[0]); - spobj->flag = 0; - spobj->typ = SPP_BUILDING; - spobj->data.i = id; - return 1; + spobj->flag = 0; + spobj->typ = SPP_BUILDING; + spobj->data.i = id; + return 1; } static int addparam_region(const char *const param[], spllprm ** spobjp, const unit * u, - order * ord, plane * pl) +order * ord, plane * pl) { - assert(param[0]); - if (param[1] == 0) { - /* Fehler: Zielregion vergessen */ - cmistake(u, ord, 194, MSG_MAGIC); - return -1; - } else { - int tx = atoi((const char *)param[0]), ty = atoi((const char *)param[1]); - int x = rel_to_abs(pl, u->faction, tx, 0); - int y = rel_to_abs(pl, u->faction, ty, 1); - region *rt; - - pnormalize(&x, &y, pl); - rt = findregion(x, y); - - if (rt != NULL) { - spllprm *spobj = *spobjp = (spllprm *)malloc(sizeof(spllprm)); - - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = rt; - } else { - /* Fehler: Zielregion vergessen */ - cmistake(u, ord, 194, MSG_MAGIC); - return -1; + assert(param[0]); + if (param[1] == 0) { + /* Fehler: Zielregion vergessen */ + cmistake(u, ord, 194, MSG_MAGIC); + return -1; + } + else { + int tx = atoi((const char *)param[0]), ty = atoi((const char *)param[1]); + int x = rel_to_abs(pl, u->faction, tx, 0); + int y = rel_to_abs(pl, u->faction, ty, 1); + region *rt; + + pnormalize(&x, &y, pl); + rt = findregion(x, y); + + if (rt != NULL) { + spllprm *spobj = *spobjp = (spllprm *)malloc(sizeof(spllprm)); + + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = rt; + } + else { + /* Fehler: Zielregion vergessen */ + cmistake(u, ord, 194, MSG_MAGIC); + return -1; + } + return 2; } - return 2; - } } static int addparam_unit(const char *const param[], spllprm ** spobjp, const unit * u, - order * ord) +order * ord) { - spllprm *spobj; - int i = 0; - sppobj_t otype = SPP_UNIT; + spllprm *spobj; + int i = 0; + sppobj_t otype = SPP_UNIT; - *spobjp = NULL; - if (isparam(param[0], u->faction->locale, P_TEMP)) { - if (param[1] == NULL) { - /* Fehler: Ziel vergessen */ - cmistake(u, ord, 203, MSG_MAGIC); - return -1; + *spobjp = NULL; + if (isparam(param[0], u->faction->locale, P_TEMP)) { + if (param[1] == NULL) { + /* Fehler: Ziel vergessen */ + cmistake(u, ord, 203, MSG_MAGIC); + return -1; + } + ++i; + otype = SPP_TEMP; } - ++i; - otype = SPP_TEMP; - } - spobj = *spobjp = malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = otype; - spobj->data.i = atoi36((const char *)param[i]); + spobj = *spobjp = malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = otype; + spobj->data.i = atoi36((const char *)param[i]); - return i + 1; + return i + 1; } static spellparameter *add_spellparameter(region * target_r, unit * u, - const char *syntax, const char *const param[], int size, struct order *ord) + const char *syntax, const char *const param[], int size, struct order *ord) { - bool fail = false; - int i = 0; - int p = 0; - const char *c; - spellparameter *par; - int minlen = 0; + bool fail = false; + int i = 0; + int p = 0; + const char *c; + spellparameter *par; + int minlen = 0; - for (c = syntax; *c != 0; ++c) { - /* this makes sure that: - * minlen("kc?") = 0 - * minlen("kc+") = 1 - * minlen("cccc+c?") = 4 - */ - if (*c == '?') - --minlen; - else if (*c != '+' && *c != 'k') - ++minlen; - } - c = syntax; + for (c = syntax; *c != 0; ++c) { + /* this makes sure that: + * minlen("kc?") = 0 + * minlen("kc+") = 1 + * minlen("cccc+c?") = 4 + */ + if (*c == '?') + --minlen; + else if (*c != '+' && *c != 'k') + ++minlen; + } + c = syntax; - /* mindestens ein Ziel (Ziellose Zauber werden nicht - * geparst) */ - if (minlen && size == 0) { - /* Fehler: Ziel vergessen */ - cmistake(u, ord, 203, MSG_MAGIC); - return 0; - } + /* mindestens ein Ziel (Ziellose Zauber werden nicht + * geparst) */ + if (minlen && size == 0) { + /* Fehler: Ziel vergessen */ + cmistake(u, ord, 203, MSG_MAGIC); + return 0; + } + + par = malloc(sizeof(spellparameter)); + par->length = size; + if (!size) { + par->param = NULL; + return par; + } + par->param = malloc(size * sizeof(spllprm *)); + + while (!fail && *c && i < size && param[i] != NULL) { + spllprm *spobj = NULL; + int j = -1; + switch (*c) { + case '?': + /* tja. das sollte moeglichst nur am Ende passieren, + * weil sonst die kacke dampft. */ + j = 0; + ++c; + assert(*c == 0); + break; + case '+': + /* das vorhergehende Element kommt ein oder mehrmals vor, wir + * springen zum key zurück */ + j = 0; + --c; + break; + case 'u': + /* Parameter ist eine Einheit, evtl. TEMP */ + j = addparam_unit(param + i, &spobj, u, ord); + ++c; + break; + case 'r': + /* Parameter sind zwei Regionskoordinaten */ + /* this silly thing only works in the normal plane! */ + j = addparam_region(param + i, &spobj, u, ord, get_normalplane()); + ++c; + break; + case 'b': + /* Parameter ist eine Burgnummer */ + j = addparam_building(param + i, &spobj); + ++c; + break; + case 's': + j = addparam_ship(param + i, &spobj); + ++c; + break; + case 'c': + /* Text, wird im Spruch ausgewertet */ + j = addparam_string(param + i, &spobj); + ++c; + break; + case 'i': /* Zahl */ + j = addparam_int(param + i, &spobj); + ++c; + break; + case 'k': + ++c; + switch (findparam_ex(param[i++], u->faction->locale)) { + case P_REGION: + spobj = (spllprm *)malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = target_r; + j = 0; + ++c; + break; + case P_UNIT: + if (i < size) { + j = addparam_unit(param + i, &spobj, u, ord); + ++c; + } + break; + case P_BUILDING: + case P_GEBAEUDE: + if (i < size) { + j = addparam_building(param + i, &spobj); + ++c; + } + break; + case P_SHIP: + if (i < size) { + j = addparam_ship(param + i, &spobj); + ++c; + } + break; + default: + j = -1; + break; + } + break; + default: + j = -1; + break; + } + if (j < 0) + fail = true; + else { + if (spobj != NULL) + par->param[p++] = spobj; + i += j; + } + } + + /* im Endeffekt waren es evtl. nur p parameter (wegen TEMP) */ + par->length = p; + if (fail || par->length < minlen) { + cmistake(u, ord, 209, MSG_MAGIC); + free_spellparameter(par); + return NULL; + } - par = malloc(sizeof(spellparameter)); - par->length = size; - if (!size) { - par->param = NULL; return par; - } - par->param = malloc(size * sizeof(spllprm *)); - - while (!fail && *c && i < size && param[i] != NULL) { - spllprm *spobj = NULL; - int j = -1; - switch (*c) { - case '?': - /* tja. das sollte moeglichst nur am Ende passieren, - * weil sonst die kacke dampft. */ - j = 0; - ++c; - assert(*c == 0); - break; - case '+': - /* das vorhergehende Element kommt ein oder mehrmals vor, wir - * springen zum key zurück */ - j = 0; - --c; - break; - case 'u': - /* Parameter ist eine Einheit, evtl. TEMP */ - j = addparam_unit(param + i, &spobj, u, ord); - ++c; - break; - case 'r': - /* Parameter sind zwei Regionskoordinaten */ - /* this silly thing only works in the normal plane! */ - j = addparam_region(param + i, &spobj, u, ord, get_normalplane()); - ++c; - break; - case 'b': - /* Parameter ist eine Burgnummer */ - j = addparam_building(param + i, &spobj); - ++c; - break; - case 's': - j = addparam_ship(param + i, &spobj); - ++c; - break; - case 'c': - /* Text, wird im Spruch ausgewertet */ - j = addparam_string(param + i, &spobj); - ++c; - break; - case 'i': /* Zahl */ - j = addparam_int(param + i, &spobj); - ++c; - break; - case 'k': - ++c; - switch (findparam_ex(param[i++], u->faction->locale)) { - case P_REGION: - spobj = (spllprm *)malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = target_r; - j = 0; - ++c; - break; - case P_UNIT: - if (i < size) { - j = addparam_unit(param + i, &spobj, u, ord); - ++c; - } - break; - case P_BUILDING: - case P_GEBAEUDE: - if (i < size) { - j = addparam_building(param + i, &spobj); - ++c; - } - break; - case P_SHIP: - if (i < size) { - j = addparam_ship(param + i, &spobj); - ++c; - } - break; - default: - j = -1; - break; - } - break; - default: - j = -1; - break; - } - if (j < 0) - fail = true; - else { - if (spobj != NULL) - par->param[p++] = spobj; - i += j; - } - } - - /* im Endeffekt waren es evtl. nur p parameter (wegen TEMP) */ - par->length = p; - if (fail || par->length < minlen) { - cmistake(u, ord, 209, MSG_MAGIC); - free_spellparameter(par); - return NULL; - } - - return par; } struct unit * co_get_caster(const struct castorder * co) { - return co->_familiar ? co->_familiar : co->magician.u; + return co->_familiar ? co->_familiar : co->magician.u; } struct region * co_get_region(const struct castorder * co) { - return co->_rtarget; + return co->_rtarget; } castorder *create_castorder(castorder * co, unit *caster, unit * familiar, const spell * sp, region * r, - int lev, float force, int range, struct order * ord, spellparameter * p) + int lev, float force, int range, struct order * ord, spellparameter * p) { - if (!co) co = (castorder*)calloc(1, sizeof(castorder)); + if (!co) co = (castorder*)calloc(1, sizeof(castorder)); - co->magician.u = caster; - co->_familiar = familiar; - co->sp = sp; - co->level = lev; - co->force = force; - co->_rtarget = r ? r : (familiar ? familiar->region : (caster ? caster->region : 0)); - co->distance = range; - co->order = copy_order(ord); - co->par = p; + co->magician.u = caster; + co->_familiar = familiar; + co->sp = sp; + co->level = lev; + co->force = force; + co->_rtarget = r ? r : (familiar ? familiar->region : (caster ? caster->region : 0)); + co->distance = range; + co->order = copy_order(ord); + co->par = p; - return co; + return co; } void free_castorder(struct castorder *co) { - if (co->par) free_spellparameter(co->par); - if (co->order) free_order(co->order); + if (co->par) free_spellparameter(co->par); + if (co->order) free_order(co->order); } /* Hänge c-order co an die letze c-order von cll an */ void add_castorder(spellrank * cll, castorder * co) { - if (cll->begin == NULL) { - cll->end = &cll->begin; - } + if (cll->begin == NULL) { + cll->end = &cll->begin; + } - *cll->end = co; - cll->end = &co->next; + *cll->end = co; + cll->end = &co->next; - return; + return; } void free_castorders(castorder * co) { - castorder *co2; + castorder *co2; - while (co) { - co2 = co; - co = co->next; - free_castorder(co2); - free(co2); - } - return; + while (co) { + co2 = co; + co = co->next; + free_castorder(co2); + free(co2); + } + return; } /* ------------------------------------------------------------- */ @@ -2112,592 +2139,600 @@ void free_castorders(castorder * co) **/ typedef struct familiar_data { - unit *mage; - unit *familiar; + unit *mage; + unit *familiar; } famililar_data; bool is_familiar(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiarmage); - return i2b(a != NULL); + attrib *a = a_find(u->attribs, &at_familiarmage); + return i2b(a != NULL); } static void a_write_unit(const attrib * a, const void *owner, struct storage *store) { - unit *u = (unit *) a->data.v; - write_unit_reference(u, store); + unit *u = (unit *)a->data.v; + write_unit_reference(u, store); } static int sm_familiar(const unit * u, const region * r, skill_t sk, int value) { /* skillmod */ - if (sk == SK_MAGIC) - return value; - else { - int mod; - unit *familiar = get_familiar(u); - if (familiar == NULL) { - /* the familiar is dead */ - return value; + if (sk == SK_MAGIC) + return value; + else { + int mod; + unit *familiar = get_familiar(u); + if (familiar == NULL) { + /* the familiar is dead */ + return value; + } + mod = eff_skill(familiar, sk, r) / 2; + if (r != familiar->region) { + mod /= distance(r, familiar->region); + } + return value + mod; } - mod = eff_skill(familiar, sk, r) / 2; - if (r != familiar->region) { - mod /= distance(r, familiar->region); - } - return value + mod; - } } static void set_familiar(unit * mage, unit * familiar) { - /* if the skill modifier for the mage does not yet exist, add it */ - attrib *a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - skillmod_data *smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - break; - a = a->next; - } - if (a == NULL) { - attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); - skillmod_data *smd = (skillmod_data *) an->data.v; - smd->special = sm_familiar; - smd->skill = NOSKILL; - } + /* if the skill modifier for the mage does not yet exist, add it */ + attrib *a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + skillmod_data *smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + break; + a = a->next; + } + if (a == NULL) { + attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); + skillmod_data *smd = (skillmod_data *)an->data.v; + smd->special = sm_familiar; + smd->skill = NOSKILL; + } - a = a_find(mage->attribs, &at_familiar); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_familiar)); - a->data.v = familiar; - } else - assert(!a->data.v || a->data.v == familiar); - /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ + a = a_find(mage->attribs, &at_familiar); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_familiar)); + a->data.v = familiar; + } + else + assert(!a->data.v || a->data.v == familiar); + /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ - a = a_find(familiar->attribs, &at_familiarmage); - if (a == NULL) { - a = a_add(&familiar->attribs, a_new(&at_familiarmage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(familiar->attribs, &at_familiarmage); + if (a == NULL) { + a = a_add(&familiar->attribs, a_new(&at_familiarmage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); } void remove_familiar(unit * mage) { - attrib *a = a_find(mage->attribs, &at_familiar); - attrib *an; - skillmod_data *smd; + attrib *a = a_find(mage->attribs, &at_familiar); + attrib *an; + skillmod_data *smd; - if (a != NULL) { - a_remove(&mage->attribs, a); - } - a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - an = a->next; - smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - a_remove(&mage->attribs, a); - a = an; - } + if (a != NULL) { + a_remove(&mage->attribs, a); + } + a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + an = a->next; + smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + a_remove(&mage->attribs, a); + a = an; + } } bool create_newfamiliar(unit * mage, unit * familiar) { - /* if the skill modifier for the mage does not yet exist, add it */ - attrib *a; - attrib *afam = a_find(mage->attribs, &at_familiar); - attrib *amage = a_find(familiar->attribs, &at_familiarmage); + /* if the skill modifier for the mage does not yet exist, add it */ + attrib *a; + attrib *afam = a_find(mage->attribs, &at_familiar); + attrib *amage = a_find(familiar->attribs, &at_familiarmage); - if (afam == NULL) { - afam = a_add(&mage->attribs, a_new(&at_familiar)); - } - afam->data.v = familiar; - if (amage == NULL) { - amage = a_add(&familiar->attribs, a_new(&at_familiarmage)); - } - amage->data.v = mage; + if (afam == NULL) { + afam = a_add(&mage->attribs, a_new(&at_familiar)); + } + afam->data.v = familiar; + if (amage == NULL) { + amage = a_add(&familiar->attribs, a_new(&at_familiarmage)); + } + amage->data.v = mage; - /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ - /* Wenn der Magier stirbt, dann auch der Vertraute */ - add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar)); - /* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */ - add_trigger(&familiar->attribs, "destroy", trigger_shock(mage)); + /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ + /* Wenn der Magier stirbt, dann auch der Vertraute */ + add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar)); + /* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */ + add_trigger(&familiar->attribs, "destroy", trigger_shock(mage)); - a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - skillmod_data *smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - break; - a = a->next; - } - if (a == NULL) { - attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); - skillmod_data *smd = (skillmod_data *) an->data.v; - smd->special = sm_familiar; - smd->skill = NOSKILL; - } - return true; + a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + skillmod_data *smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + break; + a = a->next; + } + if (a == NULL) { + attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); + skillmod_data *smd = (skillmod_data *)an->data.v; + smd->special = sm_familiar; + smd->skill = NOSKILL; + } + return true; } static int resolve_familiar(variant data, void *addr) { - unit *familiar; - int result = resolve_unit(data, &familiar); - if (result == 0 && familiar) { - attrib *a = a_find(familiar->attribs, &at_familiarmage); - if (a != NULL && a->data.v) { - unit *mage = (unit *) a->data.v; - set_familiar(mage, familiar); + unit *familiar; + int result = resolve_unit(data, &familiar); + if (result == 0 && familiar) { + attrib *a = a_find(familiar->attribs, &at_familiarmage); + if (a != NULL && a->data.v) { + unit *mage = (unit *)a->data.v; + set_familiar(mage, familiar); + } } - } - *(unit **) addr = familiar; - return result; + *(unit **)addr = familiar; + return result; } static int read_familiar(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_familiar); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_familiar); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } /* clones */ void create_newclone(unit * mage, unit * clone) { - attrib *a; + attrib *a; - a = a_find(mage->attribs, &at_clone); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_clone)); - a->data.v = clone; - } else - assert(!a->data.v || a->data.v == clone); - /* TODO: Diese Attribute beim Tod des Klons entfernen: */ + a = a_find(mage->attribs, &at_clone); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_clone)); + a->data.v = clone; + } + else + assert(!a->data.v || a->data.v == clone); + /* TODO: Diese Attribute beim Tod des Klons entfernen: */ - a = a_find(clone->attribs, &at_clonemage); - if (a == NULL) { - a = a_add(&clone->attribs, a_new(&at_clonemage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(clone->attribs, &at_clonemage); + if (a == NULL) { + a = a_add(&clone->attribs, a_new(&at_clonemage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); - /* Wenn der Magier stirbt, wird das in destroy_unit abgefangen. - * Kein Trigger, zu kompliziert. */ + /* Wenn der Magier stirbt, wird das in destroy_unit abgefangen. + * Kein Trigger, zu kompliziert. */ - /* Wenn der Klon stirbt, dann bekommt der Magier einen Schock */ - add_trigger(&clone->attribs, "destroy", trigger_clonedied(mage)); + /* Wenn der Klon stirbt, dann bekommt der Magier einen Schock */ + add_trigger(&clone->attribs, "destroy", trigger_clonedied(mage)); } static void set_clone(unit * mage, unit * clone) { - attrib *a; + attrib *a; - a = a_find(mage->attribs, &at_clone); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_clone)); - a->data.v = clone; - } else - assert(!a->data.v || a->data.v == clone); + a = a_find(mage->attribs, &at_clone); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_clone)); + a->data.v = clone; + } + else + assert(!a->data.v || a->data.v == clone); - a = a_find(clone->attribs, &at_clonemage); - if (a == NULL) { - a = a_add(&clone->attribs, a_new(&at_clonemage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(clone->attribs, &at_clonemage); + if (a == NULL) { + a = a_add(&clone->attribs, a_new(&at_clonemage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); } unit *has_clone(unit * mage) { - attrib *a = a_find(mage->attribs, &at_clone); - if (a) - return (unit *) a->data.v; - return NULL; + attrib *a = a_find(mage->attribs, &at_clone); + if (a) + return (unit *)a->data.v; + return NULL; } static int resolve_clone(variant data, void *addr) { - unit *clone; - int result = resolve_unit(data, &clone); - if (result == 0 && clone) { - attrib *a = a_find(clone->attribs, &at_clonemage); - if (a != NULL && a->data.v) { - unit *mage = (unit *) a->data.v; - set_clone(mage, clone); + unit *clone; + int result = resolve_unit(data, &clone); + if (result == 0 && clone) { + attrib *a = a_find(clone->attribs, &at_clonemage); + if (a != NULL && a->data.v) { + unit *mage = (unit *)a->data.v; + set_clone(mage, clone); + } } - } - *(unit **) addr = clone; - return result; + *(unit **)addr = clone; + return result; } static int read_clone(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_clone); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_clone); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } /* mages */ static int resolve_mage(variant data, void *addr) { - unit *mage; - int result = resolve_unit(data, &mage); - if (result == 0 && mage) { - attrib *a = a_find(mage->attribs, &at_familiar); - if (a != NULL && a->data.v) { - unit *familiar = (unit *) a->data.v; - set_familiar(mage, familiar); + unit *mage; + int result = resolve_unit(data, &mage); + if (result == 0 && mage) { + attrib *a = a_find(mage->attribs, &at_familiar); + if (a != NULL && a->data.v) { + unit *familiar = (unit *)a->data.v; + set_familiar(mage, familiar); + } } - } - *(unit **) addr = mage; - return result; + *(unit **)addr = mage; + return result; } static int read_magician(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_mage); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_mage); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } static int age_unit(attrib * a) /* if unit is gone or dead, remove the attribute */ { - unit *u = (unit *) a->data.v; - return (u != NULL && u->number > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + unit *u = (unit *)a->data.v; + return (u != NULL && u->number > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } attrib_type at_familiarmage = { - "familiarmage", - NULL, - NULL, - age_unit, - a_write_unit, - read_magician, - ATF_UNIQUE + "familiarmage", + NULL, + NULL, + age_unit, + a_write_unit, + read_magician, + ATF_UNIQUE }; attrib_type at_familiar = { - "familiar", - NULL, - NULL, - age_unit, - a_write_unit, - read_familiar, - ATF_UNIQUE + "familiar", + NULL, + NULL, + age_unit, + a_write_unit, + read_familiar, + ATF_UNIQUE }; attrib_type at_clonemage = { - "clonemage", - NULL, - NULL, - age_unit, - a_write_unit, - read_magician, - ATF_UNIQUE + "clonemage", + NULL, + NULL, + age_unit, + a_write_unit, + read_magician, + ATF_UNIQUE }; attrib_type at_clone = { - "clone", - NULL, - NULL, - age_unit, - a_write_unit, - read_clone, - ATF_UNIQUE + "clone", + NULL, + NULL, + age_unit, + a_write_unit, + read_clone, + ATF_UNIQUE }; unit *get_familiar(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiar); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_familiar); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_familiar_mage(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiarmage); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_familiarmage); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_clone(const unit * u) { - attrib *a = a_find(u->attribs, &at_clone); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_clone); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_clone_mage(const unit * u) { - attrib *a = a_find(u->attribs, &at_clonemage); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_clonemage); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } static bool is_moving_ship(const region * r, ship * sh) { - const unit *u = ship_owner(sh); + const unit *u = ship_owner(sh); - if (u) - switch (getkeyword(u->thisorder)) { - case K_ROUTE: - case K_MOVE: - case K_FOLLOW: - return true; - default: - return false; + if (u) + switch (getkeyword(u->thisorder)) { + case K_ROUTE: + case K_MOVE: + case K_FOLLOW: + return true; + default: + return false; } - return false; + return false; } static castorder *cast_cmd(unit * u, order * ord) { - region *r = u->region; - region *target_r = r; - int level, range; - unit *familiar = NULL; - const char *s; - spell *sp = 0; - plane *pl; - spellparameter *args = NULL; - unit * caster = u; - param_t param; + region *r = u->region; + region *target_r = r; + int level, range; + unit *familiar = NULL; + const char *s; + spell *sp = 0; + plane *pl; + spellparameter *args = NULL; + unit * caster = u; + param_t param; - if (LongHunger(u)) { - cmistake(u, ord, 224, MSG_MAGIC); - return 0; - } - pl = rplane(r); - if (pl && fval(pl, PFL_NOMAGIC)) { - cmistake(u, ord, 269, MSG_MAGIC); - return 0; - } - level = eff_skill(u, SK_MAGIC, r); - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - param = findparam(s, u->faction->locale); - /* für Syntax ' STUFE x REGION y z ' */ - if (param == P_LEVEL) { - int p = getint(); - level = _min(p, level); - if (level < 1) { - /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); - return 0; + if (LongHunger(u)) { + cmistake(u, ord, 224, MSG_MAGIC); + return 0; } + pl = rplane(r); + if (pl && fval(pl, PFL_NOMAGIC)) { + cmistake(u, ord, 269, MSG_MAGIC); + return 0; + } + level = eff_skill(u, SK_MAGIC, r); + + init_tokens(ord); + skip_token(); s = getstrtoken(); param = findparam(s, u->faction->locale); - } - if (param == P_REGION) { - int t_x = getint(); - int t_y = getint(); - plane *pl = getplane(u->region); - t_x = rel_to_abs(pl, u->faction, t_x, 0); - t_y = rel_to_abs(pl, u->faction, t_y, 1); - pnormalize(&t_x, &t_y, pl); - target_r = findregion(t_x, t_y); - if (!target_r) { - /* Fehler "Die Region konnte nicht verzaubert werden" */ - ADDMSG(&u->faction->msgs, msg_message("spellregionresists", - "unit region command", u, u->region, ord)); - return 0; + /* für Syntax ' STUFE x REGION y z ' */ + if (param == P_LEVEL) { + int p = getint(); + level = _min(p, level); + if (level < 1) { + /* Fehler "Das macht wenig Sinn" */ + cmistake(u, ord, 10, MSG_MAGIC); + return 0; + } + s = getstrtoken(); + param = findparam(s, u->faction->locale); } - s = getstrtoken(); - param = findparam(s, u->faction->locale); - } - /* für Syntax ' REGION x y STUFE z ' - * hier nach REGION nochmal auf STUFE prüfen */ - if (param == P_LEVEL) { - int p = getint(); - level = _min(p, level); - if (level < 1) { - /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); - return 0; + if (param == P_REGION) { + int t_x = getint(); + int t_y = getint(); + plane *pl = getplane(u->region); + t_x = rel_to_abs(pl, u->faction, t_x, 0); + t_y = rel_to_abs(pl, u->faction, t_y, 1); + pnormalize(&t_x, &t_y, pl); + target_r = findregion(t_x, t_y); + if (!target_r) { + /* Fehler "Die Region konnte nicht verzaubert werden" */ + ADDMSG(&u->faction->msgs, msg_message("spellregionresists", + "unit region command", u, u->region, ord)); + return 0; + } + s = getstrtoken(); + param = findparam(s, u->faction->locale); } - s = getstrtoken(); - } - if (!s[0] || strlen(s) == 0) { - /* Fehler "Es wurde kein Zauber angegeben" */ - cmistake(u, ord, 172, MSG_MAGIC); - return 0; - } - - sp = unit_getspell(u, s, u->faction->locale); - - /* Vertraute können auch Zauber sprechen, die sie selbst nicht - * können. unit_getspell findet aber nur jene Sprüche, die - * die Einheit beherrscht. */ - if (!sp && is_familiar(u)) { - caster = get_familiar_mage(u); - if (caster) { - familiar = u; - sp = unit_getspell(caster, s, caster->faction->locale); - } else { - /* somehow, this familiar has no mage! */ - log_error("cast_cmd: familiar %s is without a mage?\n", unitname(u)); - caster = u; + /* für Syntax ' REGION x y STUFE z ' + * hier nach REGION nochmal auf STUFE prüfen */ + if (param == P_LEVEL) { + int p = getint(); + level = _min(p, level); + if (level < 1) { + /* Fehler "Das macht wenig Sinn" */ + cmistake(u, ord, 10, MSG_MAGIC); + return 0; + } + s = getstrtoken(); } - } - - if (!sp) { - /* Fehler 'Spell not found' */ - cmistake(u, ord, 173, MSG_MAGIC); - return 0; - } - /* um testen auf spruchnamen zu unterbinden sollte vor allen - * fehlermeldungen die anzeigen das der magier diesen Spruch - * nur in diese Situation nicht anwenden kann, noch eine - * einfache Sicherheitsprüfung kommen */ - if (!knowsspell(r, u, sp)) { - /* vorsicht! u kann der familiar sein */ - if (!familiar) { - cmistake(u, ord, 173, MSG_MAGIC); - return 0; - } - } - if (sp->sptyp & ISCOMBATSPELL) { - /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ - cmistake(u, ord, 174, MSG_MAGIC); - return 0; - } - /* Auf dem Ozean Zaubern als quasi-langer Befehl können - * normalerweise nur Meermenschen, ausgenommen explizit als - * OCEANCASTABLE deklarierte Sprüche */ - if (fval(r->terrain, SEA_REGION)) { - if (u_race(u) != get_race(RC_AQUARIAN) - && !fval(u_race(u), RCF_SWIM) - && !(sp->sptyp & OCEANCASTABLE)) { - /* Fehlermeldung */ - ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean", - "unit region command", u, u->region, ord)); - return 0; - } - /* Auf bewegenden Schiffen kann man nur explizit als - * ONSHIPCAST deklarierte Zauber sprechen */ - } else if (u->ship) { - if (is_moving_ship(r, u->ship)) { - if (!(sp->sptyp & ONSHIPCAST)) { - /* Fehler: "Diesen Spruch kann man nicht auf einem sich - * bewegenden Schiff stehend zaubern" */ - cmistake(u, ord, 175, MSG_MAGIC); + if (!s[0] || strlen(s) == 0) { + /* Fehler "Es wurde kein Zauber angegeben" */ + cmistake(u, ord, 172, MSG_MAGIC); return 0; - } } - } - /* Farcasting bei nicht farcastbaren Sprüchen abfangen */ - range = farcasting(u, target_r); - if (range > 1) { - if (!(sp->sptyp & FARCASTING)) { - /* Fehler "Diesen Spruch kann man nicht in die Ferne - * richten" */ - cmistake(u, ord, 176, MSG_MAGIC); - return 0; + + sp = unit_getspell(u, s, u->faction->locale); + + /* Vertraute können auch Zauber sprechen, die sie selbst nicht + * können. unit_getspell findet aber nur jene Sprüche, die + * die Einheit beherrscht. */ + if (!sp && is_familiar(u)) { + caster = get_familiar_mage(u); + if (caster) { + familiar = u; + sp = unit_getspell(caster, s, caster->faction->locale); + } + else { + /* somehow, this familiar has no mage! */ + log_error("cast_cmd: familiar %s is without a mage?\n", unitname(u)); + caster = u; + } } - if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */ - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "spellfail::nocontact", - "target", target_r)); - return 0; - } - } - /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ - if (!(sp->sptyp & SPELLLEVEL)) { - int ilevel = eff_skill(u, SK_MAGIC, u->region); - if (ilevel != level) { - level = ilevel; - ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel", - "mage region command", u, u->region, ord)); - } - } - /* Vertrautenmagie */ - /* Kennt der Vertraute den Spruch, so zaubert er ganz normal. - * Ansonsten zaubert der Magier durch seinen Vertrauten, dh - * zahlt Komponenten und Aura. Dabei ist die maximale Stufe - * die des Vertrauten! - * Der Spruch wirkt dann auf die Region des Vertrauten und - * gilt nicht als Farcasting. */ - if (familiar) { - if ((sp->sptyp & NOTFAMILIARCAST)) { - /* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */ - cmistake(u, ord, 177, MSG_MAGIC); - return 0; - } - if (caster != familiar) { /* Magier zaubert durch Vertrauten */ - if (range > 1) { /* Fehler! Versucht zu Farcasten */ - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast", - "mage", caster)); + + if (!sp) { + /* Fehler 'Spell not found' */ + cmistake(u, ord, 173, MSG_MAGIC); return 0; - } - if (distance(caster->region, r) > eff_skill(caster, SK_MAGIC, caster->region)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar", - "mage", caster)); + } + /* um testen auf spruchnamen zu unterbinden sollte vor allen + * fehlermeldungen die anzeigen das der magier diesen Spruch + * nur in diese Situation nicht anwenden kann, noch eine + * einfache Sicherheitsprüfung kommen */ + if (!knowsspell(r, u, sp)) { + /* vorsicht! u kann der familiar sein */ + if (!familiar) { + cmistake(u, ord, 173, MSG_MAGIC); + return 0; + } + } + if (sp->sptyp & ISCOMBATSPELL) { + /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ + cmistake(u, ord, 174, MSG_MAGIC); return 0; - } - /* mage auf magier setzen, level anpassen, range für Erhöhung - * der Spruchkosten nutzen, langen Befehl des Magiers - * löschen, zaubern kann er noch */ - range *= 2; - set_order(&caster->thisorder, NULL); - level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); } - } - /* Weitere Argumente zusammenbasteln */ - if (sp->parameter) { - char **params = (char**)malloc(2 * sizeof(char *)); - int p = 0, size = 2; - for (;;) { - s = getstrtoken(); - if (*s == 0) - break; - if (p + 1 >= size) { - size *= 2; - params = (char**)realloc(params, sizeof(char *) * size); - } - params[p++] = _strdup(s); + /* Auf dem Ozean Zaubern als quasi-langer Befehl können + * normalerweise nur Meermenschen, ausgenommen explizit als + * OCEANCASTABLE deklarierte Sprüche */ + if (fval(r->terrain, SEA_REGION)) { + if (u_race(u) != get_race(RC_AQUARIAN) + && !fval(u_race(u), RCF_SWIM) + && !(sp->sptyp & OCEANCASTABLE)) { + /* Fehlermeldung */ + ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean", + "unit region command", u, u->region, ord)); + return 0; + } + /* Auf bewegenden Schiffen kann man nur explizit als + * ONSHIPCAST deklarierte Zauber sprechen */ } - params[p] = 0; - args = - add_spellparameter(target_r, caster, sp->parameter, - (const char *const *)params, p, ord); - for (p = 0; params[p]; ++p) - free(params[p]); - free(params); - if (args == NULL) { - /* Syntax war falsch */ - return 0; + else if (u->ship) { + if (is_moving_ship(r, u->ship)) { + if (!(sp->sptyp & ONSHIPCAST)) { + /* Fehler: "Diesen Spruch kann man nicht auf einem sich + * bewegenden Schiff stehend zaubern" */ + cmistake(u, ord, 175, MSG_MAGIC); + return 0; + } + } } - } - return create_castorder(0, caster, familiar, sp, target_r, level, 0, range, ord, - args); + /* Farcasting bei nicht farcastbaren Sprüchen abfangen */ + range = farcasting(u, target_r); + if (range > 1) { + if (!(sp->sptyp & FARCASTING)) { + /* Fehler "Diesen Spruch kann man nicht in die Ferne + * richten" */ + cmistake(u, ord, 176, MSG_MAGIC); + return 0; + } + if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */ + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "spellfail::nocontact", + "target", target_r)); + return 0; + } + } + /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ + if (!(sp->sptyp & SPELLLEVEL)) { + int ilevel = eff_skill(u, SK_MAGIC, u->region); + if (ilevel != level) { + level = ilevel; + ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel", + "mage region command", u, u->region, ord)); + } + } + /* Vertrautenmagie */ + /* Kennt der Vertraute den Spruch, so zaubert er ganz normal. + * Ansonsten zaubert der Magier durch seinen Vertrauten, dh + * zahlt Komponenten und Aura. Dabei ist die maximale Stufe + * die des Vertrauten! + * Der Spruch wirkt dann auf die Region des Vertrauten und + * gilt nicht als Farcasting. */ + if (familiar) { + if ((sp->sptyp & NOTFAMILIARCAST)) { + /* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */ + cmistake(u, ord, 177, MSG_MAGIC); + return 0; + } + if (caster != familiar) { /* Magier zaubert durch Vertrauten */ + if (range > 1) { /* Fehler! Versucht zu Farcasten */ + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast", + "mage", caster)); + return 0; + } + if (distance(caster->region, r) > eff_skill(caster, SK_MAGIC, caster->region)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar", + "mage", caster)); + return 0; + } + /* mage auf magier setzen, level anpassen, range für Erhöhung + * der Spruchkosten nutzen, langen Befehl des Magiers + * löschen, zaubern kann er noch */ + range *= 2; + set_order(&caster->thisorder, NULL); + level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); + } + } + /* Weitere Argumente zusammenbasteln */ + if (sp->parameter) { + char **params = (char**)malloc(2 * sizeof(char *)); + int p = 0, size = 2; + for (;;) { + s = getstrtoken(); + if (*s == 0) + break; + if (p + 1 >= size) { + size *= 2; + params = (char**)realloc(params, sizeof(char *) * size); + } + params[p++] = _strdup(s); + } + params[p] = 0; + args = + add_spellparameter(target_r, caster, sp->parameter, + (const char *const *)params, p, ord); + for (p = 0; params[p]; ++p) + free(params[p]); + free(params); + if (args == NULL) { + /* Syntax war falsch */ + return 0; + } + } + return create_castorder(0, caster, familiar, sp, target_r, level, 0, range, ord, + args); } /* ------------------------------------------------------------- */ @@ -2720,227 +2755,231 @@ static castorder *cast_cmd(unit * u, order * ord) void magic(void) { - region *r; - int rank; - castorder *co; - spellrank spellranks[MAX_SPELLRANK]; + region *r; + int rank; + castorder *co; + spellrank spellranks[MAX_SPELLRANK]; - memset(spellranks, 0, sizeof(spellranks)); + memset(spellranks, 0, sizeof(spellranks)); - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - order *ord; + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + order *ord; - if (u->number <= 0 || u_race(u) == get_race(RC_SPELL)) - continue; + if (u->number <= 0 || u_race(u) == get_race(RC_SPELL)) + continue; - if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - continue; + if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && + !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + continue; - if (fval(u, UFL_WERE | UFL_LONGACTION)) { - continue; - } - - if (u->thisorder != NULL) { - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_CAST) { - castorder *co = cast_cmd(u, ord); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - if (co) { - const spell *sp = co->sp; - add_castorder(&spellranks[sp->rank], co); + if (fval(u, UFL_WERE | UFL_LONGACTION)) { + continue; + } + + if (u->thisorder != NULL) { + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_CAST) { + castorder *co = cast_cmd(u, ord); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + if (co) { + const spell *sp = co->sp; + add_castorder(&spellranks[sp->rank], co); + } + } + } } - } } - } } - } - /* Da sich die Aura und Komponenten in der Zwischenzeit verändert - * haben können und sich durch vorherige Sprüche das Zaubern - * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der - * Spruch überhaupt gezaubert werden kann. - * (level) die effektive Stärke des Spruchs (= Stufe, auf der der - * Spruch gezaubert wird) */ + /* Da sich die Aura und Komponenten in der Zwischenzeit verändert + * haben können und sich durch vorherige Sprüche das Zaubern + * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der + * Spruch überhaupt gezaubert werden kann. + * (level) die effektive Stärke des Spruchs (= Stufe, auf der der + * Spruch gezaubert wird) */ - for (rank = 0; rank < MAX_SPELLRANK; rank++) { - for (co = spellranks[rank].begin; co; co = co->next) { - order *ord = co->order; - int invalid, resist, success, cast_level = co->level; - bool fumbled = false; - unit *u = co->magician.u; - const spell *sp = co->sp; - region *target_r = co_get_region(co); + for (rank = 0; rank < MAX_SPELLRANK; rank++) { + for (co = spellranks[rank].begin; co; co = co->next) { + order *ord = co->order; + int invalid, resist, success, cast_level = co->level; + bool fumbled = false; + unit *u = co->magician.u; + const spell *sp = co->sp; + region *target_r = co_get_region(co); - /* reichen die Komponenten nicht, wird der Level reduziert. */ - co->level = eff_spelllevel(u, sp, cast_level, co->distance); + /* reichen die Komponenten nicht, wird der Level reduziert. */ + co->level = eff_spelllevel(u, sp, cast_level, co->distance); - if (co->level < 1) { - /* Fehlermeldung mit Komponenten generieren */ - cancast(u, sp, cast_level, co->distance, ord); - continue; - } + if (co->level < 1) { + /* Fehlermeldung mit Komponenten generieren */ + cancast(u, sp, cast_level, co->distance, ord); + continue; + } - if (cast_level > co->level) { - /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs - * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ - if (spl_costtyp(sp) != SPC_FIX) { - ADDMSG(&u->faction->msgs, msg_message("missing_components", - "unit spell level", u, sp, cast_level)); + if (cast_level > co->level) { + /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs + * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ + if (spl_costtyp(sp) != SPC_FIX) { + ADDMSG(&u->faction->msgs, msg_message("missing_components", + "unit spell level", u, sp, cast_level)); + } + } + + /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt + * werden können */ + if (!cancast(u, sp, co->level, co->distance, ord)) { + /* die Fehlermeldung wird in cancast generiert */ + continue; + } + + co->force = spellpower(target_r, u, sp, co->level, ord); + /* die Stärke kann durch Antimagie auf 0 sinken */ + if (co->force <= 0) { + co->force = 0; + ADDMSG(&u->faction->msgs, msg_message("missing_force", + "unit spell level", u, sp, co->level)); + } + + /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde + * kein Ziel gefunden, so ist verify_targets=0. Scheitert der + * Spruch an der Magieresistenz, so ist verify_targets = 1, bei + * Erfolg auf ganzer Linie ist verify_targets= 2 + */ + verify_targets(co, &invalid, &resist, &success); + if (success + resist == 0) { + /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ + /* keine kosten für den zauber */ + continue; /* äußere Schleife, nächster Zauberer */ + } + else if (co->force > 0 && resist > 0) { + /* einige oder alle Ziele waren magieresistent */ + if (success == 0) { + co->force = 0; + /* zwar wurde mindestens ein Ziel gefunden, das widerstand + * jedoch dem Zauber. Kosten abziehen und abbrechen. */ + ADDMSG(&u->faction->msgs, msg_message("spell_resist", + "unit region spell", u, r, sp)); + } + } + + /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten + * bezahlt werden und die nachfolgenden Sprüche werden teurer */ + if (co->force > 0) { + if (fumble(target_r, u, sp, co->level)) { + /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ + fumbled = true; + } + else { + co->level = sp->cast(co); + if (co->level <= 0) { + /* Kosten nur für real benötige Stufe berechnen */ + continue; + } + } + } + /* erst bezahlen, dann Kostenzähler erhöhen */ + if (co->level > 0) { + pay_spell(u, sp, co->level, co->distance); + } + if (fumbled) { + do_fumble(co); + } + countspells(u, 1); } - } - - /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt - * werden können */ - if (!cancast(u, sp, co->level, co->distance, ord)) { - /* die Fehlermeldung wird in cancast generiert */ - continue; - } - - co->force = spellpower(target_r, u, sp, co->level, ord); - /* die Stärke kann durch Antimagie auf 0 sinken */ - if (co->force <= 0) { - co->force = 0; - ADDMSG(&u->faction->msgs, msg_message("missing_force", - "unit spell level", u, sp, co->level)); - } - - /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde - * kein Ziel gefunden, so ist verify_targets=0. Scheitert der - * Spruch an der Magieresistenz, so ist verify_targets = 1, bei - * Erfolg auf ganzer Linie ist verify_targets= 2 - */ - verify_targets(co, &invalid, &resist, &success); - if (success + resist == 0) { - /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ - /* keine kosten für den zauber */ - continue; /* äußere Schleife, nächster Zauberer */ - } else if (co->force > 0 && resist > 0) { - /* einige oder alle Ziele waren magieresistent */ - if (success == 0) { - co->force = 0; - /* zwar wurde mindestens ein Ziel gefunden, das widerstand - * jedoch dem Zauber. Kosten abziehen und abbrechen. */ - ADDMSG(&u->faction->msgs, msg_message("spell_resist", - "unit region spell", u, r, sp)); - } - } - - /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten - * bezahlt werden und die nachfolgenden Sprüche werden teurer */ - if (co->force > 0) { - if (fumble(target_r, u, sp, co->level)) { - /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ - fumbled = true; - } else { - co->level = sp->cast(co); - if (co->level <= 0) { - /* Kosten nur für real benötige Stufe berechnen */ - continue; - } - } - } - /* erst bezahlen, dann Kostenzähler erhöhen */ - if (co->level>0) { - pay_spell(u, sp, co->level, co->distance); - } - if (fumbled) { - do_fumble(co); - } - countspells(u, 1); } - } - /* Sind alle Zauber gesprochen gibts Erfahrung */ - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - if (is_mage(u) && countspells(u, 0) > 0) { - produceexp(u, SK_MAGIC, u->number); - /* Spruchlistenaktualiesierung ist in Regeneration */ - } + /* Sind alle Zauber gesprochen gibts Erfahrung */ + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + if (is_mage(u) && countspells(u, 0) > 0) { + produceexp(u, SK_MAGIC, u->number); + /* Spruchlistenaktualiesierung ist in Regeneration */ + } + } } - } - for (rank = 0; rank < MAX_SPELLRANK; rank++) { - free_castorders(spellranks[rank].begin); - } - remove_empty_units(); + for (rank = 0; rank < MAX_SPELLRANK; rank++) { + free_castorders(spellranks[rank].begin); + } + remove_empty_units(); } const char *spell_info(const spell * sp, const struct locale *lang) { - return LOC(lang, mkname("spellinfo", sp->sname)); + return LOC(lang, mkname("spellinfo", sp->sname)); } const char *spell_name(const spell * sp, const struct locale *lang) { - return LOC(lang, mkname("spell", sp->sname)); + return LOC(lang, mkname("spell", sp->sname)); } const char *curse_name(const curse_type * ctype, const struct locale *lang) { - return LOC(lang, mkname("spell", ctype->cname)); + return LOC(lang, mkname("spell", ctype->cname)); } spell *unit_getspell(struct unit *u, const char *name, const struct locale * lang) { - sc_mage * mage = get_mage(u); - if (mage) { - variant token; - void * tokens = 0; - spellbook *sb = unit_get_spellbook(u); + sc_mage * mage = get_mage(u); + if (mage) { + variant token; + void * tokens = 0; + spellbook *sb = unit_get_spellbook(u); - if (sb) { - quicklist * ql; - int qi; + if (sb) { + quicklist * ql; + int qi; - for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); - spell *sp = sbe->sp; - const char *n = spell_name(sp, lang); - if (!n) { - log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); - } else { - token.v = sp; - addtoken(&tokens, n, token); + for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); + spell *sp = sbe->sp; + const char *n = spell_name(sp, lang); + if (!n) { + log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); + } + else { + token.v = sp; + addtoken(&tokens, n, token); + } + } } - } - } - if (tokens) { - if (findtoken(tokens, name, &token) != E_TOK_NOMATCH) { - freetokens(tokens); - return (spell *) token.v; - } - freetokens(tokens); + if (tokens) { + if (findtoken(tokens, name, &token) != E_TOK_NOMATCH) { + freetokens(tokens); + return (spell *)token.v; + } + freetokens(tokens); + } } - } - return 0; + return 0; } static critbit_tree cb_spellbooks; spellbook * get_spellbook(const char * name) { - char buffer[64]; - spellbook * result; - const void * match; + char buffer[64]; + spellbook * result; + const void * match; - if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0)) { - cb_get_kv(match, &result, sizeof(result)); - } else { - size_t len = strlen(name); - result = create_spellbook(name); - assert(strlen(name)+sizeof(result) - 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 @@ -74,340 +74,341 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. int *storms; typedef struct traveldir { - int no; - direction_t dir; - int age; + int no; + direction_t dir; + int age; } traveldir; static attrib_type at_traveldir = { - "traveldir", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */ - a_writechars, - a_readchars + "traveldir", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */ + a_writechars, + a_readchars }; typedef struct follower { - struct follower *next; - unit *uf; - unit *ut; - const region_list *route_end; + struct follower *next; + unit *uf; + unit *ut; + const region_list *route_end; } follower; static void get_followers(unit * target, region * r, const region_list * route_end, - follower ** followers) +follower ** followers) { - unit *uf; - for (uf = r->units; uf; uf = uf->next) { - if (fval(uf, UFL_FOLLOWING) && !fval(uf, UFL_NOTMOVING)) { - const attrib *a = a_findc(uf->attribs, &at_follow); - if (a && a->data.v == target) { - follower *fnew = (follower *)malloc(sizeof(follower)); - fnew->uf = uf; - fnew->ut = target; - fnew->route_end = route_end; - fnew->next = *followers; - *followers = fnew; - } + unit *uf; + for (uf = r->units; uf; uf = uf->next) { + if (fval(uf, UFL_FOLLOWING) && !fval(uf, UFL_NOTMOVING)) { + const attrib *a = a_findc(uf->attribs, &at_follow); + if (a && a->data.v == target) { + follower *fnew = (follower *)malloc(sizeof(follower)); + fnew->uf = uf; + fnew->ut = target; + fnew->route_end = route_end; + fnew->next = *followers; + *followers = fnew; + } + } } - } } static void shiptrail_init(attrib * a) { - a->data.v = calloc(1, sizeof(traveldir)); + a->data.v = calloc(1, sizeof(traveldir)); } static void shiptrail_finalize(attrib * a) { - free(a->data.v); + free(a->data.v); } static int shiptrail_age(attrib * a) { - traveldir *t = (traveldir *) (a->data.v); + traveldir *t = (traveldir *)(a->data.v); - t->age--; - return (t->age > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + t->age--; + return (t->age > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } static int shiptrail_read(attrib * a, void *owner, struct storage *store) { - int n; - traveldir *t = (traveldir *) (a->data.v); + int n; + traveldir *t = (traveldir *)(a->data.v); - READ_INT(store, &t->no); - READ_INT(store, &n); - t->dir = (direction_t)n; - READ_INT(store, &t->age); - return AT_READ_OK; + READ_INT(store, &t->no); + READ_INT(store, &n); + t->dir = (direction_t)n; + READ_INT(store, &t->age); + return AT_READ_OK; } static void shiptrail_write(const attrib * a, const void *owner, struct storage *store) { - traveldir *t = (traveldir *) (a->data.v); - WRITE_INT(store, t->no); - WRITE_INT(store, t->dir); - WRITE_INT(store, t->age); + traveldir *t = (traveldir *)(a->data.v); + WRITE_INT(store, t->no); + WRITE_INT(store, t->dir); + WRITE_INT(store, t->age); } attrib_type at_shiptrail = { - "traveldir_new", - shiptrail_init, - shiptrail_finalize, - shiptrail_age, - shiptrail_write, - shiptrail_read + "traveldir_new", + shiptrail_init, + shiptrail_finalize, + shiptrail_age, + shiptrail_write, + shiptrail_read }; static int age_speedup(attrib * a) { - if (a->data.sa[0] > 0) { - a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; - } - return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + if (a->data.sa[0] > 0) { + a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; + } + return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } attrib_type at_speedup = { - "speedup", - NULL, NULL, - age_speedup, - a_writeint, - a_readint + "speedup", + NULL, NULL, + age_speedup, + a_writeint, + a_readint }; /* ------------------------------------------------------------- */ static attrib_type at_driveweight = { - "driveweight", NULL, NULL, NULL, NULL, NULL + "driveweight", NULL, NULL, NULL, NULL, NULL }; static bool entrance_allowed(const struct unit *u, const struct region *r) { #ifdef REGIONOWNERS - faction *owner = region_get_owner(r); - if (owner == NULL || u->faction == owner) - return true; - if (alliedfaction(rplane(r), owner, u->faction, HELP_TRAVEL)) - return true; - return false; + faction *owner = region_get_owner(r); + if (owner == NULL || u->faction == owner) + return true; + if (alliedfaction(rplane(r), owner, u->faction, HELP_TRAVEL)) + return true; + return false; #else - return true; + return true; #endif } int personcapacity(const unit * u) { - int cap = u_race(u)->weight + u_race(u)->capacity; - return cap; + int cap = u_race(u)->weight + u_race(u)->capacity; + return cap; } static int eff_weight(const unit * u) { - attrib *a = a_find(u->attribs, &at_driveweight); + attrib *a = a_find(u->attribs, &at_driveweight); - if (a) - return weight(u) + a->data.i; + if (a) + return weight(u) + a->data.i; - return weight(u); + return weight(u); } static void get_transporters(const item * itm, int *p_animals, int *p_acap, int *p_vehicles, - int *p_vcap) +int *p_vcap) { - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - for (; itm != NULL; itm = itm->next) { - const item_type *itype = itm->type; - if (itype->capacity > 0) { - if (itype->flags & ITF_ANIMAL) { - animals += itm->number; - if (acap == 0) - acap = itype->capacity; - assert(acap == itype->capacity - || !"animals with different capacity not supported"); - } - if (itype->flags & ITF_VEHICLE) { - vehicles += itm->number; - if (vcap == 0) - vcap = itype->capacity; - assert(vcap == itype->capacity - || !"vehicles with different capacity not supported"); - } + for (; itm != NULL; itm = itm->next) { + const item_type *itype = itm->type; + if (itype->capacity > 0) { + if (itype->flags & ITF_ANIMAL) { + animals += itm->number; + if (acap == 0) + acap = itype->capacity; + assert(acap == itype->capacity + || !"animals with different capacity not supported"); + } + if (itype->flags & ITF_VEHICLE) { + vehicles += itm->number; + if (vcap == 0) + vcap = itype->capacity; + assert(vcap == itype->capacity + || !"vehicles with different capacity not supported"); + } + } } - } - *p_vehicles = vehicles; - *p_animals = animals; - *p_vcap = vcap; - *p_acap = acap; + *p_vehicles = vehicles; + *p_animals = animals; + *p_vcap = vcap; + *p_acap = acap; } static int ridingcapacity(unit * u) { - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen - ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er - ** von zwei Pferden gezogen wird */ + /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen + ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er + ** von zwei Pferden gezogen wird */ - animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); - if (fval(u_race(u), RCF_HORSE)) - animals += u->number; + animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); + if (fval(u_race(u), RCF_HORSE)) + animals += u->number; - /* maximal diese Pferde können zum Ziehen benutzt werden */ - vehicles = _min(animals / HORSESNEEDED, vehicles); + /* maximal diese Pferde können zum Ziehen benutzt werden */ + vehicles = _min(animals / HORSESNEEDED, vehicles); - return vehicles * vcap + animals * acap; + return vehicles * vcap + animals * acap; } int walkingcapacity(const struct unit *u) { - int n, people, pferde_fuer_wagen; - int wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen; - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; - const struct resource_type *rhorse = rt_find("horse"); - const struct resource_type *rbelt = rt_find("trollbelt"); + int n, people, pferde_fuer_wagen; + int wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; + const struct resource_type *rhorse = rt_find("horse"); + const struct resource_type *rbelt = rt_find("trollbelt"); - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - /* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches - * die Leute tragen */ + /* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches + * die Leute tragen */ - pferde_fuer_wagen = _min(animals, effskill(u, SK_RIDING) * u->number * 4); - if (fval(u_race(u), RCF_HORSE)) { - animals += u->number; - people = 0; - } else { - people = u->number; - } - - /* maximal diese Pferde können zum Ziehen benutzt werden */ - wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); - - n = wagen_mit_pferden * vcap; - - if (u_race(u) == get_race(RC_TROLL)) { - /* 4 Trolle ziehen einen Wagen. */ - /* Unbesetzte Wagen feststellen */ - wagen_ohne_pferde = vehicles - wagen_mit_pferden; - - /* Genug Trolle, um die Restwagen zu ziehen? */ - wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); - - /* Wagenkapazität hinzuzählen */ - n += wagen_mit_trollen * vcap; - wagen_ohne_pferde -= wagen_mit_trollen; - } - - n += animals * acap; - n += people * personcapacity(u); - /* Goliathwasser */ - if (rhorse) { - int tmp = get_effect(u, oldpotiontype[P_STRONG]); - if (tmp > 0) { - int horsecap = rhorse->itype->capacity; - if (tmp > people) { - tmp = people; - } - n += tmp * (horsecap - personcapacity(u)); + pferde_fuer_wagen = _min(animals, effskill(u, SK_RIDING) * u->number * 4); + if (fval(u_race(u), RCF_HORSE)) { + animals += u->number; + people = 0; + } + else { + people = u->number; } - } - if (rbelt) { - int tmp = i_get(u->items, rbelt->itype); - n += _min(people, tmp) * (STRENGTHMULTIPLIER - 1) * personcapacity(u); - } - return n; + /* maximal diese Pferde können zum Ziehen benutzt werden */ + wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); + + n = wagen_mit_pferden * vcap; + + if (u_race(u) == get_race(RC_TROLL)) { + /* 4 Trolle ziehen einen Wagen. */ + /* Unbesetzte Wagen feststellen */ + wagen_ohne_pferde = vehicles - wagen_mit_pferden; + + /* Genug Trolle, um die Restwagen zu ziehen? */ + wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); + + /* Wagenkapazität hinzuzählen */ + n += wagen_mit_trollen * vcap; + wagen_ohne_pferde -= wagen_mit_trollen; + } + + n += animals * acap; + n += people * personcapacity(u); + /* Goliathwasser */ + if (rhorse) { + int tmp = get_effect(u, oldpotiontype[P_STRONG]); + if (tmp > 0) { + int horsecap = rhorse->itype->capacity; + if (tmp > people) { + tmp = people; + } + n += tmp * (horsecap - personcapacity(u)); + } + } + if (rbelt) { + int tmp = i_get(u->items, rbelt->itype); + n += _min(people, tmp) * (STRENGTHMULTIPLIER - 1) * personcapacity(u); + } + + return n; } enum { - E_CANWALK_OK = 0, - E_CANWALK_TOOMANYHORSES, - E_CANWALK_TOOMANYCARTS, - E_CANWALK_TOOHEAVY + E_CANWALK_OK = 0, + E_CANWALK_TOOMANYHORSES, + E_CANWALK_TOOMANYCARTS, + E_CANWALK_TOOHEAVY }; static int canwalk(unit * u) { - int maxwagen, maxpferde; - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int maxwagen, maxpferde; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - /* workaround: monsters are too stupid to drop items, therefore they have - * infinite carrying capacity */ + /* workaround: monsters are too stupid to drop items, therefore they have + * infinite carrying capacity */ - if (is_monsters(u->faction)) - return E_CANWALK_OK; + if (is_monsters(u->faction)) + return E_CANWALK_OK; - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - maxwagen = effskill(u, SK_RIDING) * u->number * 2; - if (u_race(u) == get_race(RC_TROLL)) { - maxwagen = _max(maxwagen, u->number / 4); - } - maxpferde = effskill(u, SK_RIDING) * u->number * 4 + u->number; + maxwagen = effskill(u, SK_RIDING) * u->number * 2; + if (u_race(u) == get_race(RC_TROLL)) { + maxwagen = _max(maxwagen, u->number / 4); + } + maxpferde = effskill(u, SK_RIDING) * u->number * 4 + u->number; - if (animals > maxpferde) - return E_CANWALK_TOOMANYHORSES; + if (animals > maxpferde) + return E_CANWALK_TOOMANYHORSES; - if (walkingcapacity(u) - eff_weight(u) >= 0) - return E_CANWALK_OK; + if (walkingcapacity(u) - eff_weight(u) >= 0) + return E_CANWALK_OK; - /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne - * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat - * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen - * als erlaubt. */ + /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne + * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat + * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen + * als erlaubt. */ - if (vehicles > maxwagen) - return E_CANWALK_TOOMANYCARTS; - /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man - * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als - * Fracht draufpaßt) */ + if (vehicles > maxwagen) + return E_CANWALK_TOOMANYCARTS; + /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man + * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als + * Fracht draufpaßt) */ - return E_CANWALK_TOOHEAVY; + return E_CANWALK_TOOHEAVY; } bool canfly(unit * u) { - if (i_get(u->items, it_find("pegasus")) >= u->number && effskill(u, SK_RIDING) >= 4) - return true; + if (i_get(u->items, it_find("pegasus")) >= u->number && effskill(u, SK_RIDING) >= 4) + return true; - if (fval(u_race(u), RCF_FLY)) - return true; + if (fval(u_race(u), RCF_FLY)) + return true; - if (get_movement(&u->attribs, MV_FLY)) - return true; + if (get_movement(&u->attribs, MV_FLY)) + return true; - return false; + return false; } bool canswim(unit * u) { - if (i_get(u->items, it_find("dolphin")) >= u->number && effskill(u, SK_RIDING) >= 4) - return true; + if (i_get(u->items, it_find("dolphin")) >= u->number && effskill(u, SK_RIDING) >= 4) + return true; - if (u_race(u)->flags & RCF_FLY) - return true; + if (u_race(u)->flags & RCF_FLY) + return true; - if (u_race(u)->flags & RCF_SWIM) - return true; + if (u_race(u)->flags & RCF_SWIM) + return true; - if (get_movement(&u->attribs, MV_FLY)) - return true; + if (get_movement(&u->attribs, MV_FLY)) + return true; - if (get_movement(&u->attribs, MV_SWIM)) - return true; + if (get_movement(&u->attribs, MV_SWIM)) + return true; - return false; + return false; } static int canride(unit * u) @@ -422,211 +423,213 @@ static int canride(unit * u) it_elvenhorse = (rtype = get_resourcetype(R_UNICORN)) ? rtype->itype : 0; it_charger = (rtype = get_resourcetype(R_CHARGER)) ? rtype->itype : 0; - for (itm = u->items; itm; itm = itm->next) { - if (itm->type == it_horse || itm->type == it_charger) { - horses += itm->number; - } else if (itm->type == it_elvenhorse) { - unicorns += itm->number; + for (itm = u->items; itm; itm = itm->next) { + if (itm->type == it_horse || itm->type == it_charger) { + horses += itm->number; + } + else if (itm->type == it_elvenhorse) { + unicorns += itm->number; + } } - } - maxunicorns = (skill / 5) * u->number; - maxhorses = skill * u->number * 2; + maxunicorns = (skill / 5) * u->number; + maxhorses = skill * u->number * 2; + + if (!(u_race(u)->flags & RCF_HORSE) + && ((horses == 0 && unicorns == 0) + || horses > maxhorses || unicorns > maxunicorns)) { + return 0; + } + + if (ridingcapacity(u) - eff_weight(u) >= 0) { + if (horses == 0 && unicorns >= u->number && !(u_race(u)->flags & RCF_HORSE)) { + return 2; + } + return 1; + } - if (!(u_race(u)->flags & RCF_HORSE) - && ((horses == 0 && unicorns == 0) - || horses > maxhorses || unicorns > maxunicorns)) { return 0; - } - - if (ridingcapacity(u) - eff_weight(u) >= 0) { - if (horses == 0 && unicorns >= u->number && !(u_race(u)->flags & RCF_HORSE)) { - return 2; - } - return 1; - } - - return 0; } static bool cansail(const region * r, ship * sh) { - /* sonst ist construction:: size nicht ship_type::maxsize */ - assert(!sh->type->construction - || sh->type->construction->improvement == NULL); + /* sonst ist construction:: size nicht ship_type::maxsize */ + assert(!sh->type->construction + || sh->type->construction->improvement == NULL); - if (sh->type->construction && sh->size != sh->type->construction->maxsize) { - return false; - } else { - int n = 0, p = 0; - int mweight = shipcapacity(sh); - int mcabins = sh->type->cabins; + if (sh->type->construction && sh->size != sh->type->construction->maxsize) { + return false; + } + else { + int n = 0, p = 0; + int mweight = shipcapacity(sh); + int mcabins = sh->type->cabins; - getshipweight(sh, &n, &p); + getshipweight(sh, &n, &p); - if (n > mweight) - return false; - if (mcabins && p > mcabins) - return false; - } - return true; + if (n > mweight) + return false; + if (mcabins && p > mcabins) + return false; + } + return true; } int enoughsailors(const ship * sh, const region * r) { - int n; - unit *u; + int n; + unit *u; - n = 0; + n = 0; - for (u = r->units; u; u = u->next) { - if (u->ship == sh) - n += eff_skill(u, SK_SAILING, r) * u->number; - } - return n >= sh->type->sumskill; + for (u = r->units; u; u = u->next) { + if (u->ship == sh) + n += eff_skill(u, SK_SAILING, r) * u->number; + } + return n >= sh->type->sumskill; } /* ------------------------------------------------------------- */ static ship *do_maelstrom(region * r, unit * u) { - int damage; - ship *sh = u->ship; + int damage; + ship *sh = u->ship; - damage = rng_int() % 75 + rng_int() % 75 - eff_skill(u, SK_SAILING, r) * 4; + damage = rng_int() % 75 + rng_int() % 75 - eff_skill(u, SK_SAILING, r) * 4; - if (damage <= 0) { - return sh; - } + if (damage <= 0) { + return sh; + } - damage_ship(u->ship, 0.01 * damage); + damage_ship(u->ship, 0.01 * damage); - if (sh->damage >= sh->size * DAMAGE_SCALE) { + if (sh->damage >= sh->size * DAMAGE_SCALE) { + ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", + "region ship damage sink", r, sh, damage, 1)); + remove_ship(&sh->region->ships, sh); + return NULL; + } ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", - "region ship damage sink", r, sh, damage, 1)); - remove_ship(&sh->region->ships, sh); - return NULL; - } - ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", - "region ship damage sink", r, sh, damage, 0)); - return u->ship; + "region ship damage sink", r, sh, damage, 0)); + return u->ship; } /** sets a marker in the region telling that the unit has travelled through it * this is used for two distinctly different purposes: * - to report that a unit has travelled through. the report function - * makes sure to only report the ships of travellers, not the travellers + * makes sure to only report the ships of travellers, not the travellers * themselves * - to report the region to the traveller */ void travelthru(const unit * u, region * r) { - attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); + attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); - fset(r, RF_TRAVELUNIT); + fset(r, RF_TRAVELUNIT); - ru->data.v = (void *)u; + ru->data.v = (void *)u; - /* the first and last region of the faction gets reset, because travelthrough - * could be in regions that are located before the [first, last] interval, - * and recalculation is needed */ + /* the first and last region of the faction gets reset, because travelthrough + * could be in regions that are located before the [first, last] interval, + * and recalculation is needed */ #ifdef SMART_INTERVALS - update_interval(u->faction, r); + update_interval(u->faction, r); #endif } static void leave_trail(ship * sh, region * from, region_list * route) { - region *r = from; + region *r = from; - while (route != NULL) { - region *rn = route->data; - direction_t dir = reldirection(r, rn); + while (route != NULL) { + region *rn = route->data; + direction_t dir = reldirection(r, rn); - /* TODO: we cannot leave a trail into special directions - * if we use this kind of direction-attribute */ - if (dir < MAXDIRECTIONS && dir >= 0) { - traveldir *td = NULL; - attrib *a = a_find(r->attribs, &at_shiptrail); + /* TODO: we cannot leave a trail into special directions + * if we use this kind of direction-attribute */ + if (dir < MAXDIRECTIONS && dir >= 0) { + traveldir *td = NULL; + attrib *a = a_find(r->attribs, &at_shiptrail); - while (a != NULL && a->type == &at_shiptrail) { - td = (traveldir *) a->data.v; - if (td->no == sh->no) - break; - a = a->next; - } + while (a != NULL && a->type == &at_shiptrail) { + td = (traveldir *)a->data.v; + if (td->no == sh->no) + break; + a = a->next; + } - if (a == NULL || a->type != &at_shiptrail) { - a = a_add(&(r->attribs), a_new(&at_shiptrail)); - td = (traveldir *) a->data.v; - td->no = sh->no; - } - td->dir = dir; - td->age = 2; + if (a == NULL || a->type != &at_shiptrail) { + a = a_add(&(r->attribs), a_new(&at_shiptrail)); + td = (traveldir *)a->data.v; + td->no = sh->no; + } + td->dir = dir; + td->age = 2; + } + route = route->next; + r = rn; } - route = route->next; - r = rn; - } } static void mark_travelthru(const unit * u, region * r, const region_list * route, - const region_list * route_end) +const region_list * route_end) { - /* kein travelthru in der letzten region! */ - while (route != route_end) { - travelthru(u, r); - r = route->data; - route = route->next; - } + /* kein travelthru in der letzten region! */ + while (route != route_end) { + travelthru(u, r); + r = route->data; + route = route->next; + } } ship *move_ship(ship * sh, region * from, region * to, region_list * route) { - unit **iunit = &from->units; - unit **ulist = &to->units; - bool trail = (route == NULL); + unit **iunit = &from->units; + unit **ulist = &to->units; + bool trail = (route == NULL); - if (from != to) { - translist(&from->ships, &to->ships, sh); - sh->region = to; - } - if (!trail) { - leave_trail(sh, from, route); - trail = true; - } - - while (*iunit != NULL) { - unit *u = *iunit; - assert(u->region == from); - - if (u->ship == sh) { - if (route != NULL) - mark_travelthru(u, from, route, NULL); - if (from != to) { - u->ship = 0; /* temporary trick -- do not use u_set_ship here */ - move_unit(u, to, ulist); - ulist = &u->next; - u->ship = sh; /* undo the trick -- do not use u_set_ship here */ - } - if (route && eff_skill(u, SK_SAILING, from) >= 1) { - produceexp(u, SK_SAILING, u->number); - } + if (from != to) { + translist(&from->ships, &to->ships, sh); + sh->region = to; + } + if (!trail) { + leave_trail(sh, from, route); + trail = true; } - if (*iunit == u) - iunit = &u->next; - } - return sh; + while (*iunit != NULL) { + unit *u = *iunit; + assert(u->region == from); + + if (u->ship == sh) { + if (route != NULL) + mark_travelthru(u, from, route, NULL); + if (from != to) { + u->ship = 0; /* temporary trick -- do not use u_set_ship here */ + move_unit(u, to, ulist); + ulist = &u->next; + u->ship = sh; /* undo the trick -- do not use u_set_ship here */ + } + if (route && eff_skill(u, SK_SAILING, from) >= 1) { + produceexp(u, SK_SAILING, u->number); + } + } + if (*iunit == u) + iunit = &u->next; + } + + return sh; } static bool is_freezing(const unit * u) { if (u_race(u) != get_race(RC_INSECT)) - return false; - if (is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - return false; - return true; + return false; + if (is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + return false; + return true; } int check_ship_allowed(struct ship *sh, const region * r) @@ -638,24 +641,24 @@ int check_ship_allowed(struct ship *sh, const region * r) if (sh->region && r_insectstalled(r)) { /* insekten dürfen nicht hier rein. haben wir welche? */ unit *u; - + for (u = sh->region->units; u != NULL; u = u->next) { if (u->ship != sh) { continue; } - + if (is_freezing(u)) { unit *captain = ship_owner(sh); if (captain) { ADDMSG(&captain->faction->msgs, - msg_message("detectforbidden", "unit region", u, r)); + msg_message("detectforbidden", "unit region", u, r)); } - + return SA_NO_INSECT; } } } - + if (bt_harbour && buildingtype_exists(r, bt_harbour, true)) { return SA_HARBOUR; } @@ -674,162 +677,165 @@ int check_ship_allowed(struct ship *sh, const region * r) static bool flying_ship(const ship * sh) { - if (sh->type->flags & SFL_FLY) - return true; - if (sh->flags & SF_FLYING) - return true; - return false; + if (sh->type->flags & SFL_FLY) + return true; + if (sh->flags & SF_FLYING) + return true; + return false; } static void set_coast(ship * sh, region * r, region * rnext) { - if (sh->type->flags & SFL_NOCOAST) { - sh->coast = NODIRECTION; - } else if (!fval(rnext->terrain, SEA_REGION) && !flying_ship(sh)) { - sh->coast = reldirection(rnext, r); - assert(fval(r->terrain, SEA_REGION)); - } else { - sh->coast = NODIRECTION; - } + if (sh->type->flags & SFL_NOCOAST) { + sh->coast = NODIRECTION; + } + else if (!fval(rnext->terrain, SEA_REGION) && !flying_ship(sh)) { + sh->coast = reldirection(rnext, r); + assert(fval(r->terrain, SEA_REGION)); + } + else { + sh->coast = NODIRECTION; + } } static float damage_drift(void) { - static float value = -1.0F; - if (value < 0) { - value = get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F); - } - return value; + static float value = -1.0F; + if (value < 0) { + value = get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F); + } + return value; } static void drifting_ships(region * r) { - direction_t d; - bool drift = get_param_int(global.parameters, "rules.ship.drifting", 1)!=0; + direction_t d; + bool drift = get_param_int(global.parameters, "rules.ship.drifting", 1) != 0; - if (fval(r->terrain, SEA_REGION)) { - ship **shp = &r->ships; - while (*shp) { - ship *sh = *shp; - region *rnext = NULL; - region_list *route = NULL; - unit *firstu = NULL, *captain; - int d_offset; - direction_t dir = 0; + if (fval(r->terrain, SEA_REGION)) { + ship **shp = &r->ships; + while (*shp) { + ship *sh = *shp; + region *rnext = NULL; + region_list *route = NULL; + unit *firstu = NULL, *captain; + int d_offset; + direction_t dir = 0; - if (sh->type->fishing > 0) { - sh->flags |= SF_FISHING; - } + if (sh->type->fishing > 0) { + sh->flags |= SF_FISHING; + } - /* Schiff schon abgetrieben oder durch Zauber geschützt? */ - if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { - shp = &sh->next; - continue; - } + /* Schiff schon abgetrieben oder durch Zauber geschützt? */ + if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + shp = &sh->next; + continue; + } - /* Kapitän bestimmen */ - for (captain = r->units; captain; captain = captain->next) { - if (captain->ship != sh) - continue; - if (firstu == NULL) - firstu = captain; - if (eff_skill(captain, SK_SAILING, r) >= sh->type->cptskill) { - break; + /* Kapitän bestimmen */ + for (captain = r->units; captain; captain = captain->next) { + if (captain->ship != sh) + continue; + if (firstu == NULL) + firstu = captain; + if (eff_skill(captain, SK_SAILING, r) >= sh->type->cptskill) { + break; + } + } + /* Kapitän da? Beschädigt? Genügend Matrosen? + * Genügend leicht? Dann ist alles OK. */ + + assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (captain && sh->size == sh->type->construction->maxsize + && enoughsailors(sh, r) && cansail(r, sh)) { + shp = &sh->next; + continue; + } + + /* Auswahl einer Richtung: Zuerst auf Land, dann + * zufällig. Falls unmögliches Resultat: vergiß es. */ + d_offset = rng_int() % MAXDIRECTIONS; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn; + dir = (direction_t)((d + d_offset) % MAXDIRECTIONS); + rn = rconnect(r, dir); + if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) { + rnext = rn; + if (!fval(rnext->terrain, SEA_REGION)) + break; + } + } + + if (rnext == NULL) { + shp = &sh->next; + continue; + } + + /* Das Schiff und alle Einheiten darin werden nun von r + * nach rnext verschoben. Danach eine Meldung. */ + add_regionlist(&route, rnext); + + set_coast(sh, r, rnext); + sh = move_ship(sh, r, rnext, route); + free_regionlist(route); + + if (firstu != NULL) { + unit *u, *lastu = NULL; + message *msg = msg_message("ship_drift", "ship dir", sh, dir); + for (u = firstu; u; u = u->next) { + if (u->ship == sh && !fval(u->faction, FFL_MARK)) { + fset(u->faction, FFL_MARK); + add_message(&u->faction->msgs, msg); + lastu = u->next; + } + } + for (u = firstu; u != lastu; u = u->next) { + freset(u->faction, FFL_MARK); + } + msg_release(msg); + } + + if (sh != NULL) { + fset(sh, SF_DRIFTED); + + damage_ship(sh, damage_drift()); + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(&sh->region->ships, sh); + } + } + + if (*shp == sh) + shp = &sh->next; } - } - /* Kapitän da? Beschädigt? Genügend Matrosen? - * Genügend leicht? Dann ist alles OK. */ - - assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (captain && sh->size == sh->type->construction->maxsize - && enoughsailors(sh, r) && cansail(r, sh)) { - shp = &sh->next; - continue; - } - - /* Auswahl einer Richtung: Zuerst auf Land, dann - * zufällig. Falls unmögliches Resultat: vergiß es. */ - d_offset = rng_int() % MAXDIRECTIONS; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn; - dir = (direction_t) ((d + d_offset) % MAXDIRECTIONS); - rn = rconnect(r, dir); - if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) { - rnext = rn; - if (!fval(rnext->terrain, SEA_REGION)) - break; - } - } - - if (rnext == NULL) { - shp = &sh->next; - continue; - } - - /* Das Schiff und alle Einheiten darin werden nun von r - * nach rnext verschoben. Danach eine Meldung. */ - add_regionlist(&route, rnext); - - set_coast(sh, r, rnext); - sh = move_ship(sh, r, rnext, route); - free_regionlist(route); - - if (firstu != NULL) { - unit *u, *lastu = NULL; - message *msg = msg_message("ship_drift", "ship dir", sh, dir); - for (u = firstu; u; u = u->next) { - if (u->ship == sh && !fval(u->faction, FFL_MARK)) { - fset(u->faction, FFL_MARK); - add_message(&u->faction->msgs, msg); - lastu = u->next; - } - } - for (u = firstu; u != lastu; u = u->next) { - freset(u->faction, FFL_MARK); - } - msg_release(msg); - } - - if (sh != NULL) { - fset(sh, SF_DRIFTED); - - damage_ship(sh, damage_drift()); - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); - } - } - - if (*shp == sh) - shp = &sh->next; } - } } static bool present(region * r, unit * u) { - return (bool) (u && u->region == r); + return (bool)(u && u->region == r); } static void caught_target(region * r, unit * u) { - attrib *a = a_find(u->attribs, &at_follow); + attrib *a = a_find(u->attribs, &at_follow); - /* Verfolgungen melden */ - /* Misserfolgsmeldung, oder bei erfolgreichem Verfolgen unter - * Umstaenden eine Warnung. */ + /* Verfolgungen melden */ + /* Misserfolgsmeldung, oder bei erfolgreichem Verfolgen unter + * Umstaenden eine Warnung. */ - if (a) { - unit *target = (unit *) a->data.v; + if (a) { + unit *target = (unit *)a->data.v; - if (!present(r, target)) { - ADDMSG(&u->faction->msgs, msg_message("followfail", "unit follower", - target, u)); - } else if (!alliedunit(target, u->faction, HELP_ALL) - && cansee(target->faction, r, u, 0)) { - ADDMSG(&target->faction->msgs, msg_message("followdetect", - "unit follower", target, u)); + if (!present(r, target)) { + ADDMSG(&u->faction->msgs, msg_message("followfail", "unit follower", + target, u)); + } + else if (!alliedunit(target, u->faction, HELP_ALL) + && cansee(target->faction, r, u, 0)) { + ADDMSG(&target->faction->msgs, msg_message("followdetect", + "unit follower", target, u)); + } } - } } /* TODO: Unsichtbarkeit bedenken ! */ @@ -857,84 +863,84 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) gamecookie = global.cookie; } - if (fval(u_race(reisender), RCF_ILLUSIONARY)) - return NULL; - for (u = r->units; u && !contact; u = u->next) { - if (is_guard(u, GUARD_TRAVELTHRU)) { - int sk = eff_skill(u, SK_PERCEPTION, r); - if (invisible(reisender, u) >= reisender->number) - continue; - if (u->faction == reisender->faction) - contact = true; - else if (ucontact(u, reisender)) - contact = true; - else if (alliedunit(u, reisender->faction, HELP_GUARD)) - contact = true; - else if (sk >= stealth) { - double prob_u = (sk - stealth) * skill_prob; - /* amulet counts at most once */ - prob_u += _min (1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob; - if (prob_u >= prob) { - prob = prob_u; - guard = u; - } - } + if (fval(u_race(reisender), RCF_ILLUSIONARY)) + return NULL; + for (u = r->units; u && !contact; u = u->next) { + if (is_guard(u, GUARD_TRAVELTHRU)) { + int sk = eff_skill(u, SK_PERCEPTION, r); + if (invisible(reisender, u) >= reisender->number) + continue; + if (u->faction == reisender->faction) + contact = true; + else if (ucontact(u, reisender)) + contact = true; + else if (alliedunit(u, reisender->faction, HELP_GUARD)) + contact = true; + else if (sk >= stealth) { + double prob_u = (sk - stealth) * skill_prob; + /* amulet counts at most once */ + prob_u += _min(1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob; + if (prob_u >= prob) { + prob = prob_u; + guard = u; + } + } + } } - } - if (!contact && guard) { - prob += base_prob; /* 30% base chance */ + if (!contact && guard) { + prob += base_prob; /* 30% base chance */ - if (chance(prob)) { - return guard; + if (chance(prob)) { + return guard; + } } - } - return NULL; + return NULL; } static bool is_guardian_u(const unit * guard, unit * u, unsigned int mask) { - if (guard->faction == u->faction) - return false; - if (is_guard(guard, mask) == 0) - return false; - if (alliedunit(guard, u->faction, HELP_GUARD)) - return false; - if (ucontact(guard, u)) - return false; - if (!cansee(guard->faction, u->region, u, 0)) - return false; + if (guard->faction == u->faction) + return false; + if (is_guard(guard, mask) == 0) + return false; + if (alliedunit(guard, u->faction, HELP_GUARD)) + return false; + if (ucontact(guard, u)) + return false; + if (!cansee(guard->faction, u->region, u, 0)) + return false; - return true; + return true; } static bool is_guardian_r(const unit * guard) { - if (guard->number == 0) - return false; - if (besieged(guard)) - return false; + if (guard->number == 0) + return false; + if (besieged(guard)) + return false; - /* if region_owners exist then they may be guardians: */ - if (guard->building && rule_region_owners() && guard==building_owner(guard->building)) { - faction *owner = region_get_owner(guard->region); - if (owner == guard->faction) { - building *bowner = largestbuilding(guard->region, &cmp_taxes, false); - if (bowner == guard->building) { - return true; - } + /* if region_owners exist then they may be guardians: */ + if (guard->building && rule_region_owners() && guard == building_owner(guard->building)) { + faction *owner = region_get_owner(guard->region); + if (owner == guard->faction) { + building *bowner = largestbuilding(guard->region, &cmp_taxes, false); + if (bowner == guard->building) { + return true; + } + } } - } - if ((guard->flags & UFL_GUARD) == 0) - return false; - if (!armedmen(guard, true) && !fval(u_race(guard), RCF_UNARMEDGUARD)) - return false; - return true; + if ((guard->flags & UFL_GUARD) == 0) + return false; + if (!armedmen(guard, true) && !fval(u_race(guard), RCF_UNARMEDGUARD)) + return false; + return true; } bool is_guard(const struct unit * u, int mask) { - return is_guardian_r(u) && (getguard(u) & mask) != 0; + return is_guardian_r(u) && (getguard(u) & mask) != 0; } #define MAXGUARDCACHE 16 @@ -942,398 +948,406 @@ bool is_guard(const struct unit * u, int mask) */ unit *is_guarded(region * r, unit * u, unsigned int mask) { - unit *u2 = NULL; - int i, noguards = 1; - static unit *guardcache[MAXGUARDCACHE], *lastguard; /* STATIC_XCALL: used across calls */ - static int gamecookie = -1; + unit *u2 = NULL; + int i, noguards = 1; + static unit *guardcache[MAXGUARDCACHE], *lastguard; /* STATIC_XCALL: used across calls */ + static int gamecookie = -1; - if (!fval(r, RF_GUARDED)) { - return NULL; - } - - if (gamecookie != global.cookie) { - if (gamecookie >= 0) { - /* clear the previous turn's cache */ - memset(guardcache, 0, sizeof(guardcache)); - lastguard = NULL; - } - gamecookie = global.cookie; - } - - if (lastguard && lastguard->region == r) { - if (is_guardian_u(lastguard, u, mask)) { - return lastguard; - } - } - - for (i = 0; i != MAXGUARDCACHE; ++i) { - unit *guard = guardcache[i]; - if (guard && guard != lastguard && guard->region == r) { - noguards = 0; - if (is_guardian_u(guard, u, mask)) { - lastguard = guard; - return guard; - } - if (u2 == guard) { - /* same guard twice signals we've tested everyone */ + if (!fval(r, RF_GUARDED)) { return NULL; - } - u2 = guard; - } else { - /* exhausted all the guards in the cache, but maybe we'll find one later? */ - break; } - } - /* at this point, u2 is the last unit we tested to - * be a guard (and failed), or NULL - * i is the position of the first free slot in the cache */ - - for (u2 = (u2 ? u2->next : r->units); u2; u2 = u2->next) { - if (is_guardian_r(u2)) { - noguards = 0; - /* u2 is a guard, so worth remembering */ - if (i < MAXGUARDCACHE) - guardcache[i++] = u2; - if (is_guardian_u(u2, u, mask)) { - /* u2 is our guard. stop processing (we might have to go further next time) */ - lastguard = u2; - return u2; - } + if (gamecookie != global.cookie) { + if (gamecookie >= 0) { + /* clear the previous turn's cache */ + memset(guardcache, 0, sizeof(guardcache)); + lastguard = NULL; + } + gamecookie = global.cookie; } - } - /* there are no more guards. we signal this by duplicating the last one. - * i is still the position of the first free slot in the cache */ - if (i > 0 && i < MAXGUARDCACHE) { - guardcache[i] = guardcache[i - 1]; - } - if (noguards) { - /* you are mistaken, sir. there are no guards in these lands */ - freset(r, RF_GUARDED); - } - return NULL; + if (lastguard && lastguard->region == r) { + if (is_guardian_u(lastguard, u, mask)) { + return lastguard; + } + } + + for (i = 0; i != MAXGUARDCACHE; ++i) { + unit *guard = guardcache[i]; + if (guard && guard != lastguard && guard->region == r) { + noguards = 0; + if (is_guardian_u(guard, u, mask)) { + lastguard = guard; + return guard; + } + if (u2 == guard) { + /* same guard twice signals we've tested everyone */ + return NULL; + } + u2 = guard; + } + else { + /* exhausted all the guards in the cache, but maybe we'll find one later? */ + break; + } + } + + /* at this point, u2 is the last unit we tested to + * be a guard (and failed), or NULL + * i is the position of the first free slot in the cache */ + + for (u2 = (u2 ? u2->next : r->units); u2; u2 = u2->next) { + if (is_guardian_r(u2)) { + noguards = 0; + /* u2 is a guard, so worth remembering */ + if (i < MAXGUARDCACHE) + guardcache[i++] = u2; + if (is_guardian_u(u2, u, mask)) { + /* u2 is our guard. stop processing (we might have to go further next time) */ + lastguard = u2; + return u2; + } + } + } + /* there are no more guards. we signal this by duplicating the last one. + * i is still the position of the first free slot in the cache */ + if (i > 0 && i < MAXGUARDCACHE) { + guardcache[i] = guardcache[i - 1]; + } + + if (noguards) { + /* you are mistaken, sir. there are no guards in these lands */ + freset(r, RF_GUARDED); + } + return NULL; } static const char *shortdirections[MAXDIRECTIONS] = { - "dir_nw", - "dir_ne", - "dir_east", - "dir_se", - "dir_sw", - "dir_west" + "dir_nw", + "dir_ne", + "dir_east", + "dir_se", + "dir_sw", + "dir_west" }; static void cycle_route(order * ord, unit * u, int gereist) { - int bytes, cm = 0; - char tail[1024], *bufp = tail; - char neworder[2048]; - const char *token; - direction_t d = NODIRECTION; - bool paused = false; - bool pause; - order *norder; - size_t size = sizeof(tail) - 1; + int bytes, cm = 0; + char tail[1024], *bufp = tail; + char neworder[2048]; + const char *token; + direction_t d = NODIRECTION; + bool paused = false; + bool pause; + order *norder; + size_t size = sizeof(tail) - 1; - if (getkeyword(ord) != K_ROUTE) - return; - tail[0] = '\0'; + if (getkeyword(ord) != K_ROUTE) + return; + tail[0] = '\0'; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - neworder[0] = 0; - for (cm = 0;; ++cm) { - const struct locale *lang = u->faction->locale; - pause = false; - token = getstrtoken(); - if (token && *token) { - d = get_direction(token, lang); - if (d == D_PAUSE) { - pause = true; - } else if (d == NODIRECTION) { - break; - } - } else { - break; - } - if (cm < gereist) { - /* hier sollte keine PAUSE auftreten */ - assert(!pause); - if (!pause) { - const char *loc = LOC(lang, shortdirections[d]); - if (bufp != tail) { - bytes = (int)strlcpy(bufp, " ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + neworder[0] = 0; + for (cm = 0;; ++cm) { + const struct locale *lang = u->faction->locale; + pause = false; + token = getstrtoken(); + if (token && *token) { + d = get_direction(token, lang); + if (d == D_PAUSE) { + pause = true; + } + else if (d == NODIRECTION) { + break; + } + } + else { + break; + } + if (cm < gereist) { + /* hier sollte keine PAUSE auftreten */ + assert(!pause); + if (!pause) { + const char *loc = LOC(lang, shortdirections[d]); + if (bufp != tail) { + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + bytes = (int)strlcpy(bufp, loc, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + } + else if (strlen(neworder) > sizeof(neworder) / 2) + break; + else if (cm == gereist && !paused && pause) { + const char *loc = LOC(lang, parameters[P_PAUSE]); + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, loc, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + paused = true; + } + else if (pause) { + /* da PAUSE nicht in ein shortdirections[d] umgesetzt wird (ist + * hier keine normale direction), muss jede PAUSE einzeln + * herausgefiltert und explizit gesetzt werden */ + if (neworder[0]) + strcat(neworder, " "); + strcat(neworder, LOC(lang, parameters[P_PAUSE])); + } + else { + if (neworder[0]) + strcat(neworder, " "); + strcat(neworder, LOC(lang, shortdirections[d])); } - bytes = (int)strlcpy(bufp, loc, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - } else if (strlen(neworder) > sizeof(neworder) / 2) - break; - else if (cm == gereist && !paused && pause) { - const char *loc = LOC(lang, parameters[P_PAUSE]); - bytes = (int)strlcpy(bufp, " ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, loc, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - paused = true; - } else if (pause) { - /* da PAUSE nicht in ein shortdirections[d] umgesetzt wird (ist - * hier keine normale direction), muss jede PAUSE einzeln - * herausgefiltert und explizit gesetzt werden */ - if (neworder[0]) - strcat(neworder, " "); - strcat(neworder, LOC(lang, parameters[P_PAUSE])); - } else { - if (neworder[0]) - strcat(neworder, " "); - strcat(neworder, LOC(lang, shortdirections[d])); } - } - if (neworder[0]) { - norder = create_order(K_ROUTE, u->faction->locale, "%s %s", neworder, tail); - } else { - norder = create_order(K_ROUTE, u->faction->locale, "%s", tail); - } - replace_order(&u->orders, ord, norder); - free_order(norder); + if (neworder[0]) { + norder = create_order(K_ROUTE, u->faction->locale, "%s %s", neworder, tail); + } + else { + norder = create_order(K_ROUTE, u->faction->locale, "%s", tail); + } + replace_order(&u->orders, ord, norder); + free_order(norder); } static bool transport(unit * ut, unit * u) { - order *ord; + order *ord; - if (LongHunger(u) || fval(ut->region->terrain, SEA_REGION)) { - return false; - } - - for (ord = ut->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_TRANSPORT) { - init_tokens(ord); - skip_token(); - if (getunit(ut->region, ut->faction) == u) { - return true; - } + if (LongHunger(u) || fval(ut->region->terrain, SEA_REGION)) { + return false; } - } - return false; + + for (ord = ut->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_TRANSPORT) { + init_tokens(ord); + skip_token(); + if (getunit(ut->region, ut->faction) == u) { + return true; + } + } + } + return false; } static bool can_move(const unit * u) { - if (u_race(u)->flags & RCF_CANNOTMOVE) - return false; - if (get_movement(&u->attribs, MV_CANNOTMOVE)) - return false; - return true; + if (u_race(u)->flags & RCF_CANNOTMOVE) + return false; + if (get_movement(&u->attribs, MV_CANNOTMOVE)) + return false; + return true; } static void init_transportation(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit *u; + for (r = regions; r; r = r->next) { + unit *u; - /* This is just a simple check for non-corresponding K_TRANSPORT/ - * K_DRIVE. This is time consuming for an error check, but there - * doesn't seem to be an easy way to speed this up. */ - for (u = r->units; u; u = u->next) { - if (getkeyword(u->thisorder) == K_DRIVE && can_move(u) - && !fval(u, UFL_NOTMOVING) && !LongHunger(u)) { - unit *ut; + /* This is just a simple check for non-corresponding K_TRANSPORT/ + * K_DRIVE. This is time consuming for an error check, but there + * doesn't seem to be an easy way to speed this up. */ + for (u = r->units; u; u = u->next) { + if (getkeyword(u->thisorder) == K_DRIVE && can_move(u) + && !fval(u, UFL_NOTMOVING) && !LongHunger(u)) { + unit *ut; - init_tokens(u->thisorder); - skip_token(); - ut = getunit(r, u->faction); - if (ut == NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "feedback_unit_not_found", "")); - continue; - } - if (!transport(ut, u)) { - if (cansee(u->faction, r, ut, 0)) { - cmistake(u, u->thisorder, 286, MSG_MOVE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "feedback_unit_not_found", "")); - } - } - } - } - - /* This calculates the weights of all transported units and - * adds them to an internal counter which is used by travel () to - * calculate effective weight and movement. */ - - if (!fval(r->terrain, SEA_REGION)) { - for (u = r->units; u; u = u->next) { - order *ord; - int w = 0; - - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_TRANSPORT) { - init_tokens(ord); - skip_token(); - for (;;) { - unit *ut = getunit(r, u->faction); - - if (ut == NULL) - break; - if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) - && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { - init_tokens(ut->thisorder); + init_tokens(u->thisorder); skip_token(); - if (getunit(r, ut->faction) == u) { - w += weight(ut); + ut = getunit(r, u->faction); + if (ut == NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "feedback_unit_not_found", "")); + continue; + } + if (!transport(ut, u)) { + if (cansee(u->faction, r, ut, 0)) { + cmistake(u, u->thisorder, 286, MSG_MOVE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "feedback_unit_not_found", "")); + } } - } } - } } - if (w > 0) - a_add(&u->attribs, a_new(&at_driveweight))->data.i = w; - } + + /* This calculates the weights of all transported units and + * adds them to an internal counter which is used by travel () to + * calculate effective weight and movement. */ + + if (!fval(r->terrain, SEA_REGION)) { + for (u = r->units; u; u = u->next) { + order *ord; + int w = 0; + + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_TRANSPORT) { + init_tokens(ord); + skip_token(); + for (;;) { + unit *ut = getunit(r, u->faction); + + if (ut == NULL) + break; + if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) + && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + init_tokens(ut->thisorder); + skip_token(); + if (getunit(r, ut->faction) == u) { + w += weight(ut); + } + } + } + } + } + if (w > 0) + a_add(&u->attribs, a_new(&at_driveweight))->data.i = w; + } + } } - } } static bool roadto(const region * r, direction_t dir) { - /* wenn es hier genug strassen gibt, und verbunden ist, und es dort - * genug strassen gibt, dann existiert eine strasse in diese richtung */ - region *r2; - static const curse_type *roads_ct = NULL; + /* wenn es hier genug strassen gibt, und verbunden ist, und es dort + * genug strassen gibt, dann existiert eine strasse in diese richtung */ + region *r2; + static const curse_type *roads_ct = NULL; - if (dir >= MAXDIRECTIONS || dir < 0) - return false; - r2 = rconnect(r, dir); - if (r == NULL || r2 == NULL) - return false; + if (dir >= MAXDIRECTIONS || dir < 0) + return false; + r2 = rconnect(r, dir); + if (r == NULL || r2 == NULL) + return false; - if (roads_ct == NULL) - roads_ct = ct_find("magicstreet"); - if (roads_ct != NULL) { - if (get_curse(r->attribs, roads_ct) != NULL) - return true; - if (get_curse(r2->attribs, roads_ct) != NULL) - return true; - } + if (roads_ct == NULL) + roads_ct = ct_find("magicstreet"); + if (roads_ct != NULL) { + if (get_curse(r->attribs, roads_ct) != NULL) + return true; + if (get_curse(r2->attribs, roads_ct) != NULL) + return true; + } - if (r->terrain->max_road <= 0) - return false; - if (r2->terrain->max_road <= 0) - return false; - if (rroad(r, dir) < r->terrain->max_road) - return false; - if (rroad(r2, dir_invert(dir)) < r2->terrain->max_road) - return false; - return true; + if (r->terrain->max_road <= 0) + return false; + if (r2->terrain->max_road <= 0) + return false; + if (rroad(r, dir) < r->terrain->max_road) + return false; + if (rroad(r2, dir_invert(dir)) < r2->terrain->max_road) + return false; + return true; } static const region_list *cap_route(region * r, const region_list * route, - const region_list * route_end, int speed) + const region_list * route_end, int speed) { - region *current = r; - int moves = speed; - const region_list *iroute = route; - while (iroute != route_end) { - region *next = iroute->data; - direction_t reldir = reldirection(current, next); + region *current = r; + int moves = speed; + const region_list *iroute = route; + while (iroute != route_end) { + region *next = iroute->data; + direction_t reldir = reldirection(current, next); - /* adjust the range of the unit */ - if (roadto(current, reldir)) - moves -= BP_ROAD; - else - moves -= BP_NORMAL; - if (moves < 0) - break; - iroute = iroute->next; - current = next; - } - return iroute; + /* adjust the range of the unit */ + if (roadto(current, reldir)) + moves -= BP_ROAD; + else + moves -= BP_NORMAL; + if (moves < 0) + break; + iroute = iroute->next; + current = next; + } + return iroute; } static region *next_region(unit * u, region * current, region * next) { - connection *b; + connection *b; - b = get_borders(current, next); - while (b != NULL) { - if (b->type->move) { - region *rto = b->type->move(b, u, current, next, true); - if (rto != next) { - /* the target region was changed (wisps, for example). check the - * new target region for borders */ - next = rto; - b = get_borders(current, next); - continue; - } + b = get_borders(current, next); + while (b != NULL) { + if (b->type->move) { + region *rto = b->type->move(b, u, current, next, true); + if (rto != next) { + /* the target region was changed (wisps, for example). check the + * new target region for borders */ + next = rto; + b = get_borders(current, next); + continue; + } + } + b = b->next; } - b = b->next; - } - return next; + return next; } static const region_list *reroute(unit * u, const region_list * route, - const region_list * route_end) + const region_list * route_end) { - region *current = u->region; - while (route != route_end) { - region *next = next_region(u, current, route->data); - if (next != route->data) - break; - route = route->next; - } - return route; + region *current = u->region; + while (route != route_end) { + region *next = next_region(u, current, route->data); + if (next != route->data) + break; + route = route->next; + } + return route; } static void make_route(unit * u, order * ord, region_list ** routep) { - region_list **iroute = routep; - region *current = u->region; - region *next = NULL; - const char *token = getstrtoken(); - int error = movewhere(u, token, current, &next); + region_list **iroute = routep; + region *current = u->region; + region *next = NULL; + const char *token = getstrtoken(); + int error = movewhere(u, token, current, &next); - if (error != E_MOVE_OK) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); + if (error != E_MOVE_OK) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next = NULL; } - next = NULL; - } - while (next != NULL) { - if (current == next) { - /* PAUSE */ - break; + while (next != NULL) { + if (current == next) { + /* PAUSE */ + break; + } + next = next_region(u, current, next); + + add_regionlist(iroute, next); + iroute = &(*iroute)->next; + + current = next; + token = getstrtoken(); + error = movewhere(u, token, current, &next); + if (error) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next = NULL; + } } - next = next_region(u, current, next); - - add_regionlist(iroute, next); - iroute = &(*iroute)->next; - - current = next; - token = getstrtoken(); - error = movewhere(u, token, current, &next); - if (error) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - next = NULL; - } - } } /** calculate the speed of a unit @@ -1347,757 +1361,769 @@ static void make_route(unit * u, order * ord, region_list ** routep) */ static int movement_speed(unit * u) { - int mp; - static const curse_type *speed_ct; - static bool init = false; - double dk = u_race(u)->speed; + int mp; + static const curse_type *speed_ct; + static bool init = false; + double dk = u_race(u)->speed; - assert(u->number); - /* dragons have a fixed speed, and no other effects work on them: */ - switch (old_race(u_race(u))) { - case RC_DRAGON: - case RC_WYRM: - case RC_FIREDRAGON: - case RC_BIRTHDAYDRAGON: - case RC_SONGDRAGON: - return BP_DRAGON; - default: - break; - } - - if (!init) { - init = true; - speed_ct = ct_find("speed"); - } - if (speed_ct) { - curse *c = get_curse(u->attribs, speed_ct); - if (c != NULL) { - int men = get_cursedmen(u, c); - dk *= 1.0 + (double)men / (double)u->number; - } - } - - switch (canride(u)) { - - case 1: /* Pferd */ - mp = BP_RIDING; - break; - - case 2: /* Einhorn */ - mp = BP_UNICORN; - break; - - default: - mp = BP_WALKING; - - /* Siebenmeilentee */ - if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) { - mp *= 2; - change_effect(u, oldpotiontype[P_FAST], -u->number); + assert(u->number); + /* dragons have a fixed speed, and no other effects work on them: */ + switch (old_race(u_race(u))) { + case RC_DRAGON: + case RC_WYRM: + case RC_FIREDRAGON: + case RC_BIRTHDAYDRAGON: + case RC_SONGDRAGON: + return BP_DRAGON; + default: + break; } - /* unicorn in inventory */ - if (u->number <= i_get(u->items, it_find("fairyboot"))) { - mp *= 2; + if (!init) { + init = true; + speed_ct = ct_find("speed"); + } + if (speed_ct) { + curse *c = get_curse(u->attribs, speed_ct); + if (c != NULL) { + int men = get_cursedmen(u, c); + dk *= 1.0 + (double)men / (double)u->number; + } } - /* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell. - * Nicht kumulativ mit anderen Beschleunigungen! */ - if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region) - && is_mage(u)) { - sc_mage *mage = get_mage(u); - if (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN) { - mp *= 2; - } + switch (canride(u)) { + + case 1: /* Pferd */ + mp = BP_RIDING; + break; + + case 2: /* Einhorn */ + mp = BP_UNICORN; + break; + + default: + mp = BP_WALKING; + + /* Siebenmeilentee */ + if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) { + mp *= 2; + change_effect(u, oldpotiontype[P_FAST], -u->number); + } + + /* unicorn in inventory */ + if (u->number <= i_get(u->items, it_find("fairyboot"))) { + mp *= 2; + } + + /* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell. + * Nicht kumulativ mit anderen Beschleunigungen! */ + if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region) + && is_mage(u)) { + sc_mage *mage = get_mage(u); + if (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN) { + mp *= 2; + } + } + break; } - break; - } - return (int)(dk * mp); + return (int)(dk * mp); } enum { - TRAVEL_NORMAL, - TRAVEL_FOLLOWING, - TRAVEL_TRANSPORTED, - TRAVEL_RUNNING + TRAVEL_NORMAL, + TRAVEL_FOLLOWING, + TRAVEL_TRANSPORTED, + TRAVEL_RUNNING }; static arg_regions *var_copy_regions(const region_list * begin, int size) { - const region_list *rsrc; + const region_list *rsrc; - if (size > 0) { - int i = 0; - arg_regions *dst = - (arg_regions *) malloc(sizeof(arg_regions) + sizeof(region *) * size); - dst->nregions = size; - dst->regions = (region **) (dst + 1); - for (rsrc = begin; i != size; rsrc = rsrc->next) { - dst->regions[i++] = rsrc->data; + if (size > 0) { + int i = 0; + arg_regions *dst = + (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * size); + dst->nregions = size; + dst->regions = (region **)(dst + 1); + for (rsrc = begin; i != size; rsrc = rsrc->next) { + dst->regions[i++] = rsrc->data; + } + return dst; } - return dst; - } - return NULL; + return NULL; } static const region_list *travel_route(unit * u, - const region_list * route_begin, const region_list * route_end, order * ord, - int mode) + const region_list * route_begin, const region_list * route_end, order * ord, + int mode) { - region *r = u->region; - region *current = u->region; - const region_list *iroute = route_begin; - int steps = 0; - bool landing = false; /* aquarians have landed */ + region *r = u->region; + region *current = u->region; + const region_list *iroute = route_begin; + int steps = 0; + bool landing = false; /* aquarians have landed */ - while (iroute && iroute != route_end) { - region *next = iroute->data; - direction_t reldir = reldirection(current, next); - connection *b = get_borders(current, next); + while (iroute && iroute != route_end) { + region *next = iroute->data; + direction_t reldir = reldirection(current, next); + connection *b = get_borders(current, next); - /* check if we are caught by guarding units */ - if (iroute != route_begin && mode != TRAVEL_RUNNING - && mode != TRAVEL_TRANSPORTED) { - unit *wache = bewegung_blockiert_von(u, current); - if (wache != NULL) { - ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard", - "unit region guard", u, current, wache)); - break; - } - } + /* check if we are caught by guarding units */ + if (iroute != route_begin && mode != TRAVEL_RUNNING + && mode != TRAVEL_TRANSPORTED) { + unit *wache = bewegung_blockiert_von(u, current); + if (wache != NULL) { + ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard", + "unit region guard", u, current, wache)); + break; + } + } - /* check movement from/to oceans. - * aquarian special, flying units, horses, the works */ - if ((u_race(u)->flags & RCF_FLY) == 0) { - if (!fval(next->terrain, SEA_REGION)) { - /* next region is land */ - if (fval(current->terrain, SEA_REGION)) { - int moving = u_race(u)->flags & (RCF_SWIM | RCF_WALK | RCF_COASTAL); - /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */ - if (moving != (RCF_SWIM | RCF_WALK) && (moving & RCF_COASTAL) == 0) { - /* can't swim+walk and isn't allowed to enter coast from sea */ - if (ord != NULL) - cmistake(u, ord, 44, MSG_MOVE); + /* check movement from/to oceans. + * aquarian special, flying units, horses, the works */ + if ((u_race(u)->flags & RCF_FLY) == 0) { + if (!fval(next->terrain, SEA_REGION)) { + /* next region is land */ + if (fval(current->terrain, SEA_REGION)) { + int moving = u_race(u)->flags & (RCF_SWIM | RCF_WALK | RCF_COASTAL); + /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */ + if (moving != (RCF_SWIM | RCF_WALK) && (moving & RCF_COASTAL) == 0) { + /* can't swim+walk and isn't allowed to enter coast from sea */ + if (ord != NULL) + cmistake(u, ord, 44, MSG_MOVE); + break; + } + landing = true; + } + else if ((u_race(u)->flags & RCF_WALK) == 0) { + /* Spezialeinheiten, die nicht laufen können. */ + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + else if (landing) { + /* wir sind diese woche angelandet */ + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + } + else { + /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne + * Pferde betreten werden. */ + if (!(canswim(u) || canfly(u))) { + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + } + + if (fval(current->terrain, SEA_REGION) || fval(next->terrain, SEA_REGION)) { + /* trying to enter or exit ocean with horses, are we? */ + if (has_horses(u)) { + /* tries to do it with horses */ + if (ord != NULL) + cmistake(u, ord, 67, MSG_MOVE); + break; + } + } + + } + + /* movement blocked by a wall */ + if (reldir >= 0 && move_blocked(u, current, next)) { + ADDMSG(&u->faction->msgs, msg_message("leavefail", + "unit region", u, next)); break; - } - landing = true; - } else if ((u_race(u)->flags & RCF_WALK) == 0) { - /* Spezialeinheiten, die nicht laufen können. */ - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; - } else if (landing) { - /* wir sind diese woche angelandet */ - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; } - } else { - /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne - * Pferde betreten werden. */ - if (!(canswim(u) || canfly(u))) { - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; + + /* region ownership only: region owned by enemies */ + if (!entrance_allowed(u, next)) { + ADDMSG(&u->faction->msgs, msg_message("regionowned", + "unit region target", u, current, next)); + break; } - } - if (fval(current->terrain, SEA_REGION) || fval(next->terrain, SEA_REGION)) { - /* trying to enter or exit ocean with horses, are we? */ - if (has_horses(u)) { - /* tries to do it with horses */ - if (ord != NULL) - cmistake(u, ord, 67, MSG_MOVE); - break; + /* illusionary units disappear in antimagic zones */ + if (fval(u_race(u), RCF_ILLUSIONARY)) { + curse *c = get_curse(next->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + curse_changevigour(&next->attribs, c, (float)-u->number); + ADDMSG(&u->faction->msgs, msg_message("illusionantimagic", "unit", u)); + set_number(u, 0); + break; + } } - } + /* terrain is marked as forbidden (curse, etc) */ + if (fval(next, RF_BLOCKED) || fval(next->terrain, FORBIDDEN_REGION)) { + ADDMSG(&u->faction->msgs, msg_message("detectforbidden", + "unit region", u, next)); + break; + } + + /* unit is an insect and cannot move into a glacier */ + if (u_race(u) == get_race(RC_INSECT)) { + if (r_insectstalled(next) && is_freezing(u)) { + ADDMSG(&u->faction->msgs, msg_message("detectforbidden", + "unit region", u, next)); + break; + } + } + + /* effect of borders */ + while (b != NULL) { + if (b->type->move) { + b->type->move(b, u, current, next, false); + } + b = b->next; + } + + current = next; + iroute = iroute->next; + ++steps; + if (u->number == 0) + break; } - /* movement blocked by a wall */ - if (reldir >= 0 && move_blocked(u, current, next)) { - ADDMSG(&u->faction->msgs, msg_message("leavefail", - "unit region", u, next)); - break; + if (iroute != route_begin) { + /* the unit has moved at least one region */ + int walkmode; + + setguard(u, GUARD_NONE); + cycle_route(ord, u, steps); + + if (mode == TRAVEL_RUNNING) { + walkmode = 0; + } + if (canride(u)) { + walkmode = 1; + produceexp(u, SK_RIDING, u->number); + } + else { + walkmode = 2; + } + + /* Berichte über Durchreiseregionen */ + + if (mode != TRAVEL_TRANSPORTED) { + arg_regions *ar = var_copy_regions(route_begin, steps - 1); + ADDMSG(&u->faction->msgs, msg_message("travel", + "unit mode start end regions", u, walkmode, r, current, ar)); + } + + mark_travelthru(u, r, route_begin, iroute); + move_unit(u, current, NULL); + + /* make orders for the followers */ } - - /* region ownership only: region owned by enemies */ - if (!entrance_allowed(u, next)) { - ADDMSG(&u->faction->msgs, msg_message("regionowned", - "unit region target", u, current, next)); - break; - } - - /* illusionary units disappear in antimagic zones */ - if (fval(u_race(u), RCF_ILLUSIONARY)) { - curse *c = get_curse(next->attribs, ct_find("antimagiczone")); - if (curse_active(c)) { - curse_changevigour(&next->attribs, c, (float)-u->number); - ADDMSG(&u->faction->msgs, msg_message("illusionantimagic", "unit", u)); - set_number(u, 0); - break; - } - } - - /* terrain is marked as forbidden (curse, etc) */ - if (fval(next, RF_BLOCKED) || fval(next->terrain, FORBIDDEN_REGION)) { - ADDMSG(&u->faction->msgs, msg_message("detectforbidden", - "unit region", u, next)); - break; - } - - /* unit is an insect and cannot move into a glacier */ - if (u_race(u) == get_race(RC_INSECT)) { - if (r_insectstalled(next) && is_freezing(u)) { - ADDMSG(&u->faction->msgs, msg_message("detectforbidden", - "unit region", u, next)); - break; - } - } - - /* effect of borders */ - while (b != NULL) { - if (b->type->move) { - b->type->move(b, u, current, next, false); - } - b = b->next; - } - - current = next; - iroute = iroute->next; - ++steps; - if (u->number == 0) - break; - } - - if (iroute != route_begin) { - /* the unit has moved at least one region */ - int walkmode; - + fset(u, UFL_LONGACTION | UFL_NOTMOVING); setguard(u, GUARD_NONE); - cycle_route(ord, u, steps); - - if (mode == TRAVEL_RUNNING) { - walkmode = 0; - } - if (canride(u)) { - walkmode = 1; - produceexp(u, SK_RIDING, u->number); - } else { - walkmode = 2; - } - - /* Berichte über Durchreiseregionen */ - - if (mode != TRAVEL_TRANSPORTED) { - arg_regions *ar = var_copy_regions(route_begin, steps - 1); - ADDMSG(&u->faction->msgs, msg_message("travel", - "unit mode start end regions", u, walkmode, r, current, ar)); - } - - mark_travelthru(u, r, route_begin, iroute); - move_unit(u, current, NULL); - - /* make orders for the followers */ - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - setguard(u, GUARD_NONE); - assert(u->region == current); - return iroute; + assert(u->region == current); + return iroute; } static bool ship_ready(const region * r, unit * u) { - if (!u->ship || u!=ship_owner(u->ship)) { - cmistake(u, u->thisorder, 146, MSG_MOVE); - return false; - } - if (eff_skill(u, SK_SAILING, r) < u->ship->type->cptskill) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_captain_skill_low", "value ship", u->ship->type->cptskill, - u->ship)); - return false; - } - assert(u->ship->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (u->ship->size != u->ship->type->construction->maxsize) { - cmistake(u, u->thisorder, 15, MSG_MOVE); - return false; - } - if (!enoughsailors(u->ship, r)) { - cmistake(u, u->thisorder, 1, MSG_MOVE); -/* mistake(u, u->thisorder, - "Auf dem Schiff befinden sich zuwenig erfahrene Seeleute.", MSG_MOVE); */ - return false; - } - if (!cansail(r, u->ship)) { - cmistake(u, u->thisorder, 18, MSG_MOVE); - return false; - } - return true; + if (!u->ship || u != ship_owner(u->ship)) { + cmistake(u, u->thisorder, 146, MSG_MOVE); + return false; + } + if (eff_skill(u, SK_SAILING, r) < u->ship->type->cptskill) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_captain_skill_low", "value ship", u->ship->type->cptskill, + u->ship)); + return false; + } + assert(u->ship->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (u->ship->size != u->ship->type->construction->maxsize) { + cmistake(u, u->thisorder, 15, MSG_MOVE); + return false; + } + if (!enoughsailors(u->ship, r)) { + cmistake(u, u->thisorder, 1, MSG_MOVE); + /* mistake(u, u->thisorder, + "Auf dem Schiff befinden sich zuwenig erfahrene Seeleute.", MSG_MOVE); */ + return false; + } + if (!cansail(r, u->ship)) { + cmistake(u, u->thisorder, 18, MSG_MOVE); + return false; + } + return true; } unit *owner_buildingtyp(const region * r, const building_type * bt) { - building *b; - unit *owner; + building *b; + unit *owner; - for (b = rbuildings(r); b; b = b->next) { - owner = building_owner(b); - if (b->type == bt && owner != NULL) { - if (b->size >= bt->maxsize) { - return owner; - } + for (b = rbuildings(r); b; b = b->next) { + owner = building_owner(b); + if (b->type == bt && owner != NULL) { + if (b->size >= bt->maxsize) { + return owner; + } + } } - } - return NULL; + return NULL; } bool buildingtype_exists(const region * r, const building_type * bt, bool working) { - building *b; + building *b; - for (b = rbuildings(r); b; b = b->next) { - if (b->type == bt && b->size >= bt->maxsize && (!working || fval(b, BLD_WORKING))) - return true; - } + for (b = rbuildings(r); b; b = b->next) { + if (b->type == bt && b->size >= bt->maxsize && (!working || fval(b, BLD_WORKING))) + return true; + } - return false; + return false; } /* Prüft, ob Ablegen von einer Küste in eine der erlaubten Richtungen erfolgt. */ static bool check_takeoff(ship * sh, region * from, region * to) { - if (!fval(from->terrain, SEA_REGION) && sh->coast != NODIRECTION) { - direction_t coast = sh->coast; - direction_t dir = reldirection(from, to); - direction_t coastr = (direction_t) ((coast + 1) % MAXDIRECTIONS); - direction_t coastl = - (direction_t) ((coast + MAXDIRECTIONS - 1) % MAXDIRECTIONS); + if (!fval(from->terrain, SEA_REGION) && sh->coast != NODIRECTION) { + direction_t coast = sh->coast; + direction_t dir = reldirection(from, to); + direction_t coastr = (direction_t)((coast + 1) % MAXDIRECTIONS); + direction_t coastl = + (direction_t)((coast + MAXDIRECTIONS - 1) % MAXDIRECTIONS); - if (dir != coast && dir != coastl && dir != coastr - && !buildingtype_exists(from, bt_find("harbour"), true)) { - return false; + if (dir != coast && dir != coastl && dir != coastr + && !buildingtype_exists(from, bt_find("harbour"), true)) { + return false; + } } - } - return true; + return true; } static void sail(unit * u, order * ord, bool move_on_land, region_list ** routep) { - region *starting_point = u->region; - region *current_point, *last_point; - int k, step = 0; - region_list **iroute = routep; - ship *sh = u->ship; - faction *f = u->faction; - region *next_point = NULL; - int error; - const char *token = getstrtoken(); - - if (routep) - *routep = NULL; - - error = movewhere(u, token, starting_point, &next_point); - if (error) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - return; - } - - if (!ship_ready(starting_point, u)) - return; - - /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden - * dann nacheinander ausgeführt. */ - - k = shipspeed(sh, u); - - last_point = starting_point; - current_point = starting_point; - - /* die nächste Region, in die man segelt, wird durch movewhere () aus der - * letzten Region bestimmt. - * - * Anfangen tun wir bei starting_point. next_point ist beim ersten - * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, - * befahrene Region. */ - - while (next_point && current_point != next_point && step < k) { - const char *token; + region *starting_point = u->region; + region *current_point, *last_point; + int k, step = 0; + region_list **iroute = routep; + ship *sh = u->ship; + faction *f = u->faction; + region *next_point = NULL; int error; - const terrain_type *tthis = current_point->terrain; - /* these values need to be updated if next_point changes (due to storms): */ - const terrain_type *tnext = next_point->terrain; + const char *token = getstrtoken(); - assert(sh == u->ship || !"ship has sunk, but we didn't notice it"); + if (routep) + *routep = NULL; - if (fval(next_point->terrain, FORBIDDEN_REGION)||fval(next_point,RF_BLOCKED)) { - ADDMSG(&f->msgs, msg_message("sailforbidden", - "ship region", sh, next_point)); - break; + error = movewhere(u, token, starting_point, &next_point); + if (error) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + return; } - if (!flying_ship(sh)) { - int stormchance; - static int stormyness; - static int gamecookie = -1; - int reason; + if (!ship_ready(starting_point, u)) + return; - if (gamecookie != global.cookie) { - bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1)!=0; - if (storms_enabled) { - gamedate date; - get_gamedate(turn, &date); - stormyness = storms ? storms[date.month] * 5 : 0; - } - gamecookie = global.cookie; - } + /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden + * dann nacheinander ausgeführt. */ - /* storms should be the first thing we do. */ - stormchance = stormyness / shipspeed(sh, u); - if (check_leuchtturm(next_point, NULL)) { - int param = get_param_int(global.parameters, "rules.lighthous.stormchancedevisor", 0); - if (param > 0) { - stormchance /= param; - } - else { - stormchance = 0; - } - } - if (rng_int() % 10000 < stormchance * sh->type->storm - && fval(current_point->terrain, SEA_REGION)) { - if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { - region *rnext = NULL; - bool storm = true; - int d_offset = rng_int() % MAXDIRECTIONS; - direction_t d; - /* Sturm nur, wenn nächste Region Hochsee ist. */ - for (d = 0; d != MAXDIRECTIONS; ++d) { - direction_t dnext = (direction_t) ((d + d_offset) % MAXDIRECTIONS); - region *rn = rconnect(current_point, dnext); + k = shipspeed(sh, u); - if (rn != NULL) { - if (fval(rn->terrain, FORBIDDEN_REGION)) - continue; - if (!fval(rn->terrain, SEA_REGION)) { - storm = false; - break; - } - if (rn != next_point) - rnext = rn; - } - } - if (storm && rnext != NULL) { - ADDMSG(&f->msgs, msg_message("storm", "ship region sink", - sh, current_point, sh->damage >= sh->size * DAMAGE_SCALE)); + last_point = starting_point; + current_point = starting_point; - /* damage the ship. we handle destruction in the end */ - damage_ship(sh, damage_drift()); - if (sh->damage >= sh->size * DAMAGE_SCALE) - break; + /* die nächste Region, in die man segelt, wird durch movewhere () aus der + * letzten Region bestimmt. + * + * Anfangen tun wir bei starting_point. next_point ist beim ersten + * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, + * befahrene Region. */ - next_point = rnext; - /* these values need to be updated if next_point changes (due to storms): */ - tnext = next_point->terrain; - } - } - } + while (next_point && current_point != next_point && step < k) { + const char *token; + int error; + const terrain_type *tthis = current_point->terrain; + /* these values need to be updated if next_point changes (due to storms): */ + const terrain_type *tnext = next_point->terrain; - if (!fval(tthis, SEA_REGION)) { - if (!fval(tnext, SEA_REGION)) { - if (!move_on_land) { - /* check that you're not traveling from one land region to another. */ - ADDMSG(&u->faction->msgs, msg_message("shipnoshore", + assert(sh == u->ship || !"ship has sunk, but we didn't notice it"); + + if (fval(next_point->terrain, FORBIDDEN_REGION) || fval(next_point, RF_BLOCKED)) { + ADDMSG(&f->msgs, msg_message("sailforbidden", "ship region", sh, next_point)); break; - } - } else { - if (!check_takeoff(sh, current_point, next_point)) { - /* Schiff kann nicht ablegen */ - cmistake(u, ord, 182, MSG_MOVE); - break; - } } - } else if (fval(tnext, SEA_REGION)) { - /* target region is an ocean, and we're not leaving a shore */ - if (!(sh->type->flags & SFL_OPENSEA)) { - /* ship can only stay close to shore */ - direction_t d; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rc = rconnect(next_point, d); - if (rc == NULL || !fval(rc->terrain, SEA_REGION)) - break; - } - if (d == MAXDIRECTIONS) { - /* Schiff kann nicht aufs offene Meer */ - cmistake(u, ord, 249, MSG_MOVE); - break; - } - } - } + if (!flying_ship(sh)) { + int stormchance; + static int stormyness; + static int gamecookie = -1; + int reason; - reason = check_ship_allowed(sh, next_point); - if (reason<0) { - /* for some reason or another, we aren't allowed in there.. */ - if (check_leuchtturm(current_point, NULL) || reason == SA_NO_INSECT) { - ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point)); - } else { - float dmg = - get_param_flt(global.parameters, "rules.ship.damage.nolanding", - 0.10F); - ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh, - next_point)); - damage_ship(sh, dmg); - /* we handle destruction at the end */ - } - break; - } - - if (curse_active(get_curse(next_point->attribs, ct_find("maelstrom")))) { - if (do_maelstrom(next_point, u) == NULL) - break; - } - - } - - /* !flying_ship */ - /* Falls Blockade, endet die Seglerei hier */ - if (move_blocked(u, current_point, next_point)) { - ADDMSG(&u->faction->msgs, msg_message("sailfail", "ship region", sh, - current_point)); - break; - } - - /* Falls kein Problem, eines weiter ziehen */ - fset(sh, SF_MOVED); - if (iroute) { - add_regionlist(iroute, next_point); - iroute = &(*iroute)->next; - } - step++; - - last_point = current_point; - current_point = next_point; - - if (!fval(current_point->terrain, SEA_REGION) - && !is_cursed(sh->attribs, C_SHIP_FLYING, 0)) - break; - token = getstrtoken(); - error = movewhere(u, token, current_point, &next_point); - if (error || next_point == NULL) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - next_point = current_point; - break; - } - } - - if (sh->damage >= sh->size * DAMAGE_SCALE) { - if (sh->region) { - ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); - remove_ship(&sh->region->ships, sh); - } - sh = NULL; - } - - /* Nun enthält current_point die Region, in der das Schiff seine Runde - * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das - * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck - * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins - * Inland zu segeln versuchte */ - - if (sh != NULL && fval(sh, SF_MOVED)) { - unit *hafenmeister; - /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten - * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ - cycle_route(ord, u, step); - set_order(&u->thisorder, NULL); - if (!move_on_land) { - set_coast(sh, last_point, current_point); - } - - if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { - ADDMSG(&f->msgs, msg_message("shipfly", "ship from to", sh, - starting_point, current_point)); - } else { - ADDMSG(&f->msgs, msg_message("shipsail", "ship from to", sh, - starting_point, current_point)); - } - - /* Das Schiff und alle Einheiten darin werden nun von - * starting_point nach current_point verschoben */ - - /* Verfolgungen melden */ - if (fval(u, UFL_FOLLOWING)) - caught_target(current_point, u); - - sh = move_ship(sh, starting_point, current_point, *routep); - - /* Hafengebühren ? */ - - hafenmeister = owner_buildingtyp(current_point, bt_find("harbour")); - if (sh && hafenmeister != NULL) { - item *itm; - unit *u2; - item *trans = NULL; - - for (u2 = current_point->units; u2; u2 = u2->next) { - if (u2->ship == sh && !alliedunit(hafenmeister, u->faction, HELP_GUARD)) { - - if (effskill(hafenmeister, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { - for (itm = u2->items; itm; itm = itm->next) { - const luxury_type *ltype = resource2luxury(itm->type->rtype); - if (ltype != NULL && itm->number > 0) { - int st = itm->number * effskill(hafenmeister, SK_TRADE) / 50; - st = _min(itm->number, st); - - if (st > 0) { - i_change(&u2->items, itm->type, -st); - i_change(&hafenmeister->items, itm->type, st); - i_add(&trans, i_new(itm->type, st)); + if (gamecookie != global.cookie) { + bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1) != 0; + if (storms_enabled) { + gamedate date; + get_gamedate(turn, &date); + stormyness = storms ? storms[date.month] * 5 : 0; } - } + gamecookie = global.cookie; + } + + /* storms should be the first thing we do. */ + stormchance = stormyness / shipspeed(sh, u); + if (check_leuchtturm(next_point, NULL)) { + int param = get_param_int(global.parameters, "rules.lighthous.stormchancedevisor", 0); + if (param > 0) { + stormchance /= param; + } + else { + stormchance = 0; + } + } + if (rng_int() % 10000 < stormchance * sh->type->storm + && fval(current_point->terrain, SEA_REGION)) { + if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + region *rnext = NULL; + bool storm = true; + int d_offset = rng_int() % MAXDIRECTIONS; + direction_t d; + /* Sturm nur, wenn nächste Region Hochsee ist. */ + for (d = 0; d != MAXDIRECTIONS; ++d) { + direction_t dnext = (direction_t)((d + d_offset) % MAXDIRECTIONS); + region *rn = rconnect(current_point, dnext); + + if (rn != NULL) { + if (fval(rn->terrain, FORBIDDEN_REGION)) + continue; + if (!fval(rn->terrain, SEA_REGION)) { + storm = false; + break; + } + if (rn != next_point) + rnext = rn; + } + } + if (storm && rnext != NULL) { + ADDMSG(&f->msgs, msg_message("storm", "ship region sink", + sh, current_point, sh->damage >= sh->size * DAMAGE_SCALE)); + + /* damage the ship. we handle destruction in the end */ + damage_ship(sh, damage_drift()); + if (sh->damage >= sh->size * DAMAGE_SCALE) + break; + + next_point = rnext; + /* these values need to be updated if next_point changes (due to storms): */ + tnext = next_point->terrain; + } + } + } + + if (!fval(tthis, SEA_REGION)) { + if (!fval(tnext, SEA_REGION)) { + if (!move_on_land) { + /* check that you're not traveling from one land region to another. */ + ADDMSG(&u->faction->msgs, msg_message("shipnoshore", + "ship region", sh, next_point)); + break; + } + } + else { + if (!check_takeoff(sh, current_point, next_point)) { + /* Schiff kann nicht ablegen */ + cmistake(u, ord, 182, MSG_MOVE); + break; + } + } + } + else if (fval(tnext, SEA_REGION)) { + /* target region is an ocean, and we're not leaving a shore */ + if (!(sh->type->flags & SFL_OPENSEA)) { + /* ship can only stay close to shore */ + direction_t d; + + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rc = rconnect(next_point, d); + if (rc == NULL || !fval(rc->terrain, SEA_REGION)) + break; + } + if (d == MAXDIRECTIONS) { + /* Schiff kann nicht aufs offene Meer */ + cmistake(u, ord, 249, MSG_MOVE); + break; + } + } + } + + reason = check_ship_allowed(sh, next_point); + if (reason < 0) { + /* for some reason or another, we aren't allowed in there.. */ + if (check_leuchtturm(current_point, NULL) || reason == SA_NO_INSECT) { + ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point)); + } + else { + float dmg = + get_param_flt(global.parameters, "rules.ship.damage.nolanding", + 0.10F); + ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh, + next_point)); + damage_ship(sh, dmg); + /* we handle destruction at the end */ + } + break; + } + + if (curse_active(get_curse(next_point->attribs, ct_find("maelstrom")))) { + if (do_maelstrom(next_point, u) == NULL) + break; + } + + } + + /* !flying_ship */ + /* Falls Blockade, endet die Seglerei hier */ + if (move_blocked(u, current_point, next_point)) { + ADDMSG(&u->faction->msgs, msg_message("sailfail", "ship region", sh, + current_point)); + break; + } + + /* Falls kein Problem, eines weiter ziehen */ + fset(sh, SF_MOVED); + if (iroute) { + add_regionlist(iroute, next_point); + iroute = &(*iroute)->next; + } + step++; + + last_point = current_point; + current_point = next_point; + + if (!fval(current_point->terrain, SEA_REGION) + && !is_cursed(sh->attribs, C_SHIP_FLYING, 0)) + break; + token = getstrtoken(); + error = movewhere(u, token, current_point, &next_point); + if (error || next_point == NULL) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next_point = current_point; + break; + } + } + + if (sh->damage >= sh->size * DAMAGE_SCALE) { + if (sh->region) { + ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); + remove_ship(&sh->region->ships, sh); + } + sh = NULL; + } + + /* Nun enthält current_point die Region, in der das Schiff seine Runde + * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das + * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck + * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins + * Inland zu segeln versuchte */ + + if (sh != NULL && fval(sh, SF_MOVED)) { + unit *hafenmeister; + /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten + * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ + cycle_route(ord, u, step); + set_order(&u->thisorder, NULL); + if (!move_on_land) { + set_coast(sh, last_point, current_point); + } + + if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { + ADDMSG(&f->msgs, msg_message("shipfly", "ship from to", sh, + starting_point, current_point)); + } + else { + ADDMSG(&f->msgs, msg_message("shipsail", "ship from to", sh, + starting_point, current_point)); + } + + /* Das Schiff und alle Einheiten darin werden nun von + * starting_point nach current_point verschoben */ + + /* Verfolgungen melden */ + if (fval(u, UFL_FOLLOWING)) + caught_target(current_point, u); + + sh = move_ship(sh, starting_point, current_point, *routep); + + /* Hafengebühren ? */ + + hafenmeister = owner_buildingtyp(current_point, bt_find("harbour")); + if (sh && hafenmeister != NULL) { + item *itm; + unit *u2; + item *trans = NULL; + + for (u2 = current_point->units; u2; u2 = u2->next) { + if (u2->ship == sh && !alliedunit(hafenmeister, u->faction, HELP_GUARD)) { + + if (effskill(hafenmeister, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { + for (itm = u2->items; itm; itm = itm->next) { + const luxury_type *ltype = resource2luxury(itm->type->rtype); + if (ltype != NULL && itm->number > 0) { + int st = itm->number * effskill(hafenmeister, SK_TRADE) / 50; + st = _min(itm->number, st); + + if (st > 0) { + i_change(&u2->items, itm->type, -st); + i_change(&hafenmeister->items, itm->type, st); + i_add(&trans, i_new(itm->type, st)); + } + } + } + } + } + } + if (trans) { + message *msg = + msg_message("harbor_trade", "unit items ship", hafenmeister, trans, + u->ship); + add_message(&u->faction->msgs, msg); + add_message(&hafenmeister->faction->msgs, msg); + msg_release(msg); + while (trans) + i_remove(&trans, trans); } - } } - } - if (trans) { - message *msg = - msg_message("harbor_trade", "unit items ship", hafenmeister, trans, - u->ship); - add_message(&u->faction->msgs, msg); - add_message(&hafenmeister->faction->msgs, msg); - msg_release(msg); - while (trans) - i_remove(&trans, trans); - } } - } } unit *get_captain(const ship * sh) { - const region *r = sh->region; - unit *u; + const region *r = sh->region; + unit *u; - for (u = r->units; u; u = u->next) { - if (u->ship == sh && u->number - && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) - return u; - } + for (u = r->units; u; u = u->next) { + if (u->ship == sh && u->number + && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) + return u; + } - return NULL; + return NULL; } -/* Segeln, Wandern, Reiten -* when this routine returns a non-zero value, movement for the region needs -* to be done again because of followers that got new MOVE orders. +/* Segeln, Wandern, Reiten +* when this routine returns a non-zero value, movement for the region needs +* to be done again because of followers that got new MOVE orders. * Setting FL_LONGACTION will prevent a unit from being handled more than once -* by this routine +* by this routine * * the token parser needs to be initialized before calling this function! */ -/** fleeing units use this function +/** fleeing units use this function */ void run_to(unit * u, region * to) { - region_list *route = NULL; - add_regionlist(&route, to); - travel_route(u, route, NULL, NULL, TRAVEL_RUNNING); - free_regionlist(route); - /* weder transport noch follow */ + region_list *route = NULL; + add_regionlist(&route, to); + travel_route(u, route, NULL, NULL, TRAVEL_RUNNING); + free_regionlist(route); + /* weder transport noch follow */ } static const region_list *travel_i(unit * u, const region_list * route_begin, - const region_list * route_end, order * ord, int mode, follower ** followers) + const region_list * route_end, order * ord, int mode, follower ** followers) { - region *r = u->region; + region *r = u->region; - if (u->building && !can_leave(u)) { - cmistake(u, u->thisorder, 150, MSG_MOVE); - return route_begin; - } - switch (canwalk(u)) { - case E_CANWALK_TOOHEAVY: - cmistake(u, ord, 57, MSG_MOVE); - return route_begin; - case E_CANWALK_TOOMANYHORSES: - cmistake(u, ord, 56, MSG_MOVE); - return route_begin; - case E_CANWALK_TOOMANYCARTS: - cmistake(u, ord, 42, MSG_MOVE); - return route_begin; - } - route_end = cap_route(r, route_begin, route_end, movement_speed(u)); - - route_end = travel_route(u, route_begin, route_end, ord, mode); - get_followers(u, r, route_end, followers); - - /* transportation */ - for (ord = u->orders; ord; ord = ord->next) { - unit *ut; - - if (getkeyword(ord) != K_TRANSPORT) - continue; - - init_tokens(ord); - skip_token(); - ut = getunit(r, u->faction); - if (ut != NULL) { - if (getkeyword(ut->thisorder) == K_DRIVE) { - if (ut->building && !can_leave(ut)) { - cmistake(ut, ut->thisorder, 150, MSG_MOVE); - cmistake(u, ord, 99, MSG_MOVE); - } else if (!can_move(ut)) { - cmistake(u, ord, 99, MSG_MOVE); - } else { - bool found = false; - - if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { - init_tokens(ut->thisorder); - skip_token(); - if (getunit(u->region, ut->faction) == u) { - const region_list *route_to = - travel_route(ut, route_begin, route_end, ord, - TRAVEL_TRANSPORTED); - - if (route_to != route_begin) { - get_followers(ut, r, route_to, followers); - } - ADDMSG(&ut->faction->msgs, msg_message("transport", - "unit target start end", u, ut, r, ut->region)); - found = true; - } - } - if (!found) { - if (cansee(u->faction, u->region, ut, 0)) { - cmistake(u, ord, 90, MSG_MOVE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - } - } - } - } - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); + if (u->building && !can_leave(u)) { + cmistake(u, u->thisorder, 150, MSG_MOVE); + return route_begin; } - } - return route_end; + switch (canwalk(u)) { + case E_CANWALK_TOOHEAVY: + cmistake(u, ord, 57, MSG_MOVE); + return route_begin; + case E_CANWALK_TOOMANYHORSES: + cmistake(u, ord, 56, MSG_MOVE); + return route_begin; + case E_CANWALK_TOOMANYCARTS: + cmistake(u, ord, 42, MSG_MOVE); + return route_begin; + } + route_end = cap_route(r, route_begin, route_end, movement_speed(u)); + + route_end = travel_route(u, route_begin, route_end, ord, mode); + get_followers(u, r, route_end, followers); + + /* transportation */ + for (ord = u->orders; ord; ord = ord->next) { + unit *ut; + + if (getkeyword(ord) != K_TRANSPORT) + continue; + + init_tokens(ord); + skip_token(); + ut = getunit(r, u->faction); + if (ut != NULL) { + if (getkeyword(ut->thisorder) == K_DRIVE) { + if (ut->building && !can_leave(ut)) { + cmistake(ut, ut->thisorder, 150, MSG_MOVE); + cmistake(u, ord, 99, MSG_MOVE); + } + else if (!can_move(ut)) { + cmistake(u, ord, 99, MSG_MOVE); + } + else { + bool found = false; + + if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + init_tokens(ut->thisorder); + skip_token(); + if (getunit(u->region, ut->faction) == u) { + const region_list *route_to = + travel_route(ut, route_begin, route_end, ord, + TRAVEL_TRANSPORTED); + + if (route_to != route_begin) { + get_followers(ut, r, route_to, followers); + } + ADDMSG(&ut->faction->msgs, msg_message("transport", + "unit target start end", u, ut, r, ut->region)); + found = true; + } + } + if (!found) { + if (cansee(u->faction, u->region, ut, 0)) { + cmistake(u, ord, 90, MSG_MOVE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + } + } + } + } + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + } + } + return route_end; } /** traveling without ships @@ -2105,556 +2131,571 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, */ static void travel(unit * u, region_list ** routep) { - region *r = u->region; - region_list *route_begin = NULL; - follower *followers = NULL; + region *r = u->region; + region_list *route_begin = NULL; + follower *followers = NULL; - if (routep) - *routep = NULL; + if (routep) + *routep = NULL; - /* a few pre-checks that need not be done for each step: */ - if (!fval(r->terrain, SEA_REGION)) { - ship *sh = u->ship; + /* a few pre-checks that need not be done for each step: */ + if (!fval(r->terrain, SEA_REGION)) { + ship *sh = u->ship; - if (!can_leave(u)) { - cmistake(u, u->thisorder, 150, MSG_MOVE); - return; + if (!can_leave(u)) { + cmistake(u, u->thisorder, 150, MSG_MOVE); + return; + } + + /* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */ + if (sh == NULL) { + sh = leftship(u); + if (sh && sh->region != u->region) + sh = NULL; + } + if (sh) { + unit *guard = is_guarded(r, u, GUARD_LANDING); + if (guard) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "region_guarded", "guard", guard)); + return; + } + } + if (u->ship && u_race(u)->flags & RCF_SWIM) { + cmistake(u, u->thisorder, 143, MSG_MOVE); + return; + } } - - /* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */ - if (sh == NULL) { - sh = leftship(u); - if (sh && sh->region != u->region) - sh = NULL; - } - if (sh) { - unit *guard = is_guarded(r, u, GUARD_LANDING); - if (guard) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "region_guarded", "guard", guard)); + else if (u->ship && fval(u->ship, SF_MOVED)) { + /* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */ + cmistake(u, u->thisorder, 13, MSG_MOVE); return; - } } - if (u->ship && u_race(u)->flags & RCF_SWIM) { - cmistake(u, u->thisorder, 143, MSG_MOVE); - return; + + make_route(u, u->thisorder, routep); + route_begin = *routep; + + /* und ab die post: */ + travel_i(u, route_begin, NULL, u->thisorder, TRAVEL_NORMAL, &followers); + + /* followers */ + while (followers != NULL) { + follower *fnext = followers->next; + unit *uf = followers->uf; + unit *ut = followers->ut; + const region_list *route_end = followers->route_end; + + free(followers); + followers = fnext; + + if (uf->region == r) { + order *follow_order; + const struct locale *lang = u->faction->locale; + + /* construct an order */ + follow_order = create_order(K_FOLLOW, lang, "%s %i", + LOC(uf->faction->locale, parameters[P_UNIT]), ut->no); + + route_end = reroute(uf, route_begin, route_end); + travel_i(uf, route_begin, route_end, follow_order, TRAVEL_FOLLOWING, + &followers); + caught_target(uf->region, uf); + free_order(follow_order); + } } - } else if (u->ship && fval(u->ship, SF_MOVED)) { - /* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */ - cmistake(u, u->thisorder, 13, MSG_MOVE); - return; - } - - make_route(u, u->thisorder, routep); - route_begin = *routep; - - /* und ab die post: */ - travel_i(u, route_begin, NULL, u->thisorder, TRAVEL_NORMAL, &followers); - - /* followers */ - while (followers != NULL) { - follower *fnext = followers->next; - unit *uf = followers->uf; - unit *ut = followers->ut; - const region_list *route_end = followers->route_end; - - free(followers); - followers = fnext; - - if (uf->region == r) { - order *follow_order; - const struct locale *lang = u->faction->locale; - - /* construct an order */ - follow_order = create_order(K_FOLLOW, lang, "%s %i", - LOC(uf->faction->locale, parameters[P_UNIT]), ut->no); - - route_end = reroute(uf, route_begin, route_end); - travel_i(uf, route_begin, route_end, follow_order, TRAVEL_FOLLOWING, - &followers); - caught_target(uf->region, uf); - free_order(follow_order); - } - } } static void move(unit * u, bool move_on_land) { - region_list *route = NULL; + region_list *route = NULL; - assert(u->number); - if (u->ship && u==ship_owner(u->ship)) { - sail(u, u->thisorder, move_on_land, &route); - } else { - travel(u, &route); - } + assert(u->number); + if (u->ship && u == ship_owner(u->ship)) { + sail(u, u->thisorder, move_on_land, &route); + } + else { + travel(u, &route); + } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - set_order(&u->thisorder, NULL); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + set_order(&u->thisorder, NULL); - if (route != NULL) - free_regionlist(route); + if (route != NULL) + free_regionlist(route); } typedef struct piracy_data { - const struct faction *pirate; - const struct faction *target; - direction_t dir; + const struct faction *pirate; + const struct faction *target; + direction_t dir; } piracy_data; static void piracy_init(struct attrib *a) { - a->data.v = calloc(1, sizeof(piracy_data)); + a->data.v = calloc(1, sizeof(piracy_data)); } static void piracy_done(struct attrib *a) { - free(a->data.v); + free(a->data.v); } static attrib_type at_piracy_direction = { - "piracy_direction", - piracy_init, - piracy_done, - DEFAULT_AGE, - NO_WRITE, - NO_READ + "piracy_direction", + piracy_init, + piracy_done, + DEFAULT_AGE, + NO_WRITE, + NO_READ }; static attrib *mk_piracy(const faction * pirate, const faction * target, - direction_t target_dir) + direction_t target_dir) { - attrib *a = a_new(&at_piracy_direction); - piracy_data *data = a->data.v; - data->pirate = pirate; - data->target = target; - data->dir = target_dir; - return a; + attrib *a = a_new(&at_piracy_direction); + piracy_data *data = a->data.v; + data->pirate = pirate; + data->target = target; + data->dir = target_dir; + return a; } static void piracy_cmd(unit * u, struct order *ord) { - region *r = u->region; - ship *sh = u->ship, *sh2; - direction_t dir, target_dir = NODIRECTION; - struct { - const faction *target; - int value; - } aff[MAXDIRECTIONS]; - int saff = 0; - int *il = NULL; - const char *s; - attrib *a; + region *r = u->region; + ship *sh = u->ship, *sh2; + direction_t dir, target_dir = NODIRECTION; + struct { + const faction *target; + int value; + } aff[MAXDIRECTIONS]; + int saff = 0; + int *il = NULL; + const char *s; + attrib *a; - if (!sh) { - cmistake(u, ord, 144, MSG_MOVE); - return; - } - - if (!u->ship || u!=ship_owner(u->ship)) { - cmistake(u, ord, 146, MSG_MOVE); - return; - } - - /* Feststellen, ob schon ein anderer alliierter Pirat ein - * Ziel gefunden hat. */ - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - if (s != NULL && *s) { - il = intlist_init(); - while (s && *s) { - il = intlist_add(il, atoi36(s)); - s = getstrtoken(); + if (!sh) { + cmistake(u, ord, 144, MSG_MOVE); + return; } - } - for (a = a_find(r->attribs, &at_piracy_direction); - a && a->type == &at_piracy_direction; a = a->next) { - piracy_data *data = a->data.v; - const faction *p = data->pirate; - const faction *t = data->target; - - if (alliedunit(u, p, HELP_FIGHT)) { - if (il == 0 || (t && intlist_find(il, t->no))) { - target_dir = data->dir; - break; - } + if (!u->ship || u != ship_owner(u->ship)) { + cmistake(u, ord, 146, MSG_MOVE); + return; } - } - /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ + /* Feststellen, ob schon ein anderer alliierter Pirat ein + * Ziel gefunden hat. */ - if (target_dir == NODIRECTION) { - /* Einheit ist also Kapitän. Jetzt gucken, in wievielen - * Nachbarregionen potentielle Opfer sind. */ + init_tokens(ord); + skip_token(); + s = getstrtoken(); + if (s != NULL && *s) { + il = intlist_init(); + while (s && *s) { + il = intlist_add(il, atoi36(s)); + s = getstrtoken(); + } + } - for (dir = 0; dir < MAXDIRECTIONS; dir++) { - region *rc = rconnect(r, dir); - aff[dir].value = 0; - aff[dir].target = 0; - if (rc && fval(rc->terrain, SWIM_INTO) && check_takeoff(sh, r, rc)) { + for (a = a_find(r->attribs, &at_piracy_direction); + a && a->type == &at_piracy_direction; a = a->next) { + piracy_data *data = a->data.v; + const faction *p = data->pirate; + const faction *t = data->target; - for (sh2 = rc->ships; sh2; sh2 = sh2->next) { - unit *cap = ship_owner(sh2); - if (cap) { - faction *f = visible_faction(cap->faction, cap); - if (alliedunit(u, f, HELP_FIGHT)) - continue; - if (il == 0 || intlist_find(il, cap->faction->no)) { - ++aff[dir].value; - if (rng_int() % aff[dir].value == 0) { - aff[dir].target = f; - } + if (alliedunit(u, p, HELP_FIGHT)) { + if (il == 0 || (t && intlist_find(il, t->no))) { + target_dir = data->dir; + break; + } + } + } + + /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ + + if (target_dir == NODIRECTION) { + /* Einheit ist also Kapitän. Jetzt gucken, in wievielen + * Nachbarregionen potentielle Opfer sind. */ + + for (dir = 0; dir < MAXDIRECTIONS; dir++) { + region *rc = rconnect(r, dir); + aff[dir].value = 0; + aff[dir].target = 0; + if (rc && fval(rc->terrain, SWIM_INTO) && check_takeoff(sh, r, rc)) { + + for (sh2 = rc->ships; sh2; sh2 = sh2->next) { + unit *cap = ship_owner(sh2); + if (cap) { + faction *f = visible_faction(cap->faction, cap); + if (alliedunit(u, f, HELP_FIGHT)) + continue; + if (il == 0 || intlist_find(il, cap->faction->no)) { + ++aff[dir].value; + if (rng_int() % aff[dir].value == 0) { + aff[dir].target = f; + } + } + } + } + + /* Und aufaddieren. */ + saff += aff[dir].value; } - } } - /* Und aufaddieren. */ - saff += aff[dir].value; - } + if (saff != 0) { + saff = rng_int() % saff; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + if (saff < aff[dir].value) + break; + saff -= aff[dir].value; + } + target_dir = dir; + a = + a_add(&r->attribs, mk_piracy(u->faction, aff[dir].target, target_dir)); + } } - if (saff != 0) { - saff = rng_int() % saff; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - if (saff < aff[dir].value) - break; - saff -= aff[dir].value; - } - target_dir = dir; - a = - a_add(&r->attribs, mk_piracy(u->faction, aff[dir].target, target_dir)); + free(il); + + /* Wenn kein Ziel gefunden, entsprechende Meldung generieren */ + if (target_dir == NODIRECTION) { + ADDMSG(&u->faction->msgs, msg_message("piratenovictim", + "ship region", sh, r)); + return; } - } - free(il); + /* Meldung generieren */ + ADDMSG(&u->faction->msgs, msg_message("piratesawvictim", + "ship region dir", sh, r, target_dir)); - /* Wenn kein Ziel gefunden, entsprechende Meldung generieren */ - if (target_dir == NODIRECTION) { - ADDMSG(&u->faction->msgs, msg_message("piratenovictim", - "ship region", sh, r)); - return; - } + /* Befehl konstruieren */ + set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", + LOC(u->faction->locale, directions[target_dir]))); - /* Meldung generieren */ - ADDMSG(&u->faction->msgs, msg_message("piratesawvictim", - "ship region dir", sh, r, target_dir)); - - /* Befehl konstruieren */ - set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", - LOC(u->faction->locale, directions[target_dir]))); - - /* Bewegung ausführen */ - init_tokens(u->thisorder); - skip_token(); - move(u, true); + /* Bewegung ausführen */ + init_tokens(u->thisorder); + skip_token(); + move(u, true); } static void age_traveldir(region * r) { - attrib *a = a_find(r->attribs, &at_traveldir); + attrib *a = a_find(r->attribs, &at_traveldir); - while (a && a->type == &at_traveldir) { - attrib *an = a->next; - a->data.ca[3]--; - if (a->data.ca[3] <= 0) { - a_remove(&r->attribs, a); + while (a && a->type == &at_traveldir) { + attrib *an = a->next; + a->data.ca[3]--; + if (a->data.ca[3] <= 0) { + a_remove(&r->attribs, a); + } + a = an; } - a = an; - } } static direction_t hunted_dir(attrib * at, int id) { - attrib *a = a_find(at, &at_shiptrail); - direction_t d = NODIRECTION; + attrib *a = a_find(at, &at_shiptrail); + direction_t d = NODIRECTION; - while (a != NULL && a->type == &at_shiptrail) { - traveldir *t = (traveldir *) (a->data.v); - if (t->no == id) { - d = t->dir; - /* do not break, because we want the last one for this ship */ + while (a != NULL && a->type == &at_shiptrail) { + traveldir *t = (traveldir *)(a->data.v); + if (t->no == id) { + d = t->dir; + /* do not break, because we want the last one for this ship */ + } + a = a->next; } - a = a->next; - } - return d; + return d; } static int hunt(unit * u, order * ord) { - region *rc = u->region; - int bytes, moves, id, speed; - char command[256], *bufp = command; - size_t size = sizeof(command); - direction_t dir; + region *rc = u->region; + int bytes, moves, id, speed; + char command[256], *bufp = command; + size_t size = sizeof(command); + direction_t dir; - if (fval(u, UFL_NOTMOVING)) { - return 0; - } else if (!u->ship) { - cmistake(u, ord, 144, MSG_MOVE); - return 0; - } else if (u!=ship_owner(u->ship)) { - cmistake(u, ord, 146, MSG_MOVE); - return 0; - } else if (!can_move(u)) { - cmistake(u, ord, 55, MSG_MOVE); - return 0; - } - - id = getshipid(); - - if (id <= 0) { - cmistake(u, ord, 20, MSG_MOVE); - return 0; - } - - dir = hunted_dir(rc->attribs, id); - - if (dir == NODIRECTION) { - ship *sh = findship(id); - if (sh == NULL || sh->region != rc) { - cmistake(u, ord, 20, MSG_MOVE); + if (fval(u, UFL_NOTMOVING)) { + return 0; + } + else if (!u->ship) { + cmistake(u, ord, 144, MSG_MOVE); + return 0; + } + else if (u != ship_owner(u->ship)) { + cmistake(u, ord, 146, MSG_MOVE); + return 0; + } + else if (!can_move(u)) { + cmistake(u, ord, 55, MSG_MOVE); + return 0; } - return 0; - } - bufp = command; - bytes = slprintf(bufp, size, "%s %s", LOC(u->faction->locale, keyword(K_MOVE)), LOC(u->faction->locale, directions[dir])); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + id = getshipid(); - moves = 1; + if (id <= 0) { + cmistake(u, ord, 20, MSG_MOVE); + return 0; + } - speed = getuint(); - if (speed == 0) { - speed = shipspeed(u->ship, u); - } else { - int maxspeed = shipspeed(u->ship, u); - if (maxspeed < speed) - speed = maxspeed; - } - rc = rconnect(rc, dir); - while (moves < speed && (dir = hunted_dir(rc->attribs, id)) != NODIRECTION) { - bytes = (int)strlcpy(bufp, " ", size); + dir = hunted_dir(rc->attribs, id); + + if (dir == NODIRECTION) { + ship *sh = findship(id); + if (sh == NULL || sh->region != rc) { + cmistake(u, ord, 20, MSG_MOVE); + } + return 0; + } + + bufp = command; + bytes = slprintf(bufp, size, "%s %s", LOC(u->faction->locale, keyword(K_MOVE)), LOC(u->faction->locale, directions[dir])); if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - moves++; + WARN_STATIC_BUFFER(); + + moves = 1; + + speed = getuint(); + if (speed == 0) { + speed = shipspeed(u->ship, u); + } + else { + int maxspeed = shipspeed(u->ship, u); + if (maxspeed < speed) + speed = maxspeed; + } rc = rconnect(rc, dir); - } + while (moves < speed && (dir = hunted_dir(rc->attribs, id)) != NODIRECTION) { + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + moves++; + rc = rconnect(rc, dir); + } - /* In command steht jetzt das NACH-Kommando. */ + /* In command steht jetzt das NACH-Kommando. */ - /* NACH ignorieren und Parsing initialisieren. */ - igetstrtoken(command); - /* NACH ausführen */ - move(u, false); - return 1; /* true -> Einheitenliste von vorne durchgehen */ + /* NACH ignorieren und Parsing initialisieren. */ + igetstrtoken(command); + /* NACH ausführen */ + move(u, false); + return 1; /* true -> Einheitenliste von vorne durchgehen */ } void destroy_damaged_ships(void) { - region *r; - ship *sh, *shn; + region *r; + ship *sh, *shn; - for (r = regions; r; r = r->next) { - for (sh = r->ships; sh;) { - shn = sh->next; - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); - } - sh = shn; + for (r = regions; r; r = r->next) { + for (sh = r->ships; sh;) { + shn = sh->next; + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(&sh->region->ships, sh); + } + sh = shn; + } } - } } /* Bewegung, Verfolgung, Piraterie */ /** ships that folow other ships * Dann generieren die jagenden Einheiten ihre Befehle und - * bewegen sich. + * bewegen sich. * Following the trails of other ships. */ static void move_hunters(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; + for (r = regions; r; r = r->next) { + unit **up = &r->units; - while (*up != NULL) { - unit *u = *up; + while (*up != NULL) { + unit *u = *up; - if (!fval(u, UFL_MOVED | UFL_NOTMOVING)) { - order *ord; + if (!fval(u, UFL_MOVED | UFL_NOTMOVING)) { + order *ord; - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_FOLLOW) { - param_t p; + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_FOLLOW) { + param_t p; - init_tokens(ord); - skip_token(); - p = getparam(u->faction->locale); - if (p != P_SHIP) { - if (p != P_UNIT) { - cmistake(u, ord, 240, MSG_MOVE); - } - break; + init_tokens(ord); + skip_token(); + p = getparam(u->faction->locale); + if (p != P_SHIP) { + if (p != P_UNIT) { + cmistake(u, ord, 240, MSG_MOVE); + } + break; + } + + /* wir folgen definitiv einem Schiff. */ + + if (fval(u, UFL_NOTMOVING)) { + cmistake(u, ord, 52, MSG_MOVE); + break; + } + else if (!can_move(u)) { + cmistake(u, ord, 55, MSG_MOVE); + break; + } + + if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u, ord)) { + up = &r->units; + break; + } + } + } } - - /* wir folgen definitiv einem Schiff. */ - - if (fval(u, UFL_NOTMOVING)) { - cmistake(u, ord, 52, MSG_MOVE); - break; - } else if (!can_move(u)) { - cmistake(u, ord, 55, MSG_MOVE); - break; - } - - if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u, ord)) { - up = &r->units; - break; - } - } + if (*up == u) + up = &u->next; } - } - if (*up == u) - up = &u->next; } - } } -/** Piraten and Drift - * +/** Piraten and Drift + * */ static void move_pirates(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; + for (r = regions; r; r = r->next) { + unit **up = &r->units; - while (*up) { - unit *u = *up; + while (*up) { + unit *u = *up; - if (!fval(u, UFL_NOTMOVING) && getkeyword(u->thisorder) == K_PIRACY) { - piracy_cmd(u, u->thisorder); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + if (!fval(u, UFL_NOTMOVING) && getkeyword(u->thisorder) == K_PIRACY) { + piracy_cmd(u, u->thisorder); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } - if (*up == u) { - /* not moved, use next unit */ - up = &u->next; - } else if (*up && (*up)->region != r) { - /* moved the previous unit along with u (units on same ship) - * must start from the beginning again */ - up = &r->units; - } - /* else *up is already the next unit */ + if (*up == u) { + /* not moved, use next unit */ + up = &u->next; + } + else if (*up && (*up)->region != r) { + /* moved the previous unit along with u (units on same ship) + * must start from the beginning again */ + up = &r->units; + } + /* else *up is already the next unit */ + } + + a_removeall(&r->attribs, &at_piracy_direction); + age_traveldir(r); } - - a_removeall(&r->attribs, &at_piracy_direction); - age_traveldir(r); - } } void movement(void) { - int ships; + int ships; - /* Initialize the additional encumbrance by transported units */ - init_transportation(); + /* Initialize the additional encumbrance by transported units */ + init_transportation(); - /* Move ships in last phase, others first - * This is to make sure you can't land someplace and then get off the ship - * in the same turn. - */ - for (ships = 0; ships <= 1; ++ships) { - region *r = regions; - while (r != NULL) { - unit **up = &r->units; - bool repeat = false; + /* Move ships in last phase, others first + * This is to make sure you can't land someplace and then get off the ship + * in the same turn. + */ + for (ships = 0; ships <= 1; ++ships) { + region *r = regions; + while (r != NULL) { + unit **up = &r->units; + bool repeat = false; - while (*up) { - unit *u = *up; - keyword_t kword; + while (*up) { + unit *u = *up; + keyword_t kword; - if (u->ship && fval(u->ship, SF_DRIFTED)) { - up = &u->next; - continue; - } - kword = getkeyword(u->thisorder); + if (u->ship && fval(u->ship, SF_DRIFTED)) { + up = &u->next; + continue; + } + kword = getkeyword(u->thisorder); - if (kword == K_ROUTE || kword == K_MOVE) { - /* after moving, the unit has no thisorder. this prevents - * it from moving twice (or getting error messages twice). - * UFL_NOTMOVING is set in combat if the unit is not allowed - * to move because it was involved in a battle. - */ - if (fval(u, UFL_NOTMOVING)) { - if (fval(u, UFL_LONGACTION)) { - cmistake(u, u->thisorder, 52, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else { - cmistake(u, u->thisorder, 319, MSG_MOVE); - set_order(&u->thisorder, NULL); + if (kword == K_ROUTE || kword == K_MOVE) { + /* after moving, the unit has no thisorder. this prevents + * it from moving twice (or getting error messages twice). + * UFL_NOTMOVING is set in combat if the unit is not allowed + * to move because it was involved in a battle. + */ + if (fval(u, UFL_NOTMOVING)) { + if (fval(u, UFL_LONGACTION)) { + cmistake(u, u->thisorder, 52, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else { + cmistake(u, u->thisorder, 319, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + } + else if (fval(u, UFL_MOVED)) { + cmistake(u, u->thisorder, 187, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else if (!can_move(u)) { + cmistake(u, u->thisorder, 55, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else { + if (ships) { + if (u->ship && ship_owner(u->ship) == u) { + init_tokens(u->thisorder); + skip_token(); + move(u, false); + } + } + else { + if (!u->ship || ship_owner(u->ship) != u) { + init_tokens(u->thisorder); + skip_token(); + move(u, false); + } + } + } + } + if (u->region == r) { + /* not moved, use next unit */ + up = &u->next; + } + else { + if (*up && (*up)->region != r) { + /* moved the upcoming unit along with u (units on ships or followers, + * for example). must start from the beginning again immediately */ + up = &r->units; + repeat = false; + } + else { + repeat = true; + } + } + /* else *up is already the next unit */ } - } else if (fval(u, UFL_MOVED)) { - cmistake(u, u->thisorder, 187, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else if (!can_move(u)) { - cmistake(u, u->thisorder, 55, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else { - if (ships) { - if (u->ship && ship_owner(u->ship)==u) { - init_tokens(u->thisorder); - skip_token(); - move(u, false); - } - } else { - if (!u->ship || ship_owner(u->ship)!=u) { - init_tokens(u->thisorder); - skip_token(); - move(u, false); - } + if (repeat) + continue; + if (ships == 0) { + /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ + drifting_ships(r); } - } + r = r->next; } - if (u->region == r) { - /* not moved, use next unit */ - up = &u->next; - } else { - if (*up && (*up)->region != r) { - /* moved the upcoming unit along with u (units on ships or followers, - * for example). must start from the beginning again immediately */ - up = &r->units; - repeat = false; - } else { - repeat = true; - } - } - /* else *up is already the next unit */ - } - if (repeat) - continue; - if (ships == 0) { - /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ - drifting_ships(r); - } - r = r->next; } - } - move_hunters(); - move_pirates(); + move_hunters(); + move_pirates(); } /** Overrides long orders with a FOLLOW order if the target is moving. @@ -2662,124 +2703,126 @@ void movement(void) */ void follow_unit(unit * u) { - region *r = u->region; - attrib *a = NULL; - order *ord; - unit *u2 = NULL; - int followship = false; + region *r = u->region; + attrib *a = NULL; + order *ord; + unit *u2 = NULL; + int followship = false; - if (fval(u, UFL_NOTMOVING) || LongHunger(u)) - return; + if (fval(u, UFL_NOTMOVING) || LongHunger(u)) + return; - for (ord = u->orders; ord; ord = ord->next) { - const struct locale *lang = u->faction->locale; + for (ord = u->orders; ord; ord = ord->next) { + const struct locale *lang = u->faction->locale; - if (getkeyword(ord) == K_FOLLOW) { - init_tokens(ord); - skip_token(); - int id; - param_t p = getparam(lang); - if (p == P_UNIT) { - id = read_unitid(u->faction, r); + if (getkeyword(ord) == K_FOLLOW) { + init_tokens(ord); + skip_token(); + int id; + param_t p = getparam(lang); + if (p == P_UNIT) { + id = read_unitid(u->faction, r); - if (a != NULL) { - a = a_find(u->attribs, &at_follow); + if (a != NULL) { + a = a_find(u->attribs, &at_follow); + } + + if (id > 0) { + unit *uf = findunit(id); + if (!a) { + a = a_add(&u->attribs, make_follow(uf)); + } + else { + a->data.v = uf; + } + } + else if (a) { + a_remove(&u->attribs, a); + a = NULL; + } + } + if (p == P_SHIP) { + id = getshipid(); + if (id <= 0) { + /* cmistake(u, ord, 20, MSG_MOVE); */ + } + else { + ship *sh = findship(id); + if (sh == NULL || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) { + cmistake(u, ord, 20, MSG_MOVE); + } + else if (!u->ship) { + /* cmistake(u, ord, 144, MSG_MOVE); */ + } + else if (u != ship_owner(u->ship)) { + /* cmistake(u, ord, 146, MSG_MOVE); */ + } + else if (!can_move(u)) { + /* cmistake(u, ord, 55, MSG_MOVE); */ + } + else { + u2 = ship_owner(sh); + followship = true; + } + } + } } - - if (id > 0) { - unit *uf = findunit(id); - if (!a) { - a = a_add(&u->attribs, make_follow(uf)); - } else { - a->data.v = uf; - } - } else if (a) { - a_remove(&u->attribs, a); - a = NULL; - } - } - if (p == P_SHIP) { - id = getshipid(); - if (id <= 0) { - /* cmistake(u, ord, 20, MSG_MOVE); */ - } - else { - ship *sh = findship(id); - if (sh == NULL || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) { - cmistake(u, ord, 20, MSG_MOVE); - } - else if (!u->ship) { - /* cmistake(u, ord, 144, MSG_MOVE); */ - } - else if (u != ship_owner(u->ship)) { - /* cmistake(u, ord, 146, MSG_MOVE); */ - } - else if (!can_move(u)) { - /* cmistake(u, ord, 55, MSG_MOVE); */ - } - else { - u2 = ship_owner(sh); - followship = true; - } - } - } - } - } - - if ((a || followship )&& !fval(u, UFL_MOVED | UFL_NOTMOVING)) { - if (!followship) { - u2 = a->data.v; - } - bool follow = false; - - if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { - return; } - switch (getkeyword(u2->thisorder)) { - case K_MOVE: - case K_ROUTE: - follow = true; - break; - case K_DRIVE: - if (!followship) { - follow = true; - } - break; - default: - for (ord = u2->orders; ord; ord = ord->next) { - switch (getkeyword(ord)) { - case K_FOLLOW: - follow = true; - break; - case K_PIRACY: - if (followship) { - follow = true; - } - break; + if ((a || followship) && !fval(u, UFL_MOVED | UFL_NOTMOVING)) { + if (!followship) { + u2 = a->data.v; + } + bool follow = false; + + if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { + return; + } + + switch (getkeyword(u2->thisorder)) { + case K_MOVE: + case K_ROUTE: + follow = true; + break; + case K_DRIVE: + if (!followship) { + follow = true; + } + break; default: - if (followship && u2->region != r) { - follow = true; - break; - } - continue; + for (ord = u2->orders; ord; ord = ord->next) { + switch (getkeyword(ord)) { + case K_FOLLOW: + follow = true; + break; + case K_PIRACY: + if (followship) { + follow = true; + } + break; + default: + if (followship && u2->region != r) { + follow = true; + break; + } + continue; + } + break; + } + break; + } + if (!follow) { + attrib *a2 = a_find(u2->attribs, &at_follow); + if (a2 != NULL) { + unit *u3 = a2->data.v; + follow = (u3 && u2->region == u3->region); + } + } + if (follow) { + fset(u, UFL_FOLLOWING); + fset(u2, UFL_FOLLOWED); + /* FOLLOW unit on a (potentially) moving unit prevents long orders */ + set_order(&u->thisorder, NULL); } - break; - } - break; } - if (!follow) { - attrib *a2 = a_find(u2->attribs, &at_follow); - if (a2 != NULL) { - unit *u3 = a2->data.v; - follow = (u3 && u2->region == u3->region); - } - } - if (follow) { - fset(u, UFL_FOLLOWING); - fset(u2, UFL_FOLLOWED); - /* FOLLOW unit on a (potentially) moving unit prevents long orders */ - set_order(&u->thisorder, NULL); - } - } } diff --git a/src/kernel/order.c b/src/kernel/order.c index b23cd4652..22baf4af5 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -1,14 +1,14 @@ /* vi: set ts=2: - +-------------------+ + +-------------------+ | | Christian Schlittchen | Eressea PBEM host | Enno Rehling | (c) 1998 - 2004 | Katja Zedel | | - +-------------------+ + +-------------------+ This program may not be used, modified or distributed without prior permission by the authors of Eressea. -*/ + */ #include #include @@ -35,58 +35,58 @@ # define ORD_STRING(ord) (ord)->data->_str typedef struct locale_data { - struct order_data *short_orders[MAXKEYWORDS]; - struct order_data *study_orders[MAXSKILLS]; - const struct locale *lang; + struct order_data *short_orders[MAXKEYWORDS]; + struct order_data *study_orders[MAXSKILLS]; + const struct locale *lang; } locale_data; static struct locale_data *locale_array[16]; static int nlocales = 0; typedef struct order_data { - char *_str; + char *_str; # ifdef LOMEM - int _refcount:20; - int _lindex:4; + int _refcount:20; + int _lindex:4; # else - int _refcount; - int _lindex; + int _refcount; + int _lindex; # endif - keyword_t _keyword; + keyword_t _keyword; } order_data; static void release_data(order_data * data) { - if (data) { - if (--data->_refcount == 0) { - if (data->_str) - free(data->_str); - free(data); + if (data) { + if (--data->_refcount == 0) { + if (data->_str) + free(data->_str); + free(data); + } } - } } void replace_order(order ** dlist, order * orig, const order * src) { - while (*dlist != NULL) { - order *dst = *dlist; - if (dst->data == orig->data) { - order *cpy = copy_order(src); - *dlist = cpy; - cpy->next = dst->next; - dst->next = 0; - free_order(dst); + while (*dlist != NULL) { + order *dst = *dlist; + if (dst->data == orig->data) { + order *cpy = copy_order(src); + *dlist = cpy; + cpy->next = dst->next; + dst->next = 0; + free_order(dst); + } + dlist = &(*dlist)->next; } - dlist = &(*dlist)->next; - } } keyword_t getkeyword(const order * ord) { - if (ord == NULL) { - return NOKEYWORD; - } - return ORD_KEYWORD(ord); + if (ord == NULL) { + return NOKEYWORD; + } + return ORD_KEYWORD(ord); } /** returns a plain-text representation of the order. @@ -103,7 +103,8 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { if (size > 0) { *bufp++ = '@'; --size; - } else { + } + else { WARN_STATIC_BUFFER(); } } @@ -116,7 +117,8 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { bytes = (int)strlcpy(bufp, str, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (text) *bufp++ = ' '; - } else { + } + else { WARN_STATIC_BUFFER(); } } @@ -141,205 +143,208 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { char *getcommand(const order * ord) { - char sbuffer[DISPLAYSIZE * 2]; - return _strdup(get_command(ord, sbuffer, sizeof(sbuffer))); + char sbuffer[DISPLAYSIZE * 2]; + return _strdup(get_command(ord, sbuffer, sizeof(sbuffer))); } void free_order(order * ord) { - if (ord != NULL) { - assert(ord->next == 0); + if (ord != NULL) { + assert(ord->next == 0); - release_data(ord->data); - free(ord); - } + release_data(ord->data); + free(ord); + } } order *copy_order(const order * src) { - if (src != NULL) { - order *ord = (order *) malloc(sizeof(order)); - ord->next = NULL; - ord->_persistent = src->_persistent; - ord->data = src->data; - ++ord->data->_refcount; - return ord; - } - return NULL; + if (src != NULL) { + order *ord = (order *)malloc(sizeof(order)); + ord->next = NULL; + ord->_persistent = src->_persistent; + ord->data = src->data; + ++ord->data->_refcount; + return ord; + } + return NULL; } void set_order(struct order **destp, struct order *src) { - if (*destp == src) - return; - free_order(*destp); - *destp = src; + if (*destp == src) + return; + free_order(*destp); + *destp = src; } void free_orders(order ** olist) { - while (*olist) { - order *ord = *olist; - *olist = ord->next; - ord->next = NULL; - free_order(ord); - } + while (*olist) { + order *ord = *olist; + *olist = ord->next; + ord->next = NULL; + free_order(ord); + } } static order_data *create_data(keyword_t kwd, const char *sptr, int lindex) { - const char *s = sptr; - order_data *data; - const struct locale *lang = locale_array[lindex]->lang; + const char *s = sptr; + order_data *data; + const struct locale *lang = locale_array[lindex]->lang; - if (kwd != NOKEYWORD) - s = (*sptr) ? sptr : NULL; + if (kwd != NOKEYWORD) + s = (*sptr) ? sptr : NULL; - /* learning, only one order_data per skill required */ - if (kwd == K_STUDY) { - skill_t sk = get_skill(parse_token(&sptr), lang); - switch (sk) { - case NOSKILL: /* fehler */ - break; - case SK_MAGIC: /* kann parameter haben */ - if (*sptr != 0) - break; - default: /* nur skill als Parameter, keine extras */ - data = locale_array[lindex]->study_orders[sk]; - if (data == NULL) { - const char *skname = skillname(sk, lang); - data = (order_data *) malloc(sizeof(order_data)); - locale_array[lindex]->study_orders[sk] = data; - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - if (strchr(skname, ' ') != NULL) { - size_t len = strlen(skname); - data->_str = malloc(len + 3); - data->_str[0] = '\"'; - memcpy(data->_str + 1, skname, len); - data->_str[len + 1] = '\"'; - data->_str[len + 2] = '\0'; - } else { - data->_str = _strdup(skname); + /* learning, only one order_data per skill required */ + if (kwd == K_STUDY) { + skill_t sk = get_skill(parse_token(&sptr), lang); + switch (sk) { + case NOSKILL: /* fehler */ + break; + case SK_MAGIC: /* kann parameter haben */ + if (*sptr != 0) + break; + default: /* nur skill als Parameter, keine extras */ + data = locale_array[lindex]->study_orders[sk]; + if (data == NULL) { + const char *skname = skillname(sk, lang); + data = (order_data *)malloc(sizeof(order_data)); + locale_array[lindex]->study_orders[sk] = data; + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + if (strchr(skname, ' ') != NULL) { + size_t len = strlen(skname); + data->_str = malloc(len + 3); + data->_str[0] = '\"'; + memcpy(data->_str + 1, skname, len); + data->_str[len + 1] = '\"'; + data->_str[len + 2] = '\0'; + } + else { + data->_str = _strdup(skname); + } + data->_refcount = 1; + } + ++data->_refcount; + return data; } - data->_refcount = 1; - } - ++data->_refcount; - return data; } - } - /* orders with no parameter, only one order_data per order required */ - else if (kwd != NOKEYWORD && *sptr == 0) { - data = locale_array[lindex]->short_orders[kwd]; - if (data == NULL) { - data = (order_data *) malloc(sizeof(order_data)); - locale_array[lindex]->short_orders[kwd] = data; - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - data->_str = NULL; - data->_refcount = 1; + /* orders with no parameter, only one order_data per order required */ + else if (kwd != NOKEYWORD && *sptr == 0) { + data = locale_array[lindex]->short_orders[kwd]; + if (data == NULL) { + data = (order_data *)malloc(sizeof(order_data)); + locale_array[lindex]->short_orders[kwd] = data; + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + data->_str = NULL; + data->_refcount = 1; + } + ++data->_refcount; + return data; } - ++data->_refcount; + data = (order_data *)malloc(sizeof(order_data)); + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + data->_str = s ? _strdup(s) : NULL; + data->_refcount = 1; return data; - } - data = (order_data *) malloc(sizeof(order_data)); - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - data->_str = s ? _strdup(s) : NULL; - data->_refcount = 1; - return data; } static order *create_order_i(keyword_t kwd, const char *sptr, int persistent, - const struct locale *lang) + const struct locale *lang) { - order *ord = NULL; - int lindex; + order *ord = NULL; + int lindex; - /* if this is just nonsense, then we skip it. */ - if (lomem) { - switch (kwd) { - case K_KOMMENTAR: - case NOKEYWORD: - return NULL; - default: - break; + /* if this is just nonsense, then we skip it. */ + if (lomem) { + switch (kwd) { + case K_KOMMENTAR: + case NOKEYWORD: + return NULL; + default: + break; + } } - } - for (lindex = 0; lindex != nlocales; ++lindex) { - if (locale_array[lindex]->lang == lang) - break; - } - if (lindex == nlocales) { - locale_array[nlocales] = (locale_data *) calloc(1, sizeof(locale_data)); - locale_array[nlocales]->lang = lang; - ++nlocales; - } + for (lindex = 0; lindex != nlocales; ++lindex) { + if (locale_array[lindex]->lang == lang) + break; + } + if (lindex == nlocales) { + locale_array[nlocales] = (locale_data *)calloc(1, sizeof(locale_data)); + locale_array[nlocales]->lang = lang; + ++nlocales; + } - ord = (order *) malloc(sizeof(order)); - ord->_persistent = persistent; - ord->next = NULL; + ord = (order *)malloc(sizeof(order)); + ord->_persistent = persistent; + ord->next = NULL; - ord->data = create_data(kwd, sptr, lindex); + ord->data = create_data(kwd, sptr, lindex); - return ord; + return ord; } order *create_order(keyword_t kwd, const struct locale * lang, - const char *params, ...) + const char *params, ...) { - char zBuffer[DISPLAYSIZE]; - if (params) { - char *bufp = zBuffer; - int bytes; - size_t size = sizeof(zBuffer) - 1; - va_list marker; + char zBuffer[DISPLAYSIZE]; + if (params) { + char *bufp = zBuffer; + int bytes; + size_t size = sizeof(zBuffer) - 1; + va_list marker; - va_start(marker, params); - while (*params) { - if (*params == '%') { - int i; - const char *s; - ++params; - switch (*params) { - case 's': - s = va_arg(marker, const char *); - bytes = (int)strlcpy(bufp, s, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - case 'd': - i = va_arg(marker, int); - bytes = (int)strlcpy(bufp, itoa10(i), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - case 'i': - i = va_arg(marker, int); - bytes = (int)strlcpy(bufp, itoa36(i), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - default: - assert(!"unknown format-character in create_order"); + va_start(marker, params); + while (*params) { + if (*params == '%') { + int i; + const char *s; + ++params; + switch (*params) { + case 's': + s = va_arg(marker, const char *); + bytes = (int)strlcpy(bufp, s, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + case 'd': + i = va_arg(marker, int); + bytes = (int)strlcpy(bufp, itoa10(i), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + case 'i': + i = va_arg(marker, int); + bytes = (int)strlcpy(bufp, itoa36(i), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + default: + assert(!"unknown format-character in create_order"); + } + } + else if (size > 0) { + *bufp++ = *params; + --size; + } + ++params; } - } else if (size > 0) { - *bufp++ = *params; - --size; - } - ++params; + va_end(marker); + *bufp = 0; } - va_end(marker); - *bufp = 0; - } else { - zBuffer[0] = 0; - } - return create_order_i(kwd, zBuffer, 0, lang); + else { + zBuffer[0] = 0; + } + return create_order_i(kwd, zBuffer, 0, lang); } order *parse_order(const char *s, const struct locale * lang) @@ -352,7 +357,7 @@ order *parse_order(const char *s, const struct locale * lang) if (*s != 0) { keyword_t kwd; const char *sptr; - int persistent = 0; + int persistent = 0; while (*s == '@') { persistent = 1; @@ -379,50 +384,50 @@ order *parse_order(const char *s, const struct locale * lang) */ bool is_repeated(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - const char * s; - int result = 0; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + const char * s; + int result = 0; - switch (kwd) { - case K_CAST: - case K_BUY: - case K_SELL: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - result = 1; - break; + switch (kwd) { + case K_CAST: + case K_BUY: + case K_SELL: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + result = 1; + break; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - s = getstrtoken(); - result = !isparam(s, lang, P_TEMP); - parser_popstate(); - break; - default: - result = 0; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + s = getstrtoken(); + result = !isparam(s, lang, P_TEMP); + parser_popstate(); + break; + default: + result = 0; + } + return result; } /** @@ -435,46 +440,46 @@ bool is_repeated(const order * ord) */ bool is_exclusive(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - int result = 0; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + int result = 0; - switch (kwd) { - case K_MOVE: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - result = 1; - break; + switch (kwd) { + case K_MOVE: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + result = 1; + break; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - result = !isparam(getstrtoken(), lang, P_TEMP); - parser_popstate(); - break; - default: - result = 0; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + result = !isparam(getstrtoken(), lang, P_TEMP); + parser_popstate(); + break; + default: + result = 0; + } + return result; } /** @@ -487,48 +492,48 @@ bool is_exclusive(const order * ord) */ bool is_long(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - bool result = false; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + bool result = false; - switch (kwd) { - case K_CAST: - case K_BUY: - case K_SELL: - case K_MOVE: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - return true; + switch (kwd) { + case K_CAST: + case K_BUY: + case K_SELL: + case K_MOVE: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + return true; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - result = !isparam(getstrtoken(), lang, P_TEMP); - parser_popstate(); - break; - default: - result = false; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + result = !isparam(getstrtoken(), lang, P_TEMP); + parser_popstate(); + break; + default: + result = false; + } + return result; } /** @@ -542,48 +547,50 @@ bool is_long(const order * ord) */ bool is_persistent(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - int persist = ord->_persistent != 0; - switch (kwd) { - case K_MOVE: - case NOKEYWORD: - /* lang, aber niemals persistent! */ - return false; + keyword_t kwd = ORD_KEYWORD(ord); + int persist = ord->_persistent != 0; + switch (kwd) { + case K_MOVE: + case NOKEYWORD: + /* lang, aber niemals persistent! */ + return false; - case K_KOMMENTAR: - return true; + case K_KOMMENTAR: + return true; - default: - return persist || is_repeated(ord); - } + default: + return persist || is_repeated(ord); + } } char *write_order(const order * ord, char *buffer, size_t size) { - if (ord == 0) { - buffer[0] = 0; - } else { - keyword_t kwd = ORD_KEYWORD(ord); - if (kwd == NOKEYWORD) { - const char *text = ORD_STRING(ord); - strlcpy(buffer, (const char *)text, size); - } else { - get_command(ord, buffer, size); + if (ord == 0) { + buffer[0] = 0; } - } - return buffer; + else { + keyword_t kwd = ORD_KEYWORD(ord); + if (kwd == NOKEYWORD) { + const char *text = ORD_STRING(ord); + strlcpy(buffer, (const char *)text, size); + } + else { + get_command(ord, buffer, size); + } + } + return buffer; } void push_order(order ** ordp, order * ord) { - while (*ordp) - ordp = &(*ordp)->next; - *ordp = ord; + while (*ordp) + ordp = &(*ordp)->next; + *ordp = ord; } void init_tokens(const struct order *ord) { - char *cmd = getcommand(ord); - init_tokens_str(cmd, cmd); + char *cmd = getcommand(ord); + init_tokens_str(cmd, cmd); } diff --git a/src/laws.c b/src/laws.c index 692ee5682..e6106bfc0 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1,5 +1,6 @@ /* -Copyright (c) 1998-2010, Enno Rehling +Copyright (c) 1998-2014, +Enno Rehling Katja Zedel