server/core/src/kernel/resources.c

225 lines
5.7 KiB
C
Raw Normal View History

2010-08-08 10:06:34 +02:00
/* vi: set ts=2:
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#include <platform.h>
#include <kernel/config.h>
#include "resources.h"
/* kernel includes */
#include "build.h"
#include "item.h"
#include "region.h"
#include "terrain.h"
#include <util/rand.h>
#include <util/rng.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
2011-03-07 08:02:35 +01:00
static double ResourceFactor(void)
2010-08-08 10:06:34 +02:00
{
static double value = -1.0;
2011-03-07 08:02:35 +01:00
if (value < 0) {
const char *str = get_param(global.parameters, "resource.factor");
value = str ? atof(str) : 1.0;
2010-08-08 10:06:34 +02:00
}
return value;
}
2011-03-07 08:02:35 +01:00
void update_resources(region * r)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
struct rawmaterial *res = r->resources;
2010-08-08 10:06:34 +02:00
while (res) {
2011-03-07 08:02:35 +01:00
if (res->type->update)
res->type->update(res, r);
2010-08-08 10:06:34 +02:00
res = res->next;
}
}
extern int dice_rand(const char *s);
2011-03-07 08:02:35 +01:00
static void update_resource(struct rawmaterial *res, double modifier)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
double amount = 1 + (res->level - res->startlevel) * res->divisor / 100.0;
2010-08-08 10:06:34 +02:00
amount = ResourceFactor() * res->base * amount * modifier;
2011-03-07 08:02:35 +01:00
if (amount < 1.0)
res->amount = 1;
else
res->amount = (int)amount;
assert(res->amount > 0);
2010-08-08 10:06:34 +02:00
}
void
2011-03-07 08:02:35 +01:00
add_resource(region * r, int level, int base, int divisor,
const resource_type * rtype)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
struct rawmaterial *rm = calloc(sizeof(struct rawmaterial), 1);
2010-08-08 10:06:34 +02:00
rm->next = r->resources;
r->resources = rm;
2011-03-07 08:02:35 +01:00
rm->level = level;
2010-08-08 10:06:34 +02:00
rm->startlevel = level;
2011-03-07 08:02:35 +01:00
rm->base = base;
rm->divisor = divisor;
rm->flags = 0;
rm->type = rmt_get(rtype);
2010-08-08 10:06:34 +02:00
update_resource(rm, 1.0);
rm->type->terraform(rm, r);
}
2011-03-07 08:02:35 +01:00
void terraform_resources(region * r)
2010-08-08 10:06:34 +02:00
{
int i;
2011-03-07 08:02:35 +01:00
const terrain_type *terrain = r->terrain;
static int terraform_all = -1;
if (terraform_all<0) {
terraform_all = get_param_int(global.parameters, "rules.terraform.all", 0);
}
2011-03-07 08:02:35 +01:00
if (terrain->production == NULL)
return;
for (i = 0; terrain->production[i].type; ++i) {
2010-08-08 10:06:34 +02:00
rawmaterial *rm;
2011-03-07 08:02:35 +01:00
const terrain_production *production = terrain->production + i;
const resource_type *rtype = production->type;
for (rm = r->resources; rm; rm = rm->next) {
if (rm->type->rtype == rtype)
break;
2010-08-08 10:06:34 +02:00
}
if (rm) {
2011-03-07 08:02:35 +01:00
continue;
}
if (terraform_all || chance(production->chance)) {
2011-03-07 08:02:35 +01:00
add_resource(r, dice_rand(production->startlevel),
dice_rand(production->base), dice_rand(production->divisor),
production->type);
2010-08-08 10:06:34 +02:00
}
}
}
2011-03-07 08:02:35 +01:00
static void terraform_default(struct rawmaterial *res, const region * r)
2010-08-08 10:06:34 +02:00
{
#define SHIFT 70
2011-03-07 08:02:35 +01:00
double modifier =
1.0 + ((rng_int() % (SHIFT * 2 + 1)) - SHIFT) * ((rng_int() % (SHIFT * 2 +
1)) - SHIFT) / 10000.0;
res->amount = (int)(res->amount * modifier); /* random adjustment, +/- 91% */
if (res->amount < 1)
res->amount = 1;
unused(r);
2010-08-08 10:06:34 +02:00
}
#ifdef RANDOM_CHANGE
static void resource_random_change(int *pvalue, bool used)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
int split = 5;
int rnd = rng_int() % 100;
if (pvalue == 0 || rnd % 10 >= 10)
return;
if (used)
split = 4;
/* if a resource was mined this round, there is a 6% probability
* of a decline and a 4% probability of a raise. */
/* if it wasn't mined this round, there is an equal probability
* of 5% for a decline or a raise. */
if (rnd < split) {
(*pvalue)++;
} else {
(*pvalue)--;
}
if ((*pvalue) < 0)
(*pvalue) = 0;
2010-08-08 10:06:34 +02:00
}
#endif
2011-03-07 08:02:35 +01:00
static int visible_default(const rawmaterial * res, int skilllevel)
2010-08-08 10:06:34 +02:00
/* resources are visible, if skill equals minimum skill to mine them
* plus current level of difficulty */
{
2011-03-07 08:02:35 +01:00
const struct item_type *itype = res->type->rtype->itype;
if (res->level <= 1
&& res->level + itype->construction->minskill <= skilllevel + 1) {
assert(res->amount > 0);
return res->amount;
} else if (res->level + itype->construction->minskill <= skilllevel + 2) {
assert(res->amount > 0);
return res->amount;
}
return -1;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void use_default(rawmaterial * res, const region * r, int amount)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
assert(res->amount > 0 && amount >= 0 && amount <= res->amount);
res->amount -= amount;
while (res->amount == 0) {
double modifier =
1.0 + ((rng_int() % (SHIFT * 2 + 1)) - SHIFT) * ((rng_int() % (SHIFT * 2 +
1)) - SHIFT) / 10000.0;
2010-08-08 10:06:34 +02:00
int i;
2011-03-07 08:02:35 +01:00
for (i = 0; r->terrain->production[i].type; ++i) {
if (res->type->rtype == r->terrain->production[i].type)
break;
2010-08-08 10:06:34 +02:00
}
++res->level;
update_resource(res, modifier);
}
}
2011-03-07 08:02:35 +01:00
struct rawmaterial *rm_get(region * r, const struct resource_type *rtype)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
struct rawmaterial *rm = r->resources;
while (rm && rm->type->rtype != rtype)
rm = rm->next;
return rm;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
struct rawmaterial_type *rawmaterialtypes = 0;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
struct rawmaterial_type *rmt_find(const char *str)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
rawmaterial_type *rmt = rawmaterialtypes;
while (rmt && strcmp(rmt->name, str) != 0)
rmt = rmt->next;
return rmt;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
struct rawmaterial_type *rmt_get(const struct resource_type *rtype)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
rawmaterial_type *rmt = rawmaterialtypes;
while (rmt && rmt->rtype != rtype)
rmt = rmt->next;
2010-08-08 10:06:34 +02:00
return rmt;
}
2011-03-07 08:02:35 +01:00
struct rawmaterial_type *rmt_create(const struct resource_type *rtype,
const char *name)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
rawmaterial_type *rmtype = malloc(sizeof(rawmaterial_type));
2010-08-08 10:06:34 +02:00
rmtype->name = strdup(name);
rmtype->rtype = rtype;
rmtype->terraform = terraform_default;
rmtype->update = NULL;
rmtype->use = use_default;
rmtype->visible = visible_default;
rmtype->next = rawmaterialtypes;
rawmaterialtypes = rmtype;
return rmtype;
}