int region_getresource(const region * r, const resource_type * rtype) { const rawmaterial *rm; for (rm = r->resources; rm; rm = rm->next) { if (rm->type->rtype == rtype) { return rm->amount; } } if (rtype == get_resourcetype(R_SILVER)) return rmoney(r); if (rtype == get_resourcetype(R_HORSE)) return rhorses(r); if (rtype == get_resourcetype(R_PEASANT)) return rpeasants(r); return 0; }
summary *make_summary(void) { faction *f; region *r; unit *u; summary *s = calloc(1, sizeof(summary)); const struct resource_type *rhorse = get_resourcetype(R_HORSE); for (f = factions; f; f = f->next) { const struct locale *lang = f->locale; struct language *plang = s->languages; while (plang && plang->locale != lang) plang = plang->next; if (!plang) { plang = calloc(sizeof(struct language), 1); plang->next = s->languages; s->languages = plang; plang->locale = lang; } ++plang->number; f->nregions = 0; f->num_total = 0; f->money = 0; if (f->alive && f->units) { s->factions++; /* Problem mit Monsterpartei ... */ if (!is_monsters(f)) { s->factionrace[old_race(f->race)]++; } } } /* count everything */ for (r = regions; r; r = r->next) { s->pferde += rhorses(r); s->schiffe += listlen(r->ships); s->gebaeude += listlen(r->buildings); if (!fval(r->terrain, SEA_REGION)) { s->landregionen++; if (r->units) { s->landregionen_mit_spielern++; } if (fval(r, RF_ORCIFIED)) { s->orkifizierte_regionen++; } if (r->terrain == newterrain(T_VOLCANO)) { s->inactive_volcanos++; } else if (r->terrain == newterrain(T_VOLCANO_SMOKING)) { s->active_volcanos++; } } if (r->units) { s->regionen_mit_spielern++; } if (rpeasants(r) || r->units) { s->inhabitedregions++; s->peasants += rpeasants(r); s->peasantmoney += rmoney(r); /* Einheiten Info. nregions darf nur einmal pro Partei * incrementiert werden. */ for (u = r->units; u; u = u->next) freset(u->faction, FFL_SELECT); for (u = r->units; u; u = u->next) { f = u->faction; if (!is_monsters(u->faction)) { skill *sv; item *itm; s->nunits++; s->playerpop += u->number; if (u->flags & UFL_HERO) { s->heroes += u->number; } s->spielerpferde += i_get(u->items, rhorse->itype); s->playermoney += get_money(u); s->armed_men += armedmen(u, true); for (itm = u->items; itm; itm = itm->next) { if (itm->type->rtype->wtype) { s->waffen += itm->number; } if (itm->type->rtype->atype) { s->ruestungen += itm->number; } } s->spielerpferde += i_get(u->items, rhorse->itype); for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { skill_t sk = sv->id; int aktskill = eff_skill(u, sk, r); if (aktskill > s->maxskill) s->maxskill = aktskill; } if (!fval(f, FFL_SELECT)) { f->nregions++; fset(f, FFL_SELECT); } } f->num_total += u->number; f->money += get_money(u); s->poprace[old_race(u_race(u))] += u->number; } } } return s; }
void destroyfaction(faction ** fp) { faction * f = *fp; unit *u = f->units; *fp = f->next; f->next = dead_factions; dead_factions = f; fset(f, FFL_QUIT); f->_alive = false; if (f->spellbook) { spellbook_clear(f->spellbook); free(f->spellbook); f->spellbook = 0; } if (f->seen_factions) { selist_free(f->seen_factions); f->seen_factions = 0; } while (u) { /* give away your stuff, to ghosts if you cannot (quest items) */ if (u->items) { region *r = u->region; int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); if (result != 0) { save_special_items(u); } if (r->land && !!playerrace(u_race(u))) { const race *rc = u_race(u); int m = rmoney(r); /* Personen gehen nur an die Bauern, wenn sie auch von dort * stammen */ if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { int p = rpeasants(u->region); int h = rhorses(u->region); item *itm; p += (int)(u->number * rc->recruit_multi); for (itm = u->items; itm; itm = itm->next) { if (itm->type->flags & ITF_ANIMAL) { h += itm->number; } } rsetpeasants(r, p); rsethorses(r, h); } m += get_money(u); rsetmoney(r, m); } } set_number(u, 0); u = u->nextF; } handle_event(f->attribs, "destroy", f); if (f->alliance) { setalliance(f, NULL); } funhash(f); /* units of other factions that were disguised as this faction * have their disguise replaced by ordinary faction hiding. */ if (rule_stealth_other()) { region *rc; for (rc = regions; rc; rc = rc->next) { for (u = rc->units; u; u = u->next) { if (u->attribs && get_otherfaction(u) == f) { a_removeall(&u->attribs, &at_otherfaction); if (rule_stealth_anon()) { fset(u, UFL_ANON_FACTION); } } } } } }
void transfermen(unit * u, unit * u2, int n) { const attrib *a; int hp = u->hp; region *r = u->region; if (n == 0) return; assert(n > 0); /* "hat attackiert"-status wird übergeben */ if (u2) { skill *sv, *sn; skill_t sk; ship *sh; assert(u2->number + n > 0); for (sk = 0; sk != MAXSKILLS; ++sk) { int weeks, level = 0; sv = get_skill(u, sk); sn = get_skill(u2, sk); if (sv == NULL && sn == NULL) continue; if (sn == NULL && u2->number == 0) { /* new unit, easy to solve */ level = sv->level; weeks = sv->weeks; } else { double dlevel = 0.0; if (sv && sv->level) { dlevel += (sv->level + 1 - sv->weeks / (sv->level + 1.0)) * n; level += sv->level * n; } if (sn && sn->level) { dlevel += (sn->level + 1 - sn->weeks / (sn->level + 1.0)) * u2->number; level += sn->level * u2->number; } dlevel = dlevel / (n + u2->number); level = level / (n + u2->number); if (level <= dlevel) { /* apply the remaining fraction to the number of weeks to go. * subtract the according number of weeks, getting closer to the * next level */ level = (int)dlevel; weeks = (level + 1) - (int)((dlevel - level) * (level + 1)); } else { /* make it harder to reach the next level. * weeks+level is the max difficulty, 1 - the fraction between * level and dlevel applied to the number of weeks between this * and the previous level is the added difficutly */ level = (int)dlevel + 1; weeks = 1 + 2 * level - (int)((1 + dlevel - level) * level); } } if (level) { if (sn == NULL) sn = add_skill(u2, sk); sn->level = (unsigned char)level; sn->weeks = (unsigned char)weeks; assert(sn->weeks > 0 && sn->weeks <= sn->level * 2 + 1); assert(u2->number != 0 || (sn->level == sv->level && sn->weeks == sv->weeks)); } else if (sn) { remove_skill(u2, sk); sn = NULL; } } a = a_find(u->attribs, &at_effect); while (a && a->type == &at_effect) { effect_data *olde = (effect_data *) a->data.v; if (olde->value) change_effect(u2, olde->type, olde->value); a = a->next; } sh = leftship(u); if (sh != NULL) set_leftship(u2, sh); u2->flags |= u->flags & (UFL_LONGACTION | UFL_NOTMOVING | UFL_HUNGER | UFL_MOVED | UFL_ENTER); if (u->attribs) { transfer_curse(u, u2, n); } } scale_number(u, u->number - n); if (u2) { set_number(u2, u2->number + n); hp -= u->hp; u2->hp += hp; /* TODO: Das ist schnarchlahm! und gehört nicht hierhin */ a = a_find(u2->attribs, &at_effect); while (a && a->type == &at_effect) { attrib *an = a->next; effect_data *olde = (effect_data *) a->data.v; int e = get_effect(u, olde->type); if (e != 0) change_effect(u2, olde->type, -e); a = an; } } else if (r->land) { if ((u_race(u)->ec_flags & ECF_REC_ETHEREAL) == 0) { const race *rc = u_race(u); if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */ int h = rhorses(r) + n; rsethorses(r, h); } else { int p = rpeasants(r); p += (int)(n * rc->recruit_multi); rsetpeasants(r, p); } } } }
/** give all items to friends or peasants. * this function returns 0 on success, or 1 if there are items that * could not be destroyed. */ int gift_items(unit * u, int flags) { region *r = u->region; item **itm_p = &u->items; int retval = 0; int rule = rule_give(); assert(u->region); assert(u->faction); if ((u->faction->flags & FFL_QUIT) == 0 || (rule & GIVE_ONDEATH) == 0) { if ((rule & GIVE_ALLITEMS) == 0 && (flags & GIFT_FRIENDS)) flags -= GIFT_FRIENDS; if ((rule & GIVE_PEASANTS) == 0 && (flags & GIFT_PEASANTS)) flags -= GIFT_PEASANTS; if ((rule & GIVE_SELF) == 0 && (flags & GIFT_SELF)) flags -= GIFT_SELF; } if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY)) return 0; if ((u_race(u)->ec_flags & GIVEITEM) == 0) return 0; /* at first, I should try giving my crap to my own units in this region */ if (u->faction && (u->faction->flags & FFL_QUIT) == 0 && (flags & GIFT_SELF)) { unit *u2, *u3 = NULL; for (u2 = r->units; u2; u2 = u2->next) { if (u2 != u && u2->faction == u->faction && u2->number > 0) { /* some units won't take stuff: */ if (u_race(u2)->ec_flags & GETITEM) { /* we don't like to gift it to units that won't give it back */ if (u_race(u2)->ec_flags & GIVEITEM) { i_merge(&u2->items, &u->items); u->items = NULL; break; } else { u3 = u2; } } } } if (u->items && u3) { /* if nobody else takes it, we give it to a unit that has issues */ i_merge(&u3->items, &u->items); u->items = NULL; } if (u->items == NULL) return 0; } /* if I have friends, I'll try to give my stuff to them */ if (u->faction && (flags & GIFT_FRIENDS)) { int number = 0; buddy *friends = get_friends(u, &number); while (friends) { struct buddy *nf = friends; unit *u2 = nf->unit; item *itm = u->items; while (itm != NULL) { const item_type *itype = itm->type; item *itn = itm->next; int n = itm->number; n = n * nf->number / number; if (n > 0) { i_change(&u->items, itype, -n); i_change(&u2->items, itype, n); } itm = itn; } number -= nf->number; friends = nf->next; free(nf); } if (u->items == NULL) return 0; } /* last, but not least, give money and horses to peasants */ while (*itm_p) { item *itm = *itm_p; if (flags & GIFT_PEASANTS) { if (!fval(u->region->terrain, SEA_REGION)) { if (itm->type == olditemtype[I_HORSE]) { rsethorses(r, rhorses(r) + itm->number); itm->number = 0; } else if (itm->type == i_silver) { rsetmoney(r, rmoney(r) + itm->number); itm->number = 0; } } } if (itm->number > 0 && (itm->type->flags & ITF_NOTLOST)) { itm_p = &itm->next; retval = -1; } else { i_remove(itm_p, itm); i_free(itm); } } return retval; }