Beispiel #1
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;
}
Beispiel #2
0
static unit *random_unit(const region * r)
{
  int c = 0;
  int n;
  unit *u;

  for (u = r->units; u; u = u->next) {
      if (u_race(u) != get_race(RC_SPELL)) {
      c += u->number;
    }
  }

  if (c == 0) {
    return NULL;
  }
  n = rng_int() % c;
  c = 0;
  u = r->units;

  while (u && c < n) {
      if (u_race(u) != get_race(RC_SPELL)) {
      c += u->number;
    }
    u = u->next;
  }

  return u;
}
Beispiel #3
0
/* In general, the class index is given by player_type.pclass. However, for various
 * monster races, the "class" behavior is actually determined by the race, and we
 * encode this desire with race_t.pseudo_class_idx. As another twist, consider the
 * possessor. Here, the "class" behavior depends on the current body (see r_info.text).
 */
int get_class_idx(void)
{
    int result = p_ptr->pclass;

    if (result == CLASS_MONSTER)
    {
        switch (p_ptr->prace)
        {
        case RACE_MON_POSSESSOR:
        case RACE_MON_MIMIC:
            if (p_ptr->current_r_idx)
            {
                result = r_info[p_ptr->current_r_idx].body.class_idx;
                break;
            }
            /* vvv Fall Through vvv */
        default:
        {
            race_t *race_ptr = get_race();
            /*if (race_ptr->pseudo_class_idx) Note: CLASS_WARRIOR = 0! */
                result = race_ptr->pseudo_class_idx;
        }
        }
    }
    return result;
}
Beispiel #4
0
int rc_skillmod(const struct race *rc, const region * r, skill_t sk)
{
    int mods = 0;

    if (!skill_enabled(sk)) {
        return 0;
    }
#ifdef FASTER_SKILLMOD
    unsigned int index = hashstring(rc->_name) % RCMODMAXHASH;
    struct skillmods **imods = &modhash[index];
    while (*imods && (*imods)->race != rc) {
        imods = &(*imods)->next;
    }
    if (*imods == NULL) {
        *imods = init_skills(rc);
    }
    mods = (*imods)->mod[rterrain(r)].value[sk];
#else
    if (r) {
        mods = skill_mod(rc, sk, r->terrain);
    }
#endif
    if (rc == get_race(RC_ELF) && r && r_isforest(r)) {
        if (sk == SK_PERCEPTION || sk == SK_STEALTH) {
            ++mods;
        }
        else if (sk == SK_TACTICS) {
            mods += 2;
        }
    }
    return mods;
}
Beispiel #5
0
static void recruit_dracoids(unit * dragon, int size)
{
    faction *f = dragon->faction;
    region *r = dragon->region;
    const struct item *weapon = NULL;
    order *new_order = NULL;
    unit *un = create_unit(r, f, size, get_race(RC_DRACOID), 0, NULL, NULL);

    fset(un, UFL_ISNEW | UFL_MOVED);

    name_unit(un);
    change_money(dragon, -un->number * 50);
    equip_unit(un, get_equipment("recruited_dracoid"));

    setstatus(un, ST_FIGHT);
    for (weapon = un->items; weapon; weapon = weapon->next) {
        const weapon_type *wtype = weapon->type->rtype->wtype;
        if (wtype && (wtype->flags & WTF_MISSILE)) {
            setstatus(un, ST_BEHIND);
        }
        new_order = create_order(K_STUDY, f->locale, "'%s'",
            skillname(weapon->type->rtype->wtype->skill, f->locale));
    }

    if (new_order != NULL) {
        addlist(&un->orders, new_order);
    }
}
int bt_effsize(const building_type * btype, const building * b, int bsize)
{
    int i = bsize, n = 0;
    const construction *cons = btype->construction;

    /* TECH DEBT: simplest thing that works for E3 dwarf/halfling faction rules */
    if (b && config_get_int("rules.dwarf_castles", 0)
        && strcmp(btype->_name, "castle") == 0) {
        unit *u = building_owner(b);
        if (u && u->faction->race == get_race(RC_HALFLING)) {
            i = bsize * 10 / 8;
        }
    }

    if (!cons || !cons->improvement) {
        return 0;
    }

    while (cons && cons->maxsize != -1 && i >= cons->maxsize) {
        i -= cons->maxsize;
        cons = cons->improvement;
        ++n;
    }

    return n;
}
Beispiel #7
0
void save_special_items(unit *usrc)
{
    unit *u;
    region *r = usrc->region;
    faction *fm = get_monsters();
    static const race *rc_ghost;
    static int cache;

    if (rc_changed(&cache)) {
        rc_ghost = get_race(RC_TEMPLATE);
    }
    for (u = r->units; u; u = u->next) {
        if (u->faction == fm) {
            give_special_items(u, &usrc->items);
            return;
        }
    }
    u = create_unit(r, fm, 1, rc_ghost, 0, NULL, NULL);
    unit_setname(u, unit_getname(usrc));
    if (usrc->number > 1) {
        /* some units have plural names, it would be neat if they aren't single: */
        scale_number(u, 2);
    }
    set_racename(&u->attribs, "ghost");
    give_special_items(u, &usrc->items);
}
Beispiel #8
0
static void summarize_races(const summary *s, FILE *F, bool full) {
    int i;
    for (i = 0; i < MAXRACES; i++) {
        if (s->poprace[i] > 0) {
            const char *pad = "      ";
            int lpad = (int)strlen(pad);
            const race *rc = get_race(i);
            const char *rcname = LOC(default_locale, rc_name_s(rc, NAME_PLURAL));
            lpad -= count_umlaut(rcname);
            assert(lpad >= 0);
            if (full) {
                fputs(pad + lpad, F);
                fprintf(F, "%20s: ", rcname);
                fprintf(F, "%8d\n", s->poprace[i]);
            }
            else if (i != RC_TEMPLATE && i != RC_CLONE) {
                if (playerrace(rc)) {
                    fputs(pad + lpad, F);
                    fprintf(F, "%16s: ", rcname);
                    fprintf(F, "%8d\n", s->poprace[i]);
                }
            }
        }
    }
}
Beispiel #9
0
void drown(region * r)
{
  if (fval(r->terrain, SEA_REGION)) {
    unit **up = up = &r->units;
    while (*up) {
      unit *u = *up;
      int amphibian_level = 0;
      if (u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0) {
        up = &u->next;
        continue;
      }

      if (amphibian_level) {
        int dead = damage_unit(u, "5d1", false, false);
        if (dead) {
          ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_dead",
              "amount unit region", dead, u, r));
        } else {
          ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_nodead",
              "unit region", u, r));
        }
      } else if (!(canswim(u) || canfly(u))) {
        scale_number(u, 0);
        ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r));
      }
      if (*up == u)
        up = &u->next;
    }
    remove_empty_units_in_region(r);
  }
}
Beispiel #10
0
/* wiederbeleben */
int sp_reanimate(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    battle *b = fi->side->battle;
    unit *mage = fi->unit;
    int healable, j = 0;
    double c = 0.50 + 0.02 * power;
    double k = EFFECT_HEALING_SPELL * power;
    bool use_item = has_ao_healing(mage);
    message *msg;

    if (use_item) {
        k *= 2;
        c += 0.10;
    }

    healable = count_healable(b, fi);
    healable = (int)_min(k, healable);
    while (healable--) {
        fighter *tf = select_corpse(b, fi);
        if (tf != NULL && tf->side->casualties > 0
            && u_race(tf->unit) != get_race(RC_DAEMON)
            && (chance(c))) {
            assert(tf->alive < tf->unit->number);
            /* t.fighter->person[].hp beginnt mit t.index = 0 zu z�hlen,
             * t.fighter->alive ist jedoch die Anzahl lebender in der Einheit,
             * also sind die hp von t.fighter->alive
             * t.fighter->hitpoints[t.fighter->alive-1] und der erste Tote
             * oder weggelaufene ist t.fighter->hitpoints[tf->alive] */
            tf->person[tf->alive].hp = 2;
            ++tf->alive;
            ++tf->side->size[SUM_ROW];
            ++tf->side->size[tf->unit->status + 1];
            ++tf->side->healed;
            --tf->side->casualties;
            assert(tf->side->casualties >= 0);
            --tf->side->dead;
            assert(tf->side->dead >= 0);
            ++j;
        }
    }
    if (j <= 0) {
        level = j;
    }
    if (use_item) {
        msg =
            msg_message("reanimate_effect_1", "mage amount item", mage, j,
            get_resourcetype(R_AMULET_OF_HEALING));
    }
    else {
        msg = msg_message("reanimate_effect_0", "mage amount", mage, j);
    }
    message_all(b, msg);
    msg_release(msg);

    return level;
}
Beispiel #11
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 = get_race(RC_ILLUSION);
        f->age = turn;
        f->locale = get_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 != get_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 = create_unit(r, f, 1, get_race(RC_GOBLIN), 0, NULL, NULL);
            set_string(&u->name, "Igjarjuks Auge");
            i_change(&u->items, it_find("roi"), 1);
            set_order(&u->thisorder, NULL);
            fset(u, UFL_ANON_FACTION);
            set_money(u, 1000);
        }
}
Beispiel #12
0
void make_zombie(unit * u)
{
    u_setfaction(u, get_monsters());
    scale_number(u, 1);
    u->hp = unit_max_hp(u) * u->number;
    u_setrace(u, get_race(RC_ZOMBIE));
    u->irace = NULL;
}
Beispiel #13
0
/* ------------------------------------------------------------- */
bool magic_lowskill(unit * u)
{
    static const race *toad_rc;
    static int cache;
    if (rc_changed(&cache)) {
        toad_rc = get_race(RC_TOAD);
    }
    return u_race(u) == toad_rc;
}
Beispiel #14
0
static order *monster_seeks_target(region * r, unit * u)
{
    direction_t d;
    unit *target = NULL;
    int dist, dist2;
    direction_t i;
    region *nr;

    /* Das Monster sucht ein bestimmtes Opfer. Welches, steht
     * in einer Referenz/attribut
     * derzeit gibt es nur den alp
     */

    switch (old_race(u_race(u))) {
    case RC_ALP:
        target = alp_target(u);
        break;
    default:
        assert(!"Seeker-Monster gibt kein Ziel an");
    }

    /* TODO: prüfen, ob target überhaupt noch existiert... */
    if (!target) {
        log_error("Monster '%s' hat kein Ziel!\n", unitname(u));
        return NULL;                /* this is a bug workaround! remove!! */
    }

    if (r == target->region) {    /* Wir haben ihn! */
        if (u_race(u) == get_race(RC_ALP)) {
            alp_findet_opfer(u, r);
        } else {
            assert(!"Seeker-Monster hat keine Aktion fuer Ziel");
        }
        return NULL;
    }

    /* Simpler Ansatz: Nachbarregion mit gerinster Distanz suchen.
     * Sinnvoll momentan nur bei Monstern, die sich nicht um das
     * Terrain kümmern.  Nebelwände & Co machen derzeit auch nix...
     */
    dist2 = distance(r, target->region);
    d = NODIRECTION;
    for (i = 0; i < MAXDIRECTIONS; i++) {
        nr = rconnect(r, i);
        assert(nr);
        dist = distance(nr, target->region);
        if (dist < dist2) {
            dist2 = dist;
            d = i;
        }
    }
    assert(d != NODIRECTION);

    return create_order(K_MOVE, u->faction->locale, "%s",
        LOC(u->faction->locale, directions[d]));
}
Beispiel #15
0
static int _class_idx(void)
{
    int result = p_ptr->pclass;
    if (result == CLASS_MONSTER)
    {
        race_t *race_ptr = get_race();
        result = race_ptr->pseudo_class_idx;
    }
    return result;
}
Beispiel #16
0
int sp_igjarjuk(castorder *co) {
    unit *u;
    fighter *fm = co->magician.fig, *fi;
    const race *rc = get_race(RC_WYRM);
    fi = summon_allies(fm, rc, 1);
    u = fi->unit;
    unit_setname(u, "Igjarjuk");
    log_info("%s summons Igjarjuk in %s", unitname(fm->unit), regionname(u->region, 0));
    return co->level;
}
Beispiel #17
0
static int dragon_affinity_value(region * r, unit * u)
{
    int m = all_money(r, u->faction);

    if (u_race(u) == get_race(RC_FIREDRAGON)) {
        return (int)(normalvariate(m, m / 2));
    }
    else {
        return (int)(normalvariate(m, m / 4));
    }
}
Beispiel #18
0
void age_ghoul(unit * u)
{
  if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
    int n = _max(1, u->number / 2);
    double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
    u_setrace(u, get_race(RC_GHOUL_LORD));
    u->irace = NULL;
    scale_number(u, n);
    u->hp = (int)(unit_max_hp(u) * u->number * q);
  }
}
Beispiel #19
0
void age_zombie(unit * u)
{
    if (is_monsters(u->faction) && rng_int() % 100 < age_chance(u->age, 27, 1)) {
        int n = u->number / 2;
        double q = (double)u->hp / (double)(unit_max_hp(u) * u->number);
        if (n < 1) n = 1;
        u_setrace(u, get_race(RC_ZOMBIE_LORD));
        u->irace = NULL;
        scale_number(u, n);
        u->hp = (int)(unit_max_hp(u) * u->number * q);
    }
}
Beispiel #20
0
/** Talente von Dämonen verschieben sich.
 */
static void demon_skillchanges(void)
{
  region *r;

  for (r = regions; r; r = r->next) {
    unit *u;
    for (u = r->units; u; u = u->next) {
        if (u_race(u) == get_race(RC_DAEMON)) {
        skill *sv = u->skills;
        int upchance = 15;
        int downchance = 10;

        if (fval(u, UFL_HUNGER)) {
          /* hungry demons only go down, never up in skill */
          static int rule_hunger = -1;
          if (rule_hunger < 0) {
            rule_hunger =
              get_param_int(global.parameters, "hunger.demon.skill", 0);
          }
          if (rule_hunger) {
            upchance = 0;
            downchance = 15;
          }
        }

        while (sv != u->skills + u->skill_size) {
          int roll = rng_int() % 100;
          if (sv->level > 0 && roll < upchance + downchance) {
            int weeks = 1 + rng_int() % 3;
            if (roll < downchance) {
              reduce_skill(u, sv, weeks);
              if (sv->level < 1) {
                /* demons should never forget below 1 */
                set_level(u, sv->id, 1);
              }
            } else {
              while (weeks--)
                learn_skill(u, sv->id, 1.0);
            }
            if (sv->old > sv->level) {
              if (verbosity >= 3) {
                log_printf(stdout, "%s dropped from %u to %u:%u in %s\n",
                  unitname(u), sv->old, sv->level, sv->weeks, skillname(sv->id,
                    NULL));
              }
            }
          }
          ++sv;
        }
      }
    }
  }
}
Beispiel #21
0
int skill_mod(const race * rc, skill_t sk, const struct terrain_type *terrain)
{
    int result = 0;

    result = rc->bonus[sk];

    if (rc == get_race(RC_DWARF)) {
        if (sk == SK_TACTICS) {
            if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION))
                ++result;
        }
    }
    else if (rc == get_race(RC_INSECT)) {
        if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION))
            --result;
        else if (terrain == newterrain(T_DESERT) || terrain == newterrain(T_SWAMP))
            ++result;
    }

    return result;
}
Beispiel #22
0
caster_info *get_caster_info(void)
{
    caster_info *result = NULL;
    class_t *class_ptr = get_class();
    race_t *race_ptr = get_race();

    if (race_ptr->caster_info) /* Monster Races: Lich, Angel, Demon */
        result = (race_ptr->caster_info)();
    else if (class_ptr->caster_info)
        result = (class_ptr->caster_info)();
    return result;
}
Beispiel #23
0
/** Drachen und Seeschlangen können entstehen */
void spawn_dragons(void)
{
    region *r;
    faction *monsters = get_or_create_monsters();

    for (r = regions; r; r = r->next) {
        unit *u;

        if (fval(r->terrain, SEA_REGION) && rng_int() % 10000 < 1) {
            u = create_unit(r, monsters, 1, get_race(RC_SEASERPENT), 0, NULL, NULL);
            fset(u, UFL_ISNEW | UFL_MOVED);
            equip_unit(u, get_equipment("monster_seaserpent"));
        }

        if ((r->terrain == newterrain(T_GLACIER)
            || r->terrain == newterrain(T_SWAMP)
            || r->terrain == newterrain(T_DESERT))
            && rng_int() % 10000 < (5 + 100 * chaosfactor(r))) {
            if (chance(0.80)) {
                u = create_unit(r, monsters, nrand(60, 20) + 1, get_race(RC_FIREDRAGON), 0, NULL, NULL);
            }
            else {
                u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL);
            }
            fset(u, UFL_ISNEW | UFL_MOVED);
            equip_unit(u, get_equipment("monster_dragon"));

            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));

            name_unit(u);

            /* add message to the region */
            ADDMSG(&r->msgs,
                msg_message("sighting", "region race number", r, u_race(u), u->number));
        }
    }
}
Beispiel #24
0
/* familiars and toads are not migrants */
bool is_migrant(unit * u)
{
    if (u_race(u) == u->faction->race)
        return false;

    if (fval(u_race(u), RCF_UNDEAD | RCF_ILLUSIONARY))
        return false;
    if (is_familiar(u))
        return false;
    if (u_race(u) == get_race(RC_TOAD))
        return false;

    return true;
}
Beispiel #25
0
static int _get_spell_table(spell_info* spells, int max)
{
    int ct = 0;
    class_t *class_ptr = get_class();
    race_t  *race_ptr = get_race();

    if (race_ptr->get_spells != NULL) /* Monster Races ... */
        ct = (race_ptr->get_spells)(spells, max);
    else if (class_ptr->get_spells != NULL)
        ct = (class_ptr->get_spells)(spells, max);

    _add_extra_costs(spells, ct);
    return ct;
}
Beispiel #26
0
void drown(region * r)
{
    if (fval(r->terrain, SEA_REGION)) {
        unit **up = &r->units;
        while (*up) {
            unit *u = *up;

            if (!(u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0 || canswim(u) || canfly(u))) {
                scale_number(u, 0);
                ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r));
            }

            up = &u->next;
        }
        remove_empty_units_in_region(r);
    }
}
Beispiel #27
0
/* familiars and toads are not migrants */
bool is_migrant(unit * u)
{
    static int cache;
    static const race *toad_rc;

    if (u_race(u) == u->faction->race)
        return false;

    if (fval(u_race(u), RCF_UNDEAD | RCF_ILLUSIONARY))
        return false;
    if (is_familiar(u))
        return false;
    if (rc_changed(&cache)) {
        toad_rc = get_race(RC_TOAD);
    }
    return u_race(u) != toad_rc;
}
Beispiel #28
0
int sp_wolfhowl(castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    double power = co->force;
    int force = (int)(get_force(power, 3) / 2);
    const race * rc = get_race(RC_WOLF);
    if (force > 0) {
        unit *u;
        int skills = (int)(power/3);
        fi = summon_allies(fi, rc, force);
        u = fi->unit;
        set_level(u, SK_WEAPONLESS, skills);
        set_level(u, SK_STAMINA, skills);
        u->hp = u->number * unit_max_hp(u);
    }
    return level;
}
Beispiel #29
0
int max_magicians(const faction * f)
{
    static int rule, config, rc_cache;
    static const race *rc_elf;
    int m;

    if (config_changed(&config)) {
        rule = config_get_int("rules.maxskills.magic", 3);
    }
    m = rule;
    if (rc_changed(&rc_cache)) {
        rc_elf = get_race(RC_ELF);
    }
    if (f->race == rc_elf) {
        ++m;
    }
    return m;
}
Beispiel #30
0
/** Talente von D�monen verschieben sich.
 */
static void demon_skillchanges(void)
{
    region *r;
    static const race *rc_demon;
    static int rc_cache;

    if (rc_changed(&rc_cache)) {
        rc_demon = get_race(RC_DAEMON);
    }
    for (r = regions; r; r = r->next) {
        unit *u;
        for (u = r->units; u; u = u->next) {
            if (u_race(u) == rc_demon) {
                demon_skillchange(u);
            }
        }
    }
}