Exemple #1
0
static int scareaway(region * r, int anzahl)
{
    int n, p, diff = 0, emigrants[MAXDIRECTIONS];
    direction_t d;

    anzahl = _min(_max(1, anzahl), rpeasants(r));

    /* Wandern am Ende der Woche (normal) oder wegen Monster. Die
     * Wanderung wird erst am Ende von demographics () ausgefuehrt.
     * emigrants[] ist local, weil r->newpeasants durch die Monster
     * vielleicht schon hochgezaehlt worden ist. */

    for (d = 0; d != MAXDIRECTIONS; d++)
        emigrants[d] = 0;

    p = rpeasants(r);
    assert(p >= 0 && anzahl >= 0);
    for (n = _min(p, anzahl); n; n--) {
        direction_t dir = (direction_t) (rng_int() % MAXDIRECTIONS);
        region *rc = rconnect(r, dir);

        if (rc && fval(rc->terrain, LAND_REGION)) {
            ++diff;
            rc->land->newpeasants++;
            emigrants[dir]++;
        }
    }
    rsetpeasants(r, p - diff);
    assert(p >= diff);
    return diff;
}
Exemple #2
0
static void prepare_starting_region(region * r)
{
    int n, t;
    double p;

    assert(r->land);

    /* population between 30% and 60% of max */
    p = rng_double();
    n = (int)(r->terrain->size * (0.3 + p * 0.3));
    rsetpeasants(r, n);

    /* trees: don't squash the peasants, and at least 5% should be forrest */
    t = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE;
    if (t < r->terrain->size / 20 || t + n > r->terrain->size) {
        double p2 = 0.05 + rng_double() * (1.0 - p - 0.05);
        int maxtrees = (int)(r->terrain->size / 1.25 / TREESIZE);   /* 1.25 = each young tree will take 1/2 the space of old trees */
        int trees = (int)(p2 * maxtrees);

        rsettrees(r, 2, trees);
        rsettrees(r, 1, trees / 2);
        rsettrees(r, 0, trees / 4);
    }

    /* horses: between 1% and 2% */
    p = rng_double();
    rsethorses(r, (int)(r->terrain->size * (0.01 + p * 0.01)));

    if (!markets_module()) {
        fix_demand(r);
    }
}
Exemple #3
0
unit *addplayer(region * r, faction * f)
{
    unit *u;
    const char * name;

    assert(r->land);
    if (rpeasants(r) < PEASANT_MIN) {
        rsetpeasants(r, PEASANT_MIN + rng_int() % (PEASANT_MAX - PEASANT_MIN));
    }

    assert(f->units == NULL);
    faction_setorigin(f, 0, r->x, r->y);
    u = create_unit(r, f, 1, f->race, 0, NULL, NULL);
    u->thisorder = default_order(f->locale);
    unit_addorder(u, copy_order(u->thisorder));
    name = config_get("rules.equip_first");
    if (!equip_unit(u, name ? name : "first_unit")) {
        /* give every unit enough money to survive the first turn */
        i_change(&u->items, get_resourcetype(R_SILVER)->itype, maintenance_cost(u));
    }
    u->hp = unit_max_hp(u) * u->number;
    fset(u, UFL_ISNEW);
    if (f->race == get_race(RC_DAEMON)) {
        race_t urc;
        const race *rc;
        do {
            urc = (race_t)(rng_int() % MAXRACES);
            rc = get_race(urc);
        } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
        u->irace = rc;
    }
    f->lastorders = 0;
    return u;
}
Exemple #4
0
void region_setresource(region * r, const resource_type * rtype, int value)
{
    rawmaterial *rm = r->resources;
    while (rm) {
        if (rm->type->rtype == rtype) {
            rm->amount = value;
            break;
        }
        rm = rm->next;
    }
    if (!rm) {
        if (rtype == get_resourcetype(R_SILVER))
            rsetmoney(r, value);
        else if (rtype == get_resourcetype(R_PEASANT))
            rsetpeasants(r, value);
        else if (rtype == get_resourcetype(R_HORSE))
            rsethorses(r, value);
        else {
            int i;
            for (i = 0; r->terrain->production[i].type; ++i) {
                const terrain_production *production = r->terrain->production + i;
                if (production->type == rtype) {
                    add_resource(r, 1, value, dice_rand(production->divisor), rtype);
                    break;
                }
            }
        }
    }
}
Exemple #5
0
static void test_dragon_moves(CuTest * tc)
{
    faction *f, *f2;
    region *r;
    unit *u, *m;
    struct message *msg;

    create_monsters(&f, &f2, &u, &m);
    rsetmoney(findregion(1, 0), 1000);
    r = findregion(0, 0); // plain
    rsetpeasants(r, 0);
    rsetmoney(r, 0);

    set_level(m, SK_WEAPONLESS, 10);
    config_set("rules.monsters.attack_chance", ".0");
    plan_monsters(f2);

    CuAssertPtrNotNull(tc, find_order("move east", m));

    mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "growl:string", 0));

    random_growl(m, findregion(1, 0), 3);

    msg = test_get_last_message(r->msgs);
    assert_message(tc, msg, "dragon_growl", 4);
    assert_pointer_parameter(tc, msg, 0, m);
    assert_int_parameter(tc, msg, 1, 1);
    assert_pointer_parameter(tc, msg, 2, findregion(1,0));
    assert_string_parameter(tc, msg, 3, "growl3");

    test_cleanup();
}
Exemple #6
0
struct region *test_create_region(int x, int y, const terrain_type *terrain)
{
  region *r = new_region(x, y, NULL, 0);
  terraform_region(r, terrain);
  rsettrees(r, 0, 0);
  rsettrees(r, 1, 0);
  rsettrees(r, 2, 0);
  rsethorses(r, 0);
  rsetpeasants(r, terrain->size);
  return r;
}
Exemple #7
0
static void test_give_unit_to_peasants(CuTest * tc) {
    struct give env = { 0 };
    test_setup_ex(tc);
    env.f1 = test_create_faction(NULL);
    env.f2 = 0;
    setup_give(&env);
    rsetpeasants(env.r, 0);
    give_unit(env.src, NULL, NULL);
    CuAssertIntEquals(tc, 0, env.src->number);
    CuAssertIntEquals(tc, 1, rpeasants(env.r));
    test_teardown();
}
Exemple #8
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();
}
Exemple #9
0
static void test_give_peasants(CuTest * tc) {
    struct give env = { 0 };
    message * msg;

    test_setup_ex(tc);
    env.f1 = test_create_faction(NULL);
    env.f2 = 0;
    setup_give(&env);
    rsetpeasants(env.r, 0);
    msg = disband_men(1, env.src, NULL);
    CuAssertStrEquals(tc, "give_person_peasants", test_get_messagetype(msg));
    CuAssertIntEquals(tc, 0, env.src->number);
    CuAssertIntEquals(tc, 1, rpeasants(env.r));
    msg_release(msg);
    test_teardown();
}
Exemple #10
0
static struct unit *create_recruiter(void) {
    region *r;
    faction *f;
    unit *u;
    const resource_type* rtype;

    test_cleanup();
    test_create_world();

    r=findregion(0, 0);
    rsetpeasants(r, 999);
    f = test_create_faction(rc_find("human"));
    u = test_create_unit(f, r);
    rtype = get_resourcetype(R_SILVER);
    change_resource(u, rtype, 1000);
    return u;
}
Exemple #11
0
static void test_dragon_moves(CuTest * tc)
{
    faction *f, *f2;
    region *r;
    unit *u, *m;

    create_monsters(&f, &f2, &r, &u, &m);
    rsetpeasants(r, 0);
    rsetmoney(r, 0);
    rsetmoney(findregion(1, 0), 1000);

    set_level(m, SK_WEAPONLESS, 10);
    config_set("rules.monsters.attack_chance", ".0");
    plan_monsters(f2);

    CuAssertPtrNotNull(tc, find_order("NACH O", m));
    test_cleanup();
}
Exemple #12
0
static void eaten_by_monster(unit * u)
{
  /* adjustment for smaller worlds */
  static double multi = 0.0;
  int n = 0;
  int horse = 0;

  if (multi == 0.0) {
    multi = RESOURCE_QUANTITY * newterrain(T_PLAIN)->size / 10000.0;
  }

  switch (old_race(u_race(u))) {
    case RC_FIREDRAGON:
      n = rng_int() % 80 * u->number;
      horse = get_item(u, I_HORSE);
      break;
    case RC_DRAGON:
      n = rng_int() % 200 * u->number;
      horse = get_item(u, I_HORSE);
      break;
    case RC_WYRM:
      n = rng_int() % 500 * u->number;
      horse = get_item(u, I_HORSE);
      break;
    default:
      n = rng_int() % (u->number / 20 + 1);
  }

  n = (int)(n * multi);
  if (n > 0) {
    n = lovar(n);
    n = MIN(rpeasants(u->region), n);

    if (n > 0) {
      deathcounts(u->region, n);
      rsetpeasants(u->region, rpeasants(u->region) - n);
      ADDMSG(&u->region->msgs, msg_message("eatpeasants", "unit amount", u, n));
    }
  }
  if (horse > 0) {
    set_item(u, I_HORSE, 0);
    ADDMSG(&u->region->msgs, msg_message("eathorse", "unit amount", u, horse));
  }
}
Exemple #13
0
static void absorbed_by_monster(unit * u)
{
    int n;

    switch (old_race(u_race(u))) {
    default:
        n = rng_int() % (u->number / 20 + 1);
    }

    if (n > 0) {
        n = lovar(n);
        n = _min(rpeasants(u->region), n);
        if (n > 0) {
            rsetpeasants(u->region, rpeasants(u->region) - n);
            scale_number(u, u->number + n);
            ADDMSG(&u->region->msgs, msg_message("absorbpeasants",
                                                 "unit race amount", u, u_race(u), n));
        }
    }
}
Exemple #14
0
void plagues(region * r)
{
    int peasants;
    int i;
    int dead = 0;

    peasants = rpeasants(r);
    dead = (int)(0.5 + PLAGUE_VICTIMS * peasants);
    for (i = dead; i != 0; i--) {
        if (rng_double() < PLAGUE_HEALCHANCE && rmoney(r) >= PLAGUE_HEALCOST) {
            rsetmoney(r, rmoney(r) - PLAGUE_HEALCOST);
            --dead;
        }
    }

    if (dead > 0) {
        message *msg = add_message(&r->msgs, msg_message("pest", "dead", dead));
        msg_release(msg);
        deathcounts(r, dead);
        rsetpeasants(r, peasants - dead);
    }
}
Exemple #15
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));
        }
    }
}
Exemple #16
0
/* In a->data.ca[1] steht der Prozentsatz mit dem sich die Einheit
 * auflöst, in a->data.ca[0] kann angegeben werden, wohin die Personen
 * verschwinden. Passiert bereits in der ersten Runde! */
static void dissolve_units(void)
{
  region *r;
  unit *u;
  int n;
  int i;

  for (r = regions; r; r = r->next) {
    for (u = r->units; u; u = u->next) {
      attrib *a = a_find(u->attribs, &at_unitdissolve);
      if (a) {
        message *msg;

        if (u->age == 0 && a->data.ca[1] < 100)
          continue;

        /* TODO: Durch einzelne Berechnung ersetzen */
        if (a->data.ca[1] == 100) {
          n = u->number;
        } else {
          n = 0;
          for (i = 0; i < u->number; i++) {
            if (rng_int() % 100 < a->data.ca[1])
              n++;
          }
        }

        /* wenn keiner verschwindet, auch keine Meldung */
        if (n == 0) {
          continue;
        }

        scale_number(u, u->number - n);

        switch (a->data.ca[0]) {
          case 1:
            rsetpeasants(r, rpeasants(r) + n);
            msg =
              msg_message("dissolve_units_1", "unit region number race", u, r,
              n, u_race(u));
            break;
          case 2:
            if (r->land && !fval(r, RF_MALLORN)) {
              rsettrees(r, 2, rtrees(r, 2) + n);
              msg =
                msg_message("dissolve_units_2", "unit region number race", u, r,
                n, u_race(u));
            } else {
              msg =
                msg_message("dissolve_units_3", "unit region number race", u, r,
                n, u_race(u));
            }
            break;
          default:
              if (u_race(u) == get_race(RC_STONEGOLEM)
                  || u_race(u) == get_race(RC_IRONGOLEM)) {
              msg =
                msg_message("dissolve_units_4", "unit region number race", u, r,
                n, u_race(u));
            } else {
              msg =
                msg_message("dissolve_units_5", "unit region number race", u, r,
                n, u_race(u));
            }
            break;
        }

        add_message(&u->faction->msgs, msg);
        msg_release(msg);
      }
    }
  }

  remove_empty_units();
}
Exemple #17
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);
                    }
                }
            }
        }
    }
}
Exemple #18
0
void create_museum(void)
{
#if 0                           /* TODO: move this to Lua. It should be possible. */
    unsigned int museum_id = hashstring("museum");
    plane *museum = getplanebyid(museum_id);
    region *r;
    building *b;
    const terrain_type *terrain_hall = get_terrain("hall1");
    const terrain_type *terrain_corridor = get_terrain("corridor1");

    assert(terrain_corridor && terrain_hall);

    if (!museum) {
        museum = create_new_plane(museum_id, "Museum", 9500, 9550,
            9500, 9550, PFL_MUSEUM);
    }

    if (findregion(9525, 9525) == NULL) {
        /* Eingangshalle */
        r = new_region(9525, 9525, 0);
        terraform_region(r, terrain_hall);
        r->planep = museum;
        rsetname(r, "Eingangshalle");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Eingangshalle des Großen Museum der 1. Welt ist bereits jetzt ein beeindruckender Anblick. Obwohl das Museum noch nicht eröffnet ist, vermittelt sie bereits einen Flair exotischer Welten. In den Boden ist ein großer Kompass eingelassen, der den Besuchern bei Orientierung helfen soll.");
    }

    r = findregion(9526, 9525);
    if (!r) {
        /* Lounge */
        r = new_region(9526, 9525, 0);
        terraform_region(r, terrain_hall);
        r->planep = museum;
        rsetname(r, "Lounge");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Lounge des großen Museums ist ein Platz, in dem sich die Besucher treffen, um die Eindrücke, die sie gewonnen haben, zu verarbeiten. Gemütliche Sitzgruppen laden zum Verweilen ein.");
    }

    r = findregion(9526, 9525);
    if (!r->buildings) {
        const building_type *bt_generic = bt_find("generic");
        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im dämonischen Stil");
        set_string(&b->display,
            "Diese ganz im dämonischen Stil gehaltene Sitzgruppe ist ganz in dunklen Schwarztönen gehalten. Muster fremdartiger Runen bedecken das merkwürdig geformte Mobiliar, das unangenehm lebendig wirkt.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im elfischen Stil");
        set_string(&b->display,
            "Ganz in Grün- und Brauntönen gehalten wirkt die Sitzgruppe fast lebendig. Bei näherer Betrachtung erschließt sich dem Betrachter, daß sie tatsächlich aus lebenden Pflanzen erstellt ist. So ist der Tisch aus einem eizigen Baum gewachsen, und die Polster bestehen aus weichen Grassoden. Ein wunderschön gemusterter Webteppich mit tausenden naturgetreu eingestickter Blumensarten bedeckt den Boden.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im halblingschen Stil");
        set_string(&b->display,
            "Dieses rustikale Mobiliar ist aus einem einzigen, gewaltigen Baum hergestellt worden. Den Stamm haben fleißige Halblinge der Länge nach gevierteilt und aus den vier langen Viertelstämmen die Sitzbänke geschnitzt, während der verbleibende Stumpf als Tisch dient. Schon von weitem steigen dem Besucher die Gerüche der Köstlichkeiten entgegen, die auf dem Tisch stapeln.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im orkischen Stil");
        set_string(&b->display,
            "Grobgeschreinerte, elfenhautbespannte Stühle und ein Tisch aus Knochen, über deren Herkunft man sich lieber keine Gedanken macht, bilden die Sitzgruppe im orkischen Stil. Überall haben Orks ihre Namen, und anderes wenig zitierenswertes in das Holz und Gebein geritzt.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im Meermenschenstil");
        set_string(&b->display,
            "Ganz in Blau- und Grüntönen gehalten, mit Algen und Muscheln verziert wirken die aus altem Meerholz geschnitzten Stühle immer ein wenig feucht. Seltsammerweise hat der schwere aus alten Planken gezimmerte Tisch einen Mast mit kompletten Segel in der Mitte.");

        b = new_building(bt_generic, r, NULL);
        set_string(&b->name, "Séparée im Katzenstil");
        set_string(&b->display,
            "Die Wände dieses Séparée sind aus dunklem Holz. Was aus der Ferne wie ein chaotisch durchbrochenes Flechtwerk wirkt, entpuppt sich bei näherer Betrachtung als eine bis in winzige Details gestaltete dschungelartige Landschaft, in die eine Vielzahl von kleinen Bildergeschichten eingewoben sind. Wie es scheint hat sich der Künstler Mühe gegeben wirklich jedes Katzenvolk Eresseas zu porträtieren. Das schummrige Innere wird von einem Kamin dominiert, vor dem einige Sessel und weiche Kissen zu einem gemütlichen Nickerchen einladen. Feiner Anduner Sisal bezieht die Lehnen der Sessel und verlockt dazu, seine Krallen hinein zu versenken. Auf einem kleinen Ecktisch steht ein großer Korb mit roten Wollknäulen und grauen und braunen Spielmäusen.");
    } else {
        for (b = r->buildings; b; b = b->next) {
            b->size = b->type->maxsize;
        }
    }

    r = findregion(9524, 9526);
    if (!r) {
        r = new_region(9524, 9526, 0);
        terraform_region(r, terrain_corridor);
        r->planep = museum;
        rsetname(r, "Nördliche Promenade");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Nördliche Promenade führt direkt in den naturgeschichtlichen Teil des Museums.");
    }
    r = findregion(9525, 9524);
    if (!r) {
        r = new_region(9525, 9524, 0);
        terraform_region(r, terrain_corridor);
        r->planep = museum;
        rsetname(r, "Südliche Promenade");
        rsethorses(r, 0);
        rsetmoney(r, 0);
        rsetpeasants(r, 0);
        set_string(&r->display,
            "Die Südliche Promenade führt den Besucher in den kulturgeschichtlichen Teil des Museums.");
    }
#endif
}
Exemple #19
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);
      }
    }
  }
}
Exemple #20
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);
    }
}