static void test_get_monsters(CuTest *tc) { faction *f; free_gamedata(); CuAssertPtrNotNull(tc, (f = get_monsters())); CuAssertPtrEquals(tc, f, get_monsters()); CuAssertIntEquals(tc, 666, f->no); CuAssertStrEquals(tc, "Monster", f->name); test_cleanup(); }
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); }
void make_zombie(unit * u) { u_setfaction(u, get_monsters()); scale_number(u, 1); u_setrace(u, new_race[RC_ZOMBIE]); u->irace = NULL; }
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; }
void randomevents(void) { region *r; faction *monsters = get_monsters(); icebergs(); godcurse(); orc_growth(); demon_skillchanges(); volcano_update(); /* 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_update(); #ifdef HERBS_ROT rotting_herbs(); #endif dissolve_units(); }
static void test_remove_dead_factions(CuTest *tc) { faction *f, *fm; region *r; int fno; test_cleanup(); r = test_create_region(0, 0, 0); fm = get_or_create_monsters(); f = test_create_faction(0); assert(fm && r && f); test_create_unit(f, r); test_create_unit(fm, r); remove_empty_factions(); CuAssertPtrEquals(tc, f, findfaction(f->no)); CuAssertPtrNotNull(tc, get_monsters()); fm->units = 0; f->_alive = false; fno = f->no; remove_empty_factions(); CuAssertPtrEquals(tc, 0, findfaction(fno)); CuAssertPtrEquals(tc, fm, get_monsters()); test_cleanup(); }
static void test_remove_empty_factions(CuTest *tc) { faction *f, *fm; int fno; test_cleanup(); fm = get_or_create_monsters(); assert(fm); f = test_create_faction(0); fno = f->no; remove_empty_factions(); CuAssertIntEquals(tc, false, f->_alive); CuAssertPtrEquals(tc, fm, factions); CuAssertPtrEquals(tc, NULL, fm->next); CuAssertPtrEquals(tc, 0, findfaction(fno)); CuAssertPtrEquals(tc, fm, get_monsters()); test_cleanup(); }
int sp_summon_alp(struct castorder *co) { unit *alp, *opfer; region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; spellparameter *pa = co->par; const struct race *rc = get_race(RC_ALP); struct faction *f = get_monsters(); struct message *msg; opfer = pa->param[0]->data.u; /* Der Alp gehört den Monstern, darum erhält der Magier auch keine * Regionsberichte von ihm. Er erhält aber später eine Mitteilung, * sobald der Alp sein Opfer erreicht hat. */ alp = create_unit(r, f, 1, rc, 0, NULL, NULL); set_level(alp, SK_STEALTH, 7); setstatus(alp, ST_FLEE); /* flieht */ { attrib *a = a_add(&alp->attribs, a_new(&at_alp)); alp_data *ad = (alp_data *) a->data.v; ad->mage = mage; ad->target = opfer; } { /* Wenn der Alp stirbt, den Magier nachrichtigen */ add_trigger(&alp->attribs, "destroy", trigger_unitmessage(mage, "trigger_alp_destroy", MSG_EVENT, ML_INFO)); /* Wenn Opfer oder Magier nicht mehr existieren, dann stirbt der Alp */ add_trigger(&mage->attribs, "destroy", trigger_killunit(alp)); add_trigger(&opfer->attribs, "destroy", trigger_killunit(alp)); } msg = msg_message("summon_alp_effect", "mage alp target", mage, alp, opfer); r_addmessage(r, mage->faction, msg); msg_release(msg); return cast_level; }
void age_undead(unit * u) { region *r = u->region; int n = 0; /* untote, die einer partei angehoeren, koennen sich * absplitten, anstatt sich zu vermehren. monster * untote vermehren sich nur noch */ if (u->number > UNDEAD_MIN && !is_monsters(u->faction) && rng_int() % 100 < UNDEAD_BREAKUP) { int m; unit *u2; n = 0; for (m = u->number; m; m--) { if (rng_int() % 100 < UNDEAD_BREAKUP_FRACTION) ++n; } u2 = create_unit(r, get_monsters(), 0, get_race(RC_UNDEAD), 0, NULL, u); make_undead_unit(u2); transfermen(u, u2, u->number - n); } }
void chaos(region * r) { if (rng_int() % 100 < 8) { switch (rng_int() % 3) { case 0: /* Untote */ if (!fval(r->terrain, SEA_REGION)) { unit *u = random_unit(r); if (u && playerrace(u_race(u))) { ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); u_setfaction(u, get_monsters()); u_setrace(u, get_race(RC_GHOUL)); } } break; case 1: /* Drachen */ if (random_unit(r)) { int mfac = 0; unit *u; switch (rng_int() % 3) { case 0: mfac = 100; u = createunit(r, get_monsters(), rng_int() % 8 + 1, get_race(RC_FIREDRAGON)); break; case 1: mfac = 500; u = createunit(r, get_monsters(), rng_int() % 4 + 1, get_race(RC_DRAGON)); break; default: mfac = 1000; u = createunit(r, get_monsters(), rng_int() % 2 + 1, get_race(RC_WYRM)); break; } if (mfac) set_money(u, u->number * (rng_int() % mfac)); fset(u, UFL_ISNEW | UFL_MOVED); } case 2: /* Terrainveränderung */ if (!fval(r->terrain, FORBIDDEN_REGION)) { if (!fval(r->terrain, SEA_REGION)) { direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); if (rn && fval(rn->terrain, SEA_REGION)) break; } if (dir != MAXDIRECTIONS) { ship *sh = r->ships; unit **up; while (sh) { ship *nsh = sh->next; float dmg = get_param_flt(global.parameters, "rules.ship.damage.atlantis", 0.50); damage_ship(sh, dmg); if (sh->damage >= sh->size * DAMAGE_SCALE) { remove_ship(&sh->region->ships, sh); } sh = nsh; } for (up = &r->units; *up;) { unit *u = *up; if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) { ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill", "region unit", r, u)); remove_unit(up, u); } if (*up == u) up = &u->next; } ADDMSG(&r->msgs, msg_message("tidalwave", "region", r)); while (r->buildings) { remove_building(&r->buildings, r->buildings); } terraform_region(r, newterrain(T_OCEAN)); } } else { direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); if (rn && fval(rn->terrain, SEA_REGION)) break; } if (dir != MAXDIRECTIONS) { terraform_region(r, chaosterrain()); } } } } } }
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(); }
/** 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)); } } } }