2010-08-08 10:06:34 +02:00
|
|
|
|
/*
|
2015-01-30 22:10:29 +01:00
|
|
|
|
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
|
2014-12-08 21:19:18 +01:00
|
|
|
|
Katja Zedel <katze@felidae.kn-bremen.de
|
|
|
|
|
Christian Schlittchen <corwin@amber.kn-bremen.de>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
#include <platform.h>
|
|
|
|
|
#include <kernel/config.h>
|
|
|
|
|
#include "randenc.h"
|
|
|
|
|
|
2016-08-21 21:21:56 +02:00
|
|
|
|
#include "volcano.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#include "economy.h"
|
|
|
|
|
#include "monster.h"
|
2014-08-27 06:40:18 +02:00
|
|
|
|
#include "move.h"
|
2014-12-13 11:30:34 +01:00
|
|
|
|
#include "chaos.h"
|
2016-03-08 15:13:49 +01:00
|
|
|
|
#include "study.h"
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
|
|
|
|
/* kernel includes */
|
|
|
|
|
#include <kernel/building.h>
|
|
|
|
|
#include <kernel/curse.h>
|
|
|
|
|
#include <kernel/equipment.h>
|
|
|
|
|
#include <kernel/faction.h>
|
|
|
|
|
#include <kernel/item.h>
|
2014-06-09 18:54:48 +02:00
|
|
|
|
#include <kernel/messages.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#include <kernel/order.h>
|
|
|
|
|
#include <kernel/plane.h>
|
|
|
|
|
#include <kernel/pool.h>
|
|
|
|
|
#include <kernel/race.h>
|
|
|
|
|
#include <kernel/region.h>
|
|
|
|
|
#include <kernel/ship.h>
|
|
|
|
|
#include <kernel/terrain.h>
|
|
|
|
|
#include <kernel/terrainid.h>
|
|
|
|
|
#include <kernel/unit.h>
|
|
|
|
|
|
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/racename.h>
|
|
|
|
|
#include <attributes/reduceproduction.h>
|
|
|
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
|
#include <util/attrib.h>
|
2012-06-04 11:41:07 +02:00
|
|
|
|
#include <util/bsdstring.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#include <util/language.h>
|
|
|
|
|
#include <util/lists.h>
|
|
|
|
|
#include <util/log.h>
|
|
|
|
|
#include <util/rand.h>
|
2014-06-09 18:54:48 +02:00
|
|
|
|
#include <util/message.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#include <util/rng.h>
|
|
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include <attributes/iceberg.h>
|
|
|
|
|
extern struct attrib_type at_unitdissolve;
|
|
|
|
|
extern struct attrib_type at_orcification;
|
|
|
|
|
|
|
|
|
|
/* In a->data.ca[1] steht der Prozentsatz mit dem sich die Einheit
|
|
|
|
|
* aufl<EFBFBD>st, in a->data.ca[0] kann angegeben werden, wohin die Personen
|
|
|
|
|
* verschwinden. Passiert bereits in der ersten Runde! */
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void dissolve_units(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
int n;
|
|
|
|
|
int i;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
if (u->age == 0 && a->data.ca[1] < 100)
|
|
|
|
|
continue;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* 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++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* 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);
|
2011-03-07 08:02:35 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
remove_empty_units();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-17 21:21:23 +01:00
|
|
|
|
static bool improve_all(faction * f, skill_t sk, int by_weeks)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
unit *u;
|
2016-03-17 21:21:23 +01:00
|
|
|
|
bool result = false;
|
2014-12-08 21:19:18 +01:00
|
|
|
|
for (u = f->units; u; u = u->nextF) {
|
|
|
|
|
if (has_skill(u, sk)) {
|
2016-03-17 21:21:23 +01:00
|
|
|
|
learn_skill(u, sk, by_weeks * STUDYDAYS);
|
|
|
|
|
result = true;
|
2014-12-08 21:19:18 +01:00
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
2016-03-17 21:21:23 +01:00
|
|
|
|
return result;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
void find_manual(region * r, unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
char zLocation[32];
|
|
|
|
|
char zBook[32];
|
|
|
|
|
skill_t skill = NOSKILL;
|
|
|
|
|
message *msg;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
switch (rng_int() % 36) {
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 0:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_MAGIC;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_WEAPONSMITH;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_TACTICS;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 7:
|
|
|
|
|
case 8:
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_SHIPBUILDING;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
case 13:
|
|
|
|
|
case 14:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_SAILING;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 15:
|
|
|
|
|
case 16:
|
|
|
|
|
case 17:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_HERBALISM;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 18:
|
|
|
|
|
case 19:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_ALCHEMY;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 20:
|
|
|
|
|
case 21:
|
|
|
|
|
case 22:
|
|
|
|
|
case 23:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_BUILDING;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 24:
|
|
|
|
|
case 25:
|
|
|
|
|
case 26:
|
|
|
|
|
case 27:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_ARMORER;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 28:
|
|
|
|
|
case 29:
|
|
|
|
|
case 30:
|
|
|
|
|
case 31:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_MINING;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 32:
|
|
|
|
|
case 33:
|
|
|
|
|
case 34:
|
|
|
|
|
case 35:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
skill = SK_ENTERTAINMENT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
slprintf(zLocation, sizeof(zLocation), "manual_location_%d",
|
|
|
|
|
(int)(rng_int() % 4));
|
|
|
|
|
slprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
msg = msg_message("find_manual", "unit location book", u, zLocation, zBook);
|
|
|
|
|
if (msg) {
|
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2016-03-17 21:21:23 +01:00
|
|
|
|
if (!improve_all(u->faction, skill, 3)) {
|
|
|
|
|
learn_skill(u, skill, 9 * STUDYDAYS);
|
2014-12-08 21:19:18 +01:00
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void get_villagers(region * r, unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
unit *newunit;
|
|
|
|
|
message *msg = msg_message("encounter_villagers", "unit", u);
|
|
|
|
|
const char *name = LOC(u->faction->locale, "villagers");
|
|
|
|
|
|
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
|
|
|
|
|
|
|
|
|
newunit =
|
|
|
|
|
create_unit(r, u->faction, rng_int() % 20 + 3, u->faction->race, 0, name,
|
|
|
|
|
u);
|
|
|
|
|
leave(newunit, true);
|
|
|
|
|
fset(newunit, UFL_ISNEW | UFL_MOVED);
|
|
|
|
|
equip_unit(newunit, get_equipment("random_villagers"));
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void get_allies(region * r, unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
unit *newunit = NULL;
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *equip;
|
|
|
|
|
int number;
|
|
|
|
|
message *msg;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
assert(u->number);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
switch (rterrain(r)) {
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case T_PLAIN:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
if (!r_isforest(r)) {
|
|
|
|
|
if (get_money(u) / u->number < 100 + rng_int() % 200)
|
|
|
|
|
return;
|
|
|
|
|
name = "random_plain_men";
|
|
|
|
|
equip = "random_plain";
|
|
|
|
|
number = rng_int() % 8 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
else {
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_LONGBOW, r) < 3
|
|
|
|
|
&& effskill(u, SK_HERBALISM, r) < 2
|
|
|
|
|
&& effskill(u, SK_MAGIC, r) < 2) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_forest_men";
|
|
|
|
|
equip = "random_forest";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
case T_SWAMP:
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_MELEE, r) <= 1) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_swamp_men";
|
|
|
|
|
equip = "random_swamp";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
case T_DESERT:
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_RIDING, r) <= 2) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_desert_men";
|
|
|
|
|
equip = "random_desert";
|
|
|
|
|
number = rng_int() % 12 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
case T_HIGHLAND:
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_MELEE, r) <= 1) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_highland_men";
|
|
|
|
|
equip = "random_highland";
|
|
|
|
|
number = rng_int() % 8 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
case T_MOUNTAIN:
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_MELEE, r) <= 1 || effskill(u, SK_TRADE, r) <= 2) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_mountain_men";
|
|
|
|
|
equip = "random_mountain";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
case T_GLACIER:
|
2015-08-27 16:16:55 +02:00
|
|
|
|
if (effskill(u, SK_MELEE, r) <= 1 || effskill(u, SK_TRADE, r) <= 1) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_glacier_men";
|
|
|
|
|
equip = "random_glacier";
|
|
|
|
|
number = rng_int() % 4 + 2;
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
|
|
|
|
default:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newunit =
|
|
|
|
|
create_unit(r, u->faction, number, u->faction->race, 0,
|
|
|
|
|
LOC(u->faction->locale, name), u);
|
|
|
|
|
equip_unit(newunit, get_equipment(equip));
|
|
|
|
|
|
|
|
|
|
u_setfaction(newunit, u->faction);
|
|
|
|
|
set_racename(&newunit->attribs, get_racename(u->attribs));
|
|
|
|
|
if (u_race(u)->flags & RCF_SHAPESHIFT) {
|
|
|
|
|
newunit->irace = u->irace;
|
|
|
|
|
}
|
|
|
|
|
if (fval(u, UFL_ANON_FACTION))
|
|
|
|
|
fset(newunit, UFL_ANON_FACTION);
|
|
|
|
|
fset(newunit, UFL_ISNEW);
|
|
|
|
|
|
|
|
|
|
msg = msg_message("encounter_allies", "unit name", u, name);
|
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void encounter(region * r, unit * u)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
if (!fval(r, RF_ENCOUNTER))
|
|
|
|
|
return;
|
|
|
|
|
freset(r, RF_ENCOUNTER);
|
|
|
|
|
if (rng_int() % 100 >= ENCCHANCE)
|
|
|
|
|
return;
|
|
|
|
|
switch (rng_int() % 3) {
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 0:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
find_manual(r, u);
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 1:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
get_villagers(r, u);
|
|
|
|
|
break;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
case 2:
|
2014-12-08 21:19:18 +01:00
|
|
|
|
get_allies(r, u);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
void encounters(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (fval(r->terrain, LAND_REGION) && fval(r, RF_ENCOUNTER)) {
|
|
|
|
|
int c = 0;
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
c += u->number;
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
if (c > 0) {
|
|
|
|
|
int i = 0;
|
|
|
|
|
int n = rng_int() % c;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (i + u->number > n)
|
|
|
|
|
break;
|
|
|
|
|
i += u->number;
|
|
|
|
|
}
|
|
|
|
|
assert(u && u->number);
|
|
|
|
|
encounter(r, u);
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
void drown(region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
if (fval(r->terrain, SEA_REGION)) {
|
2015-11-05 11:11:02 +01:00
|
|
|
|
unit **up = &r->units;
|
2014-12-08 21:19:18 +01:00
|
|
|
|
while (*up) {
|
|
|
|
|
unit *u = *up;
|
2015-11-02 13:06:14 +01:00
|
|
|
|
|
2015-11-02 13:12:19 +01:00
|
|
|
|
if (!(u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0 || canswim(u) || canfly(u))) {
|
2014-12-08 21:19:18 +01:00
|
|
|
|
scale_number(u, 0);
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r));
|
|
|
|
|
}
|
2015-11-02 13:12:19 +01:00
|
|
|
|
|
|
|
|
|
up = &u->next;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
remove_empty_units_in_region(r);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void melt_iceberg(region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
attrib *a;
|
|
|
|
|
unit *u;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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));
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* driftrichtung l<>schen */
|
|
|
|
|
a = a_find(r->attribs, &at_iceberg);
|
|
|
|
|
if (a)
|
|
|
|
|
a_remove(&r->attribs, a);
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* Geb<65>ude l<>schen */
|
|
|
|
|
while (r->buildings) {
|
|
|
|
|
remove_building(&r->buildings, r->buildings);
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* in Ozean wandeln */
|
|
|
|
|
terraform_region(r, newterrain(T_OCEAN));
|
|
|
|
|
|
|
|
|
|
/* Einheiten, die nicht schwimmen k<>nnen oder in Schiffen sind,
|
|
|
|
|
* ertrinken */
|
|
|
|
|
drown(r);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void move_iceberg(region * r)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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));
|
2011-03-07 08:02:35 +01:00
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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));
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
x = r->x;
|
|
|
|
|
y = r->y;
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
runhash(r);
|
|
|
|
|
runhash(rc);
|
|
|
|
|
r->x = rc->x;
|
|
|
|
|
r->y = rc->y;
|
|
|
|
|
rc->x = x;
|
|
|
|
|
rc->y = y;
|
|
|
|
|
rhash(rc);
|
|
|
|
|
rhash(r);
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* rc ist der Ozean (Ex-Eisberg), r der Eisberg (Ex-Ozean) */
|
|
|
|
|
|
|
|
|
|
/* Schiffe aus dem Zielozean werden in den Eisberg transferiert
|
|
|
|
|
* und nehmen Schaden. */
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
for (sh = r->ships; sh; sh = sh->next)
|
|
|
|
|
freset(sh, SF_SELECT);
|
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
|
|
|
|
/* Meldung an Kapit<69>n */
|
2015-11-22 10:44:46 +01:00
|
|
|
|
double dmg = config_get_flt("rules.ship.damage.intoiceberg", 0.1);
|
2014-12-08 21:19:18 +01:00
|
|
|
|
damage_ship(sh, dmg);
|
|
|
|
|
fset(sh, SF_SELECT);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* Personen, Schiffe und Geb<65>ude verschieben */
|
|
|
|
|
while (rc->buildings) {
|
|
|
|
|
rc->buildings->region = r;
|
|
|
|
|
translist(&rc->buildings, &r->buildings, rc->buildings);
|
|
|
|
|
}
|
|
|
|
|
while (rc->ships) {
|
2015-11-22 10:44:46 +01:00
|
|
|
|
double dmg = config_get_flt("rules.ship.damage.withiceberg", 0.1);
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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 */
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* Besch<63>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;
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void move_icebergs(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (r->terrain == newterrain(T_ICEBERG) && !fval(r, RF_SELECT)) {
|
|
|
|
|
int select = rng_int() % 10;
|
|
|
|
|
if (select < 4) {
|
|
|
|
|
/* 4% chance */
|
|
|
|
|
fset(r, RF_SELECT);
|
|
|
|
|
melt_iceberg(r);
|
|
|
|
|
}
|
|
|
|
|
else if (select < 64) {
|
|
|
|
|
/* 60% chance */
|
|
|
|
|
fset(r, RF_SELECT);
|
|
|
|
|
move_iceberg(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-07 08:02:35 +01:00
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
void create_icebergs(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
rsetterrain(r, T_ICEBERG);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void godcurse(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
skill *sv = u->skills;
|
|
|
|
|
while (sv != u->skills + u->skill_size) {
|
|
|
|
|
int weeks = 1 + rng_int() % 3;
|
|
|
|
|
reduce_skill(u, sv, weeks);
|
|
|
|
|
++sv;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (fval(r->terrain, SEA_REGION)) {
|
|
|
|
|
ship *sh;
|
|
|
|
|
for (sh = r->ships; sh;) {
|
|
|
|
|
ship *shn = sh->next;
|
2015-11-22 10:44:46 +01:00
|
|
|
|
double dmg = config_get_flt("rules.ship.damage.godcurse", 0.1);
|
2014-12-08 21:19:18 +01:00
|
|
|
|
damage_ship(sh, dmg);
|
|
|
|
|
if (sh->damage >= sh->size * DAMAGE_SCALE) {
|
|
|
|
|
unit *u = ship_owner(sh);
|
|
|
|
|
if (u)
|
|
|
|
|
ADDMSG(&u->faction->msgs,
|
|
|
|
|
msg_message("godcurse_destroy_ship", "ship", sh));
|
|
|
|
|
remove_ship(&sh->region->ships, sh);
|
|
|
|
|
}
|
|
|
|
|
sh = shn;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** handles the "orcish" curse that makes units grow like old orks
|
2016-08-29 20:44:43 +02:00
|
|
|
|
* TODO: This would probably be better handled in an age-function for the curse,
|
2010-08-08 10:06:34 +02:00
|
|
|
|
* but it's now being called by randomevents()
|
|
|
|
|
*/
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void orc_growth(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2016-08-29 20:44:43 +02:00
|
|
|
|
if (u->attribs && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)
|
2014-12-08 21:19:18 +01:00
|
|
|
|
&& !fval(u, UFL_HERO)) {
|
2016-08-29 20:44:43 +02:00
|
|
|
|
const curse_type *ct_orcish = ct_find("orcish");
|
|
|
|
|
|
|
|
|
|
if (ct_orcish) {
|
|
|
|
|
curse *c = get_curse(u->attribs, ct_orcish);
|
|
|
|
|
if (c) {
|
|
|
|
|
int n;
|
|
|
|
|
int increase = 0;
|
|
|
|
|
int num = get_cursedmen(u, c);
|
|
|
|
|
double prob = curse_geteffect(c);
|
|
|
|
|
const item_type * it_chastity = it_find("ao_chastity");
|
|
|
|
|
|
|
|
|
|
if (it_chastity) {
|
|
|
|
|
num -= i_get(u->items, it_chastity);
|
|
|
|
|
}
|
|
|
|
|
for (n = num; n > 0; n--) {
|
|
|
|
|
if (chance(prob)) {
|
|
|
|
|
++increase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (increase) {
|
|
|
|
|
unit *u2 = create_unit(r, u->faction, increase, u_race(u), 0, NULL, u);
|
|
|
|
|
transfermen(u2, u, u2->number);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2016-08-29 20:44:43 +02:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
|
|
|
|
|
"unit amount race", u, increase, u_race(u)));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Talente von D<>monen verschieben sich.
|
|
|
|
|
*/
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void demon_skillchanges(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
2016-10-03 20:36:46 +02:00
|
|
|
|
static const race *rc_demon;
|
|
|
|
|
static int rc_cache;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2016-10-03 20:36:46 +02:00
|
|
|
|
if (rc_changed(&rc_cache)) {
|
|
|
|
|
rc_demon = get_race(RC_DAEMON);
|
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2016-10-03 20:36:46 +02:00
|
|
|
|
if (u_race(u) == rc_demon) {
|
2016-03-13 13:31:54 +01:00
|
|
|
|
demon_skillchange(u);
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Eisberge entstehen und bewegen sich.
|
|
|
|
|
* Einheiten die im Wasser landen, ertrinken.
|
|
|
|
|
*/
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void icebergs(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
create_icebergs();
|
|
|
|
|
move_icebergs();
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
drown(r);
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-22 16:14:27 +01:00
|
|
|
|
#define HERBS_ROT /* herbs owned by units have a chance to rot. */
|
|
|
|
|
#define HERBROTCHANCE 5 /* Verrottchance f<>r Kr<4B>uter (ifdef HERBS_ROT) */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#ifdef HERBS_ROT
|
2011-03-07 08:02:35 +01:00
|
|
|
|
static void rotting_herbs(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-06-23 16:28:10 +02:00
|
|
|
|
region *r;
|
2015-11-22 16:14:27 +01:00
|
|
|
|
int rule_rot = config_get_int("rules.economy.herbrot", HERBROTCHANCE);
|
2014-06-23 16:28:10 +02:00
|
|
|
|
if (rule_rot == 0) return;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
|
2014-06-23 16:28:10 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
const struct item_type *it_bag = it_find("magicherbbag");
|
|
|
|
|
item **itmp = &u->items;
|
|
|
|
|
int rot_chance = rule_rot;
|
|
|
|
|
|
|
|
|
|
if (it_bag && *i_find(itmp, it_bag)) {
|
|
|
|
|
rot_chance = (rot_chance * 2) / 5;
|
|
|
|
|
}
|
|
|
|
|
while (*itmp) {
|
|
|
|
|
item *itm = *itmp;
|
|
|
|
|
int n = itm->number;
|
|
|
|
|
double k = n * rot_chance / 100.0;
|
|
|
|
|
if (fval(itm->type, ITF_HERB)) {
|
|
|
|
|
double nv = normalvariate(k, k / 4);
|
|
|
|
|
int inv = (int)nv;
|
|
|
|
|
int delta = _min(n, inv);
|
|
|
|
|
if (!i_change(itmp, itm->type, -delta)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
itmp = &itm->next;
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
|
void randomevents(void)
|
2010-08-08 10:06:34 +02:00
|
|
|
|
{
|
2014-12-08 21:19:18 +01:00
|
|
|
|
region *r;
|
|
|
|
|
faction *monsters = get_monsters();
|
|
|
|
|
|
|
|
|
|
icebergs();
|
|
|
|
|
godcurse();
|
|
|
|
|
orc_growth();
|
|
|
|
|
demon_skillchanges();
|
|
|
|
|
|
|
|
|
|
/* Orkifizierte Regionen mutieren und mutieren zur<75>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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-22 21:27:24 +02:00
|
|
|
|
|
|
|
|
|
volcano_update();
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* 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;
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
2014-12-08 21:19:18 +01:00
|
|
|
|
|
2014-12-13 11:30:34 +01:00
|
|
|
|
chaos_update();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#ifdef HERBS_ROT
|
2014-12-08 21:19:18 +01:00
|
|
|
|
rotting_herbs();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
2014-12-08 21:19:18 +01:00
|
|
|
|
dissolve_units();
|
2010-08-08 10:06:34 +02:00
|
|
|
|
}
|
2014-12-16 14:18:29 +01:00
|
|
|
|
|
|
|
|
|
void plagues(region * r)
|
|
|
|
|
{
|
|
|
|
|
int peasants;
|
|
|
|
|
int i;
|
|
|
|
|
int dead = 0;
|
|
|
|
|
|
|
|
|
|
peasants = rpeasants(r);
|
2015-05-15 19:08:44 +02:00
|
|
|
|
dead = (int)(0.5 + PLAGUE_VICTIMS * peasants);
|
2014-12-16 14:18:29 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|