Пример #1
0
void set_group(struct unit *u, struct group *g)
{
    attrib *a = NULL;

    if (fval(u, UFL_GROUP)) {
        a = a_find(u->attribs, &at_group);
    }

    if (a) {
        group *og = (group *)a->data.v;
        if (og == g)
            return;
        --og->members;
    }

    if (g) {
        if (!a) {
            a = a_add(&u->attribs, a_new(&at_group));
            fset(u, UFL_GROUP);
        }
        a->data.v = g;
        g->members++;
    }
    else if (a) {
        a_remove(&u->attribs, a);
        freset(u, UFL_GROUP);
    }
}
Пример #2
0
static void melt_iceberg(region * r)
{
  attrib *a;
  unit *u;

  for (u = r->units; u; u = u->next)
    freset(u->faction, FFL_SELECT);
  for (u = r->units; u; u = u->next)
    if (!fval(u->faction, FFL_SELECT)) {
      fset(u->faction, FFL_SELECT);
      ADDMSG(&u->faction->msgs, msg_message("iceberg_melt", "region", r));
    }

  /* driftrichtung löschen */
  a = a_find(r->attribs, &at_iceberg);
  if (a)
    a_remove(&r->attribs, a);

  /* Gebäude löschen */
  while (r->buildings) {
    remove_building(&r->buildings, r->buildings);
  }

  /* in Ozean wandeln */
  terraform_region(r, newterrain(T_OCEAN));

  /* Einheiten, die nicht schwimmen können oder in Schiffen sind,
   * ertrinken */
  drown(r);
}
Пример #3
0
static quicklist * get_island(region * root)
{
    quicklist * ql, *result = 0;
    int qi = 0;

    fset(root, RF_MARK);
    ql_push(&result, root);

    for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
        int dir;
        region *r = (region *)ql_get(ql, qi);
        region * next[MAXDIRECTIONS];

        get_neighbours(r, next);

        for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
            region *rn = next[dir];
            if (rn != NULL && rn->land && !fval(rn, RF_MARK)) {
                fset(rn, RF_MARK);
                ql_push(&result, rn);
            }
        }
    }

    for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
        region *r = (region *)ql_get(ql, qi);
        freset(r, RF_MARK);
    }
    return result;
}
Пример #4
0
unit *is_guarded(region * r, unit * u)
{
    unit *u2;
    bool noguards = true;

    if (!fval(r, RF_GUARDED)) {
        return NULL;
    }

    /* 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 = r->units; u2; u2 = u2->next) {
        if (is_guardian_r(u2)) {
            noguards = false;
            if (is_guardian_u(u2, u)) {
                /* u2 is our guard. stop processing (we might have to go further next time) */
                return u2;
            }
        }
    }

    if (noguards) {
        /* you are mistaken, sir. there are no guards in these lands */
        freset(r, RF_GUARDED);
    }
    return NULL;
}
Пример #5
0
/**
 ** GM: TELL PLANE <string>
 ** requires: permission-key "gmmsgr"
 **/
static void gm_messageplane(const void *tnext, struct unit *gm, struct order *ord)
{
  const struct plane *p = rplane(gm->region);
  const char *zmsg = getstrtoken();
  if (p == NULL) {
    mistake(gm, ord, "In diese Ebene kann keine Nachricht gesandt werden.");
  } else {
    /* checking permissions */
    attrib *permissions = a_find(gm->faction->attribs, &at_permissions);
    if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) {
      mistake(gm, ord, "permission denied.");
    } else {
      message *msg = msg_message("msg_event", "string", zmsg);
      faction *f;
      region *r;
      for (f = factions; f; f = f->next) {
        freset(f, FFL_SELECT);
      }
      for (r = regions; r; r = r->next) {
        unit *u;
        if (rplane(r) != p)
          continue;
        for (u = r->units; u; u = u->next)
          if (!fval(u->faction, FFL_SELECT)) {
            f = u->faction;
            fset(f, FFL_SELECT);
            add_message(&f->msgs, msg);
          }
      }
      msg_release(msg);
    }
  }
}
Пример #6
0
static void test_piracy_cmd_errors(CuTest * tc) {
    race *r;
    faction *f;
    unit *u, *u2;
    ship_type *st_boat;

    test_setup();
    setup_piracy();

    st_boat = st_get_or_create("boat");
    r = test_create_race("pirates");
    u = test_create_unit(f = test_create_faction(r), test_create_region(0, 0, get_or_create_terrain("ocean")));
    f->locale = test_create_locale();
    u->thisorder = create_order(K_PIRACY, f->locale, "");
    assert(u && u->thisorder);

    piracy_cmd(u);
    CuAssertPtrNotNullMsg(tc, "must be on a ship for PIRACY", test_find_messagetype(f->msgs, "error144"));

    test_clear_messages(f);
    fset(r, RCF_SWIM);
    piracy_cmd(u);
    CuAssertPtrEquals_Msg(tc, "swimmers are pirates", 0, test_find_messagetype(f->msgs, "error144"));
    CuAssertPtrEquals_Msg(tc, "swimmers are pirates", 0, test_find_messagetype(f->msgs, "error146"));
    freset(r, RCF_SWIM);
    fset(r, RCF_FLY);
    CuAssertPtrEquals_Msg(tc, "flyers are pirates", 0, test_find_messagetype(f->msgs, "error144"));
    freset(r, RCF_FLY);
    test_clear_messages(f);

    u_set_ship(u, test_create_ship(u->region, st_boat));

    u2 = test_create_unit(u->faction, u->region);
    u2->thisorder = create_order(K_PIRACY, f->locale, "");
    u_set_ship(u2, u->ship);

    test_clear_messages(f);
    piracy_cmd(u2);
    CuAssertPtrNotNullMsg(tc, "must be owner for PIRACY", test_find_messagetype(f->msgs, "error146"));

    test_clear_messages(f);
    piracy_cmd(u);
    CuAssertPtrNotNullMsg(tc, "must specify target for PIRACY", test_find_messagetype(f->msgs, "piratenovictim"));
    CuAssertPtrNotNull(tc, u->thisorder);

    test_teardown();
}
Пример #7
0
static void free_nodes(node * root)
{
    while (root != NULL) {
        region *r = root->r;
        freset(r, RF_MARK);
        root = free_node(root);
    }
}
Пример #8
0
faction *gm_addquest(const char *email, const char *name, int radius,
  unsigned int flags)
{
  plane *pl;
  watcher *w = calloc(sizeof(watcher), 1);
  region *center;
  bool invalid = false;
  int minx, miny, maxx, maxy, cx, cy;
  int x;
  faction *f;

  /* GM playfield */
  do {
    minx = ((rng_int() % (2 * EXTENSION)) - EXTENSION);
    miny = ((rng_int() % (2 * EXTENSION)) - EXTENSION);
    for (x = 0; !invalid && x <= radius * 2; ++x) {
      int y;
      for (y = 0; !invalid && y <= radius * 2; ++y) {
        region *r = findregion(minx + x, miny + y);
        if (r)
          invalid = true;
      }
    }
  } while (invalid);
  maxx = minx + 2 * radius;
  cx = minx + radius;
  maxy = miny + 2 * radius;
  cy = miny + radius;
  pl = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags);
  center = new_region(cx, cy, pl, 0);
  for (x = 0; x <= 2 * radius; ++x) {
    int y;
    for (y = 0; y <= 2 * radius; ++y) {
      region *r = findregion(minx + x, miny + y);
      if (!r) {
        r = new_region(minx + x, miny + y, pl, 0);
      }
      freset(r, RF_ENCOUNTER);
      if (distance(r, center) == radius) {
        terraform_region(r, newterrain(T_FIREWALL));
      } else if (r == center) {
        terraform_region(r, newterrain(T_PLAIN));
      } else {
        terraform_region(r, newterrain(T_OCEAN));
      }
    }
  }

  /* watcher: */
  f = gm_addfaction(email, pl, center);
  w->faction = f;
  w->mode = see_unit;
  w->next = pl->watchers;
  pl->watchers = w;

  return f;
}
Пример #9
0
static void starting_region(newfaction ** players, region * r, region * rn[])
{
    int n;
    oceans_around(r, rn);
    freset(r, RF_MARK);
    for (n = 0; n != MAXDIRECTIONS; ++n) {
        freset(rn[n], RF_MARK);
    }
    terraform_region(r, newterrain(T_PLAIN));
    prepare_starting_region(r);
    if (players && *players) {
        newfaction *nf = *players;
        const struct race *rc = nf->race ? nf->race : races;
        const struct locale *lang = nf->lang ? nf->lang : default_locale;
        const char * passwd = nf->password ? nf->password : itoa36(rng_int());
        addplayer(r, addfaction(nf->email, passwd, rc, lang, 0));
        *players = nf->next;
        free_newfaction(nf);
    }
}
Пример #10
0
void setguard(unit * u, bool enabled)
{
    if (!enabled) {
        freset(u, UFL_GUARD);
    } else {
        assert(!fval(u, UFL_MOVED));
        assert(u->status < ST_FLEE);
        fset(u, UFL_GUARD);
        fset(u->region, RF_GUARDED);
    }
}
Пример #11
0
int fix_all_demand(region *rd) {
    region_list *rl, *rlist = NULL;
    recurse_regions(rd, &rlist, f_nolux);
    for (rl = rlist; rl; rl = rl->next) {
        region *r = rl->data;
        freset(r, RF_MARK);         /* undo recursive marker */
        if (!fix_demand(r)) {
            return -1;
        }
    }
    return 0;
}
Пример #12
0
void create_arena(void)
{
  int x;
  arena_id = hashstring("arena");
  arena = getplanebyid(arena_id);
  if (arena != NULL)
    return;
  score();                      /* ist wichtig, damit alle Parteien einen score haben, wenn sie durchs Tor wollen. */
  guardian_faction(arena, 999);
  if (arena)
    arena_center = findregion(plane_center_x(arena), plane_center_y(arena));
  if (!arena_center) {
    newarena = 1;
    arena =
      create_new_plane(arena_id, "Arena", -10000, -10000, 0, BLOCKSIZE - 1,
      PFL_LOWSTEALING | PFL_NORECRUITS | PFL_NOALLIANCES);
    block_create(arena->minx, arena->miny, T_OCEAN);
    arena_center = findregion(plane_center_x(arena), plane_center_y(arena));
    for (x = 0; x != BLOCKSIZE; ++x) {
      int y;
      for (y = 0; y != BLOCKSIZE; ++y) {
        region *r = findregion(arena->minx + x, arena->miny + y);
        freset(r, RF_ENCOUNTER);
        r->planep = arena;
        switch (distance(r, arena_center)) {
          case 4:
            terraform(r, T_FIREWALL);
            break;
          case 0:
            terraform(r, T_GLACIER);
            break;
          case 1:
            terraform(r, T_SWAMP);
            break;
          case 2:
            terraform(r, T_MOUNTAIN);
            break;
        }
      }
    }
  }
  make_temple(arena_center);
#ifdef CENTRAL_VOLCANO
  init_volcano();
#else
  if (arena_center->terrain != T_DESERT)
    terraform(arena_center, T_DESERT);
#endif
  rsetmoney(arena_center, 0);
  rsetpeasants(arena_center, 0);
  tower_init();
}
Пример #13
0
void create_icebergs(void)
{
  region *r;

  for (r = regions; r; r = r->next) {
    if (r->terrain == newterrain(T_ICEBERG_SLEEP) && chance(0.05)) {
      bool has_ocean_neighbour = false;
      direction_t dir;
      region *rc;
      unit *u;

      freset(r, RF_SELECT);
      for (dir = 0; dir < MAXDIRECTIONS; dir++) {
        rc = rconnect(r, dir);
        if (rc && fval(rc->terrain, SEA_REGION)) {
          has_ocean_neighbour = true;
          break;
        }
      }
      if (!has_ocean_neighbour)
        continue;

      rsetterrain(r, T_ICEBERG);

      fset(r, RF_SELECT);
      move_iceberg(r);

      for (u = r->units; u; u = u->next) {
        freset(u->faction, FFL_SELECT);
      }
      for (u = r->units; u; u = u->next) {
        if (!fval(u->faction, FFL_SELECT)) {
          fset(u->faction, FFL_SELECT);
          ADDMSG(&u->faction->msgs, msg_message("iceberg_create", "region", r));
        }
      }
    }
  }
}
Пример #14
0
static void test_give_dead_unit(CuTest * tc) {
    struct give env = { 0 };
    struct message *msg;

    test_setup_ex(tc);
    env.f1 = test_create_faction(NULL);
    env.f2 = test_create_faction(NULL);
    setup_give(&env);
    env.dst->number = 0;
    freset(env.dst, UFL_ISNEW);
    CuAssertPtrNotNull(tc, msg = check_give(env.src, env.dst, NULL));
    msg_release(msg);
    test_teardown();
}
Пример #15
0
static void test_buildingtype_exists(CuTest * tc)
{
    region *r;
    building *b;
    building_type *btype, *btype2;

    test_setup();

    btype2 = test_create_buildingtype("castle");
    assert(btype2);
    btype = test_create_buildingtype("lighhouse");
    btype->maxsize = 10;

    r = test_create_plain(0, 0);
    b = test_create_building(r, btype);
    CuAssertPtrNotNull(tc, b);
    b->size = 10;

    CuAssertTrue(tc, !buildingtype_exists(r, NULL, false));
    CuAssertTrue(tc, !buildingtype_exists(r, btype2, false));

    CuAssertTrue(tc, buildingtype_exists(r, btype, false));
    b->size = 9;
    fset(b, BLD_MAINTAINED);
    CuAssertTrue(tc, !buildingtype_exists(r, btype, false));
    btype->maxsize = 0;
    freset(b, BLD_MAINTAINED);
    CuAssertTrue(tc, buildingtype_exists(r, btype, false));
    btype->maxsize = 10;
    b->size = 10;

    fset(b, BLD_MAINTAINED);
    CuAssertTrue(tc, buildingtype_exists(r, btype, true));
    freset(b, BLD_MAINTAINED);
    CuAssertTrue(tc, !buildingtype_exists(r, btype, true));
    test_teardown();
}
Пример #16
0
void usetsiege(unit * u, const struct building *t)
{
  attrib *a = a_find(u->attribs, &at_siege);
  if (!a && t)
    a = a_add(&u->attribs, a_new(&at_siege));
  if (a) {
    if (!t) {
      a_remove(&u->attribs, a);
      freset(u, UFL_SIEGE);
    } else {
      a->data.v = (void *)t;
      fset(u, UFL_SIEGE);
    }
  }
}
Пример #17
0
void usettarget(unit * u, const unit * t)
{
  attrib *a = a_find(u->attribs, &at_target);
  if (!a && t)
    a = a_add(&u->attribs, a_new(&at_target));
  if (a) {
    if (!t) {
      a_remove(&u->attribs, a);
      freset(u, UFL_TARGET);
    } else {
      a->data.v = (void *)t;
      fset(u, UFL_TARGET);
    }
  }
}
Пример #18
0
static void guardian_faction(plane * pl, int id)
{
  region *r;
  faction *f = findfaction(id);

  if (!f) {
    f = calloc(1, sizeof(faction));
    f->banner = _strdup("Sie dienen dem großen Wyrm");
    f->passw = _strdup(itoa36(rng_int()));
    set_email(&f->email, "*****@*****.**");
    f->name = _strdup("Igjarjuks Kundschafter");
    f->race = new_race[RC_ILLUSION];
    f->age = turn;
    f->locale = find_locale("de");
    f->options =
      want(O_COMPRESS) | want(O_REPORT) | want(O_COMPUTER) | want(O_ADRESSEN) |
      want(O_DEBUG);

    f->no = id;
    addlist(&factions, f);
    fhash(f);
  }
  if (f->race != new_race[RC_ILLUSION]) {
    assert(!"guardian id vergeben");
    exit(0);
  }
  f->lastorders = turn;
  f->alive = true;
  for (r = regions; r; r = r->next)
    if (getplane(r) == pl && rterrain(r) != T_FIREWALL) {
      unit *u;
      freset(r, RF_ENCOUNTER);
      for (u = r->units; u; u = u->next) {
        if (u->faction == f)
          break;
      }
      if (u)
        continue;
      u = createunit(r, f, 1, new_race[RC_GOBLIN]);
      set_string(&u->name, "Igjarjuks Auge");
      set_item(u, I_RING_OF_INVISIBILITY, 1);
      set_order(&u->thisorder, NULL);
      fset(u, UFL_ANON_FACTION);
      set_money(u, 1000);
    }
}
Пример #19
0
plane *gm_addplane(int radius, unsigned int flags, const char *name)
{
  region *center;
  plane *pl;
  bool invalid = false;
  int minx, miny, maxx, maxy, cx, cy;
  int x;

  /* GM playfield */
  do {
    minx = (rng_int() % (2 * EXTENSION)) - EXTENSION;
    miny = (rng_int() % (2 * EXTENSION)) - EXTENSION;
    for (x = 0; !invalid && x <= radius * 2; ++x) {
      int y;
      for (y = 0; !invalid && y <= radius * 2; ++y) {
        region *r = findregion(minx + x, miny + y);
        if (r)
          invalid = true;
      }
    }
  } while (invalid);
  maxx = minx + 2 * radius;
  cx = minx + radius;
  maxy = miny + 2 * radius;
  cy = miny + radius;
  pl = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags);
  center = new_region(cx, cy, pl, 0);
  for (x = 0; x <= 2 * radius; ++x) {
    int y;
    for (y = 0; y <= 2 * radius; ++y) {
      region *r = findregion(minx + x, miny + y);
      if (!r)
        r = new_region(minx + x, miny + y, pl, 0);
      freset(r, RF_ENCOUNTER);
      if (distance(r, center) == radius) {
        terraform_region(r, newterrain(T_FIREWALL));
      } else if (r == center) {
        terraform_region(r, newterrain(T_PLAIN));
      } else {
        terraform_region(r, newterrain(T_OCEAN));
      }
    }
  }
  return pl;
}
Пример #20
0
static void encounter(region * r, unit * u)
{
  if (!fval(r, RF_ENCOUNTER))
    return;
  freset(r, RF_ENCOUNTER);
  if (rng_int() % 100 >= ENCCHANCE)
    return;
  switch (rng_int() % 3) {
    case 0:
      find_manual(r, u);
      break;
    case 1:
      get_villagers(r, u);
      break;
    case 2:
      get_allies(r, u);
      break;
  }
}
Пример #21
0
static void
get_island_info(region * root, int *size_p, int *inhabited_p, int *maxage_p)
{
    int qi, size = 0, maxage = 0, inhabited = 0;
    quicklist *ql, *island = NULL;

    ql_push(&island, root);
    fset(root, RF_MARK);

    for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
        int d;
        region *r = (region *)ql_get(ql, qi);
        if (r->units) {
            unit *u;
            for (u = r->units; u; u = u->next) {
                if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) {
                    maxage = u->faction->age;
                }
            }
            ++inhabited;
        }
        ++size;
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            region *rn = rconnect(r, d);
            if (rn && !fval(rn, RF_MARK) && rn->land) {
                ql_push(&island, rn);
                fset(rn, RF_MARK);
            }
        }
    }
    for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
        region *r = (region *)ql_get(ql, qi);
        freset(r, RF_MARK);
    }
    ql_free(island);
    if (size_p)
        *size_p = size;
    if (inhabited_p)
        *inhabited_p = inhabited;
    if (maxage_p)
        *maxage_p = maxage;
}
Пример #22
0
void volcano_outbreak(region * r)
{
    region *rn;
    unit *u;
    faction *f;

    for (f = NULL, u = r->units; u; u = u->next) {
        if (f != u->faction) {
            f = u->faction;
            freset(f, FFL_SELECT);
        }
    }

    /* Zufällige Nachbarregion verwüsten */
    rn = rrandneighbour(r);
    volcano_destruction(r, r, "4d10");
    if (rn) {
        volcano_destruction(r, rn, "3d10");
    }
}
Пример #23
0
void u_seteffstealth(unit * u, int value)
{
  if (skill_enabled[SK_STEALTH]) {
    attrib *a = NULL;
    if (fval(u, UFL_STEALTH)) {
      a = a_find(u->attribs, &at_stealth);
    }
    if (value < 0) {
      if (a != NULL) {
        freset(u, UFL_STEALTH);
        a_remove(&u->attribs, a);
      }
      return;
    }
    if (a == NULL) {
      a = a_add(&u->attribs, a_new(&at_stealth));
      fset(u, UFL_STEALTH);
    }
    a->data.i = value;
  }
}
Пример #24
0
void get_food(region * r)
{
    plane *pl = rplane(r);
    unit *u;
    int peasantfood = rpeasants(r) * 10;
    static int food_rules = -1;
    static int gamecookie = -1;

    if (food_rules < 0 || gamecookie != global.cookie) {
        gamecookie = global.cookie;
        food_rules = get_param_int(global.parameters, "rules.economy.food", 0);
    }

    if (food_rules & FOOD_IS_FREE) {
        return;
    }
    /* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber
    * wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise
    * jede Einheit genug Silber für ihren Unterhalt hat. */

    for (u = r->units; u; u = u->next) {
        int need = lifestyle(u);

        /* Erstmal zurücksetzen */
        freset(u, UFL_HUNGER);

        if (u->ship && (u->ship->flags & SF_FISHING)) {
            unit *v;
            int c = 2;
            for (v = u; c > 0 && v; v = v->next) {
                if (v->ship == u->ship) {
                    int get = 0;
                    if (v->number <= c) {
                        get = lifestyle(v);
                    }
                    else {
                        get = lifestyle(v) * c / v->number;
                    }
                    if (get) {
                        change_money(v, get);
                    }
                }
                c -= v->number;
            }
            u->ship->flags -= SF_FISHING;
        }

        if (food_rules & FOOD_FROM_PEASANTS) {
            struct faction *owner = region_get_owner(r);
            /* if the region is owned, and the owner is nice, then we'll get
            * food from the peasants - should not be used with WORK */
            if (owner != NULL && (get_alliance(owner, u->faction) & HELP_MONEY)) {
                int rm = rmoney(r);
                int use = _min(rm, need);
                rsetmoney(r, rm - use);
                need -= use;
            }
        }

        need -= get_money(u);
        if (need > 0) {
            unit *v;

            for (v = r->units; need && v; v = v->next) {
                if (v->faction == u->faction && help_money(v)) {
                    int give = get_money(v) - lifestyle(v);
                    give = _min(need, give);
                    if (give > 0) {
                        change_money(v, -give);
                        change_money(u, give);
                        need -= give;
                    }
                }
            }
        }
    }

    /* 2. Versorgung durch Fremde. Das Silber alliierter Einheiten wird
    * entsprechend verteilt. */
    for (u = r->units; u; u = u->next) {
        int need = lifestyle(u);
        faction *f = u->faction;

        need -= _max(0, get_money(u));

        if (need > 0) {
            unit *v;

            if (food_rules & FOOD_FROM_OWNER) {
                /* the owner of the region is the first faction to help out when you're hungry */
                faction *owner = region_get_owner(r);
                if (owner && owner != u->faction) {
                    for (v = r->units; v; v = v->next) {
                        if (v->faction == owner && alliedunit(v, f, HELP_MONEY)
                            && help_money(v)) {
                            help_feed(v, u, &need);
                            break;
                        }
                    }
                }
            }
            for (v = r->units; need && v; v = v->next) {
                if (v->faction != f && alliedunit(v, f, HELP_MONEY)
                    && help_money(v)) {
                    help_feed(v, u, &need);
                }
            }

            /* Die Einheit hat nicht genug Geld zusammengekratzt und
            * nimmt Schaden: */
            if (need > 0) {
                int lspp = lifestyle(u) / u->number;
                if (lspp > 0) {
                    int number = (need + lspp - 1) / lspp;
                    if (hunger(number, u))
                        fset(u, UFL_HUNGER);
                }
            }
        }
    }

    /* 3. bestimmen, wie viele Bauern gefressen werden.
    * bei fehlenden Bauern den Dämon hungern lassen
    */
    for (u = r->units; u; u = u->next) {
        if (u_race(u) == get_race(RC_DAEMON)) {
            int hungry = u->number;

            /* use peasantblood before eating the peasants themselves */
            const struct potion_type *pt_blood = 0;
            const resource_type *rt_blood = rt_find("peasantblood");
            if (rt_blood) {
                pt_blood = rt_blood->ptype;
            }
            if (pt_blood) {
                /* always start with the unit itself, then the first known unit that may have some blood */
                unit *donor = u;
                while (donor != NULL && hungry > 0) {
                    int blut = get_effect(donor, pt_blood);
                    blut = _min(blut, hungry);
                    if (blut) {
                        change_effect(donor, pt_blood, -blut);
                        hungry -= blut;
                    }
                    if (donor == u)
                        donor = r->units;
                    while (donor != NULL) {
                        if (u_race(donor) == get_race(RC_DAEMON) && donor != u) {
                            if (get_effect(donor, pt_blood)) {
                                /* if he's in our faction, drain him: */
                                if (donor->faction == u->faction)
                                    break;
                            }
                        }
                        donor = donor->next;
                    }
                }
            }
            /* remaining demons feed on peasants */
            if (pl == NULL || !fval(pl, PFL_NOFEED)) {
                if (peasantfood >= hungry) {
                    peasantfood -= hungry;
                    hungry = 0;
                }
                else {
                    hungry -= peasantfood;
                    peasantfood = 0;
                }
                if (hungry > 0) {
                    static int demon_hunger = -1;
                    if (demon_hunger < 0) {
                        demon_hunger = get_param_int(global.parameters, "hunger.demons", 0);
                    }
                    if (demon_hunger == 0) {
                        /* demons who don't feed are hungry */
                        if (hunger(hungry, u))
                            fset(u, UFL_HUNGER);
                    }
                    else {
                        /* no damage, but set the hungry-flag */
                        fset(u, UFL_HUNGER);
                    }
                }
            }
        }
    }
    rsetpeasants(r, peasantfood / 10);

    /* 3. Von den überlebenden das Geld abziehen: */
    for (u = r->units; u; u = u->next) {
        int need = _min(get_money(u), lifestyle(u));
        change_money(u, -need);
    }
}
Пример #25
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;
}
Пример #26
0
/** create new island with up to nsize players
 * returns the number of players placed on the new island.
 */
int autoseed(newfaction ** players, int nsize, int max_agediff)
{
    region *r = NULL;
    region_list *rlist = NULL;
    int rsize = 0, tsize = 0;
    int isize = REGIONS_PER_FACTION;      /* target size for the island */
    int psize = 0;                /* players on this island */
    const terrain_type *volcano_terrain = get_terrain("volcano");
    static int nterrains = -1;
    static const terrain_type **terrainarr = 0;
    static int *distribution;

    assert(players);
    if (nterrains < 0) {
        int n = 0;
        const terrain_type *terrain = terrains();
        for (nterrains = 0; terrain; terrain = terrain->next) {
            if (terrain->distribution) {
                ++nterrains;
            }
        }
        terrainarr = malloc(sizeof(terrain_type *) * nterrains);
        distribution = malloc(sizeof(int) * nterrains);
        for (terrain = terrains(); terrain; terrain = terrain->next) {
            if (terrain->distribution) {
                terrainarr[n] = terrain;
                distribution[n++] = terrain->distribution;
            }
        }
    }
    frame_regions(16, newterrain(T_FIREWALL));

    if (listlen(*players) < MINFACTIONS)
        return 0;

    if (max_agediff > 0) {
        region *rmin = NULL;
        plane *hplane = get_homeplane();
        /* find a spot that's adjacent to the previous island, but virgin.
         * like the last land virgin ocean region adjacent to land.
         */
        for (r = regions; r; r = r->next) {
            struct plane *pl = rplane(r);
            if (r->age <= max_agediff && r->terrain == newterrain(T_OCEAN)
                && pl == hplane && virgin_region(r)) {
                direction_t d;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn && rn->land && rn->age <= max_agediff && virgin_region(rn)) {
                        /* only expand islands that aren't single-islands and not too big already */
                        int size, inhabitants, maxage;
                        get_island_info(rn, &size, &inhabitants, &maxage);
                        if (maxage <= max_agediff && size >= 2 && size < MAXISLANDSIZE) {
                            rmin = rn;
                            break;
                        }
                    }
                }
            }
        }
        if (rmin != NULL) {
            faction *f;
            quicklist *ql, *rlist = get_island(rmin);
            int qi;

            for (ql = rlist, qi = 0; ql; ql_advance(&ql, &qi, 1)) {
                region *r = (region *)ql_get(ql, qi);
                unit *u;
                for (u = r->units; u; u = u->next) {
                    f = u->faction;
                    if (!fval(f, FFL_MARK)) {
                        ++psize;
                        fset(f, FFL_MARK);
                    }
                }
            }
            ql_free(rlist);
            if (psize > 0) {
                for (f = factions; f; f = f->next) {
                    freset(f, FFL_MARK);
                }
            }
            if (psize < PLAYERS_PER_ISLAND) {
                r = rmin;
            }
        }
    }
    if (r == NULL) {
        region *rmin = NULL;
        direction_t dmin = MAXDIRECTIONS;
        plane *hplane = get_homeplane();
        /* find an empty spot.
         * rmin = the youngest ocean region that has a missing neighbour
         * dmin = direction in which it's empty
         */
        for (r = regions; r; r = r->next) {
            struct plane *pl = rplane(r);
            if (r->terrain == newterrain(T_OCEAN) && pl == hplane && (rmin == NULL
                || r->age <= max_agediff)) {
                direction_t d;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn == NULL)
                        break;
                }
                if (d != MAXDIRECTIONS) {
                    rmin = r;
                    dmin = d;
                }
            }
        }

        /* create a new region where we found the empty spot, and make it the first
         * in our island. island regions are kept in rlist, so only new regions can
         * get populated, and old regions are not overwritten */
        if (rmin != NULL) {
            plane *pl = rplane(rmin);
            int x = rmin->x + delta_x[dmin];
            int y = rmin->y + delta_y[dmin];
            pnormalize(&x, &y, pl);
            assert(virgin_region(rconnect(rmin, dmin)));
            r = new_region(x, y, pl, 0);
            terraform_region(r, newterrain(T_OCEAN));
        }
    }
    if (r != NULL) {
        add_regionlist(&rlist, r);
        fset(r, RF_MARK);
        rsize = 1;
    }

    while (rsize && (nsize || isize >= REGIONS_PER_FACTION)) {
        int i = rng_int() % rsize;
        region_list **rnext = &rlist;
        region_list *rfind;
        direction_t d;
        while (i--)
            rnext = &(*rnext)->next;
        rfind = *rnext;
        r = rfind->data;
        freset(r, RF_MARK);
        *rnext = rfind->next;
        free(rfind);
        --rsize;
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            region *rn = rconnect(r, d);
            if (rn && fval(rn, RF_MARK))
                continue;
            if (rn == NULL) {
                plane *pl = rplane(r);
                int x = r->x + delta_x[d];
                int y = r->y + delta_y[d];
                pnormalize(&x, &y, pl);
                rn = new_region(x, y, pl, 0);
                terraform_region(rn, newterrain(T_OCEAN));
            }
            if (virgin_region(rn)) {
                add_regionlist(&rlist, rn);
                fset(rn, RF_MARK);
                ++rsize;
            }
        }
        if (volcano_terrain != NULL && (rng_int() % VOLCANO_CHANCE == 0)) {
            terraform_region(r, volcano_terrain);
        }
        else if (nsize && (rng_int() % isize == 0 || rsize == 0)) {
            newfaction **nfp, *nextf = *players;
            faction *f;
            unit *u;

            isize += REGIONS_PER_FACTION;
            terraform_region(r, preferred_terrain(nextf->race));
            prepare_starting_region(r);
            ++tsize;
            assert(r->land && r->units == 0);
            u = addplayer(r, addfaction(nextf->email, nextf->password, nextf->race,
                nextf->lang, nextf->subscription));
            f = u->faction;
            fset(f, FFL_ISNEW);
            f->alliance = nextf->allies;

            /* remove duplicate email addresses */
            nfp = &nextf->next;
            while (*nfp) {
                newfaction *nf = *nfp;
                if (strcmp(nextf->email, nf->email) == 0) {
                    *nfp = nf->next;
                    free_newfaction(nf);
                }
                else
                    nfp = &nf->next;
            }
            *players = nextf->next;
            free_newfaction(nextf);

            ++psize;
            --nsize;
            --isize;
            if (psize >= PLAYERS_PER_ISLAND)
                break;
        }
        else {
            terraform_region(r, random_terrain(terrainarr, distribution, nterrains));
            --isize;
        }
    }

    if (nsize != 0) {
        log_error(
            ("Could not place all factions on the same island as requested\n"));
    }

    if (rlist) {
#define MINOCEANDIST 3
#define MAXOCEANDIST 6
#define MAXFILLDIST 10
#define SPECIALCHANCE 80
        region_list **rbegin = &rlist;
        int special = 1;
        int oceandist = MINOCEANDIST + (rng_int() % (MAXOCEANDIST - MINOCEANDIST));
        while (oceandist--) {
            region_list **rend = rbegin;
            while (*rend)
                rend = &(*rend)->next;
            while (rbegin != rend) {
                direction_t d;
                region *r = (*rbegin)->data;
                rbegin = &(*rbegin)->next;
                for (d = 0; d != MAXDIRECTIONS; ++d) {
                    region *rn = rconnect(r, d);
                    if (rn == NULL) {
                        const struct terrain_type *terrain = newterrain(T_OCEAN);
                        plane *pl = rplane(r);
                        int x = r->x + delta_x[d];
                        int y = r->y + delta_y[d];
                        pnormalize(&x, &y, pl);
                        rn = new_region(x, y, pl, 0);
                        if (rng_int() % SPECIALCHANCE < special) {
                            terrain = random_terrain(terrainarr, distribution, nterrains);
                            special = SPECIALCHANCE / 3;      /* 33% chance auf noch eines */
                        }
                        else {
                            special = 1;
                        }
                        terraform_region(rn, terrain);
                        /* the new region has an extra 20% chance to have mallorn */
                        if (rng_int() % 100 < 20)
                            fset(r, RF_MALLORN);
                        add_regionlist(rend, rn);
                    }
                }
            }

        }
        while (*rbegin) {
            region *r = (*rbegin)->data;
            plane *pl = rplane(r);
            direction_t d;
            rbegin = &(*rbegin)->next;
            for (d = 0; d != MAXDIRECTIONS; ++d)
                if (rconnect(r, d) == NULL) {
                    int i;
                    for (i = 1; i != MAXFILLDIST; ++i) {
                        int x = r->x + delta_x[d] * i;
                        int y = r->y + delta_y[d] * i;
                        pnormalize(&x, &y, pl);
                        if (findregion(x, y)) {
                            break;
                        }
                    }
                    if (i != MAXFILLDIST) {
                        while (--i) {
                            region *rn;
                            int x = r->x + delta_x[d] * i;
                            int y = r->y + delta_y[d] * i;
                            pnormalize(&x, &y, pl);
                            rn = new_region(x, y, pl, 0);
                            terraform_region(rn, newterrain(T_OCEAN));
                        }
                    }
                }
        }
        while (rlist) {
            region_list *self = rlist;
            rlist = rlist->next;
            freset(self->data, RF_MARK);
            free(self);
        }
    }
    return tsize;
}
Пример #27
0
static void move_iceberg(region * r)
{
  attrib *a;
  direction_t dir;
  region *rc;

  a = a_find(r->attribs, &at_iceberg);
  if (!a) {
    dir = (direction_t) (rng_int() % MAXDIRECTIONS);
    a = a_add(&r->attribs, make_iceberg(dir));
  } else {
    if (rng_int() % 100 < 20) {
      dir = (direction_t) (rng_int() % MAXDIRECTIONS);
      a->data.i = dir;
    } else {
      dir = (direction_t) a->data.i;
    }
  }

  rc = rconnect(r, dir);

  if (rc && !fval(rc->terrain, ARCTIC_REGION)) {
    if (fval(rc->terrain, SEA_REGION)) {        /* Eisberg treibt */
      ship *sh, *shn;
      unit *u;
      int x, y;

      for (u = r->units; u; u = u->next)
        freset(u->faction, FFL_SELECT);
      for (u = r->units; u; u = u->next)
        if (!fval(u->faction, FFL_SELECT)) {
          fset(u->faction, FFL_SELECT);
          ADDMSG(&u->faction->msgs, msg_message("iceberg_drift",
              "region dir", r, dir));
        }

      x = r->x;
      y = r->y;

      runhash(r);
      runhash(rc);
      r->x = rc->x;
      r->y = rc->y;
      rc->x = x;
      rc->y = y;
      rhash(rc);
      rhash(r);

      /* rc ist der Ozean (Ex-Eisberg), r der Eisberg (Ex-Ozean) */

      /* Schiffe aus dem Zielozean werden in den Eisberg transferiert
       * und nehmen Schaden. */

      for (sh = r->ships; sh; sh = sh->next)
        freset(sh, SF_SELECT);

      for (sh = r->ships; sh; sh = sh->next) {
        /* Meldung an Kapitän */
        float dmg =
          get_param_flt(global.parameters, "rules.ship.damage.intoiceberg",
          0.10F);
        damage_ship(sh, dmg);
        fset(sh, SF_SELECT);
      }

      /* Personen, Schiffe und Gebäude verschieben */
      while (rc->buildings) {
        rc->buildings->region = r;
        translist(&rc->buildings, &r->buildings, rc->buildings);
      }
      while (rc->ships) {
        float dmg =
          get_param_flt(global.parameters, "rules.ship.damage.withiceberg",
          0.10F);
        fset(rc->ships, SF_SELECT);
        damage_ship(rc->ships, dmg);
        move_ship(rc->ships, rc, r, NULL);
      }
      while (rc->units) {
        building *b = rc->units->building;
        u = rc->units;
        u->building = 0; /* prevent leaving in move_unit */
        move_unit(rc->units, r, NULL);
        u_set_building(u, b); /* undo leave-prevention */
      }

      /* Beschädigte Schiffe können sinken */

      for (sh = r->ships; sh;) {
        shn = sh->next;
        if (fval(sh, SF_SELECT)) {
          u = ship_owner(sh);
          if (sh->damage >= sh->size * DAMAGE_SCALE) {
            if (u != NULL) {
              ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des",
                  "ship", sh));
            }
            remove_ship(&sh->region->ships, sh);
          } else if (u != NULL) {
            ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg",
                "ship", sh));
          }
        }
        sh = shn;
      }

    } else if (rng_int() % 100 < 20) {  /* Eisberg bleibt als Gletscher liegen */
      unit *u;

      rsetterrain(r, T_GLACIER);
      a_remove(&r->attribs, a);

      for (u = r->units; u; u = u->next)
        freset(u->faction, FFL_SELECT);
      for (u = r->units; u; u = u->next)
        if (!fval(u->faction, FFL_SELECT)) {
          fset(u->faction, FFL_SELECT);
          ADDMSG(&u->faction->msgs, msg_message("iceberg_land", "region", r));
        }
    }
  }
}
Пример #28
0
/** Untote können entstehen */
void spawn_undead(void)
{
    region *r;
    faction *monsters = get_monsters();

    for (r = regions; r; r = r->next) {
        int unburied = deathcount(r);
        static const curse_type *ctype = NULL;

        if (!ctype)
            ctype = ct_find("holyground");
        if (ctype && curse_active(get_curse(r->attribs, ctype)))
            continue;

        /* Chance 0.1% * chaosfactor */
        if (r->land && unburied > r->land->peasants / 20
            && rng_int() % 10000 < (100 + 100 * chaosfactor(r))) {
            message *msg;
            unit *u;
            /* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen.
             * Lieber sammeln lassen, bis sie mindestens 5% der Bevölkerung sind, und
             * dann erst auferstehen. */
            int undead = unburied / (rng_int() % 2 + 1);
            const race *rc = NULL;
            int i;
            if (r->age < 100)
                undead = undead * r->age / 100; /* newbie-regionen kriegen weniger ab */

            if (!undead || r->age < 20)
                continue;

            switch (rng_int() % 3) {
            case 0:
                rc = get_race(RC_SKELETON);
                break;
            case 1:
                rc = get_race(RC_ZOMBIE);
                break;
            default:
                rc = get_race(RC_GHOUL);
                break;
            }

            u = create_unit(r, monsters, undead, rc, 0, NULL, NULL);
            fset(u, UFL_ISNEW | UFL_MOVED);
            if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE))
                && rng_int() % 10 < 4) {
                equip_unit(u, get_equipment("rising_undead"));
            }

            for (i = 0; i < MAXSKILLS; i++) {
                if (rc->bonus[i] >= 1) {
                    set_level(u, (skill_t)i, 1);
                }
            }
            u->hp = unit_max_hp(u) * u->number;

            deathcounts(r, -undead);
            name_unit(u);

            log_debug("spawning %d %s in %s.\n", u->number,
                LOC(default_locale,
                rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL)), regionname(r, NULL));
          msg = msg_message("undeadrise", "region", r);
          add_message(&r->msgs, msg);
          for (u = r->units; u; u = u->next)
              freset(u->faction, FFL_SELECT);
          for (u = r->units; u; u = u->next) {
              if (fval(u->faction, FFL_SELECT))
                  continue;
              fset(u->faction, FFL_SELECT);
              add_message(&u->faction->msgs, msg);
          }
          msg_release(msg);
        }
        else {
            int i = deathcount(r);
            if (i) {
                /* Gräber verwittern, 3% der Untoten finden die ewige Ruhe */
                deathcounts(r, (int)(-i * 0.03));
            }
        }
    }
}
Пример #29
0
void randomevents(void)
{
  region *r;
  faction *monsters = get_monsters();

  icebergs();
  godcurse();
  orc_growth();
  demon_skillchanges();

  /* Orkifizierte Regionen mutieren und mutieren zurück */

  for (r = regions; r; r = r->next) {
    if (fval(r, RF_ORCIFIED)) {
      direction_t dir;
      double probability = 0.0;
      for (dir = 0; dir < MAXDIRECTIONS; dir++) {
        region *rc = rconnect(r, dir);
        if (rc && rpeasants(rc) > 0 && !fval(rc, RF_ORCIFIED))
          probability += 0.02;
      }
      if (chance(probability)) {
        ADDMSG(&r->msgs, msg_message("deorcified", "region", r));
        freset(r, RF_ORCIFIED);
      }
    } else {
      attrib *a = a_find(r->attribs, &at_orcification);
      if (a != NULL) {
        double probability = 0.0;
        if (rpeasants(r) <= 0)
          continue;
        probability = a->data.i / (double)rpeasants(r);
        if (chance(probability)) {
          fset(r, RF_ORCIFIED);
          a_remove(&r->attribs, a);
          ADDMSG(&r->msgs, msg_message("orcified", "region", r));
        } else {
          a->data.i -= _max(10, a->data.i / 10);
          if (a->data.i <= 0)
            a_remove(&r->attribs, a);
        }
      }
    }
  }

  /* Vulkane qualmen, brechen aus ... */
  for (r = regions; r; r = r->next) {
    if (r->terrain == newterrain(T_VOLCANO_SMOKING)) {
      if (a_find(r->attribs, &at_reduceproduction)) {
        ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
        rsetterrain(r, T_VOLCANO);
      } else {
        if (rng_int() % 100 < 12) {
          ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
          rsetterrain(r, T_VOLCANO);
        } else if (r->age > 20 && rng_int() % 100 < 8) {
          volcano_outbreak(r);
        }
      }
    } else if (r->terrain == newterrain(T_VOLCANO)) {
      if (rng_int() % 100 < 4) {
        ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r));
        rsetterrain(r, T_VOLCANO_SMOKING);
      }
    }
  }

  /* Monumente zerfallen, Schiffe verfaulen */

  for (r = regions; r; r = r->next) {
    building **blist = &r->buildings;
    while (*blist) {
      building *b = *blist;
      if (fval(b->type, BTF_DECAY) && !building_owner(b)) {
        b->size -= _max(1, (b->size * 20) / 100);
        if (b->size == 0) {
          remove_building(blist, r->buildings);
        }
      }
      if (*blist == b)
        blist = &b->next;
    }
  }

  /* monster-einheiten desertieren */
  if (monsters) {
      for (r = regions; r; r = r->next) {
          unit *u;

          for (u = r->units; u; u = u->next) {
              if (u->faction && !is_monsters(u->faction)
                  && (u_race(u)->flags & RCF_DESERT)) {
                  if (fval(u, UFL_ISNEW))
                      continue;
                  if (rng_int() % 100 < 5) {
                      ADDMSG(&u->faction->msgs, msg_message("desertion",
                          "unit region", u, r));
                      u_setfaction(u, monsters);
                  }
              }
          }
      }
  }

  /* Chaos */
  for (r = regions; r; r = r->next) {
    int i;

    if (fval(r, RF_CHAOTIC)) {
      chaos(r);
    }
    i = chaoscount(r);
    if (i) {
      chaoscounts(r, -(int)(i * ((double)(rng_int() % 10)) / 100.0));
    }
  }
#ifdef HERBS_ROT
  rotting_herbs();
#endif

  dissolve_units();
}
Пример #30
0
void terraform_region(region * r, const terrain_type * terrain)
{
    /* Resourcen, die nicht mehr vorkommen können, löschen */
    const terrain_type *oldterrain = r->terrain;
    rawmaterial **lrm = &r->resources;

    assert(terrain);

    while (*lrm) {
        rawmaterial *rm = *lrm;
        const resource_type *rtype = NULL;

        if (terrain->production != NULL) {
            int i;
            for (i = 0; terrain->production[i].type; ++i) {
                if (rm->type->rtype == terrain->production[i].type) {
                    rtype = rm->type->rtype;
                    break;
                }
            }
        }
        if (rtype == NULL) {
            *lrm = rm->next;
            free(rm);
        }
        else {
            lrm = &rm->next;
        }
    }

    r->terrain = terrain;
    terraform_resources(r);

    if (!fval(terrain, LAND_REGION)) {
        region_setinfo(r, NULL);
        if (r->land != NULL) {
            i_freeall(&r->land->items);
            freeland(r->land);
            r->land = NULL;
        }
        rsettrees(r, 0, 0);
        rsettrees(r, 1, 0);
        rsettrees(r, 2, 0);
        rsethorses(r, 0);
        rsetpeasants(r, 0);
        rsetmoney(r, 0);
        freset(r, RF_ENCOUNTER);
        freset(r, RF_MALLORN);
        /* Beschreibung und Namen löschen */
        return;
    }

    if (r->land) {
        int d;
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            rsetroad(r, d, 0);
        }
        i_freeall(&r->land->items);
    }
    else {
        static struct surround {
            struct surround *next;
            const luxury_type *type;
            int value;
        } *trash = NULL, *nb = NULL;
        const luxury_type *ltype = NULL;
        direction_t d;
        int mnr = 0;

        r->land = calloc(1, sizeof(land_region));
        r->land->ownership = NULL;
        region_set_morale(r, MORALE_DEFAULT, -1);
        region_setname(r, makename());
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            region *nr = rconnect(r, d);
            if (nr && nr->land) {
                struct demand *sale = r->land->demands;
                while (sale && sale->value != 0)
                    sale = sale->next;
                if (sale) {
                    struct surround *sr = nb;
                    while (sr && sr->type != sale->type)
                        sr = sr->next;
                    if (!sr) {
                        if (trash) {
                            sr = trash;
                            trash = trash->next;
                        }
                        else {
                            sr = calloc(1, sizeof(struct surround));
                        }
                        sr->next = nb;
                        sr->type = sale->type;
                        sr->value = 1;
                        nb = sr;
                    }
                    else
                        sr->value++;
                    ++mnr;
                }
            }
        }
        if (!nb) {
            // TODO: this is really lame
            int i = get_maxluxuries();
            if (i > 0) {
                i = rng_int() % i;
                ltype = luxurytypes;
                while (i--)
                    ltype = ltype->next;
            }
        }
        else {
            int i = rng_int() % mnr;
            struct surround *srd = nb;
            while (i > srd->value) {
                i -= srd->value;
                srd = srd->next;
            }
            if (srd->type)
                setluxuries(r, srd->type);
            while (srd->next != NULL)
                srd = srd->next;
            srd->next = trash;
            trash = nb;
            nb = NULL;
        }
    }

    if (fval(terrain, LAND_REGION)) {
        const item_type *itype = NULL;
        char equip_hash[64];

        /* TODO: put the equipment in struct terrain, faster */
        sprintf(equip_hash, "terrain_%s", terrain->_name);
        equip_items(&r->land->items, get_equipment(equip_hash));

        if (r->terrain->herbs) {
            int len = 0;
            while (r->terrain->herbs[len])
                ++len;
            if (len)
                itype = r->terrain->herbs[rng_int() % len];
        }
        if (itype != NULL) {
            rsetherbtype(r, itype);
            rsetherbs(r, (short)(50 + rng_int() % 31));
        }
        else {
            rsetherbtype(r, NULL);
        }
        if (oldterrain == NULL || !fval(oldterrain, LAND_REGION)) {
            if (rng_int() % 100 < 3)
                fset(r, RF_MALLORN);
            else
                freset(r, RF_MALLORN);
            if (rng_int() % 100 < ENCCHANCE) {
                fset(r, RF_ENCOUNTER);
            }
        }
    }

    if (oldterrain == NULL || terrain->size != oldterrain->size) {
        if (terrain == newterrain(T_PLAIN)) {
            rsethorses(r, rng_int() % (terrain->size / 50));
            if (rng_int() % 100 < 40) {
                rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000);
            }
        }
        else if (chance(0.2)) {
            rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000);
        }
        else {
            rsettrees(r, 2, 0);
        }
        rsettrees(r, 1, rtrees(r, 2) / 4);
        rsettrees(r, 0, rtrees(r, 2) / 8);

        if (!fval(r, RF_CHAOTIC)) {
            int peasants;
            peasants = (maxworkingpeasants(r) * (20 + dice_rand("6d10"))) / 100;
            rsetpeasants(r, _max(100, peasants));
            rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL,
                INT_MAX) + 1) + rng_int() % 5));
        }
    }
}