Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
0
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);
                    }
                }
            }
        }
    }
}
Beispiel #4
0
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);
      }
    }
  }
}
Beispiel #5
0
/** 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;
}