2015-01-30 20:37:14 +01:00
|
|
|
/*
|
2010-08-08 10:06:34 +02:00
|
|
|
+-------------------+ 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>
|
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
This program may not be used, modified or distributed
|
2010-08-08 10:06:34 +02:00
|
|
|
without prior permission by the authors of Eressea.
|
|
|
|
|
|
|
|
*/
|
|
|
|
#include <platform.h>
|
|
|
|
#include <kernel/config.h>
|
|
|
|
#include "market.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include <util/attrib.h>
|
2017-01-26 17:41:21 +01:00
|
|
|
#include <selist.h>
|
2010-08-08 10:06:34 +02:00
|
|
|
#include <util/rng.h>
|
|
|
|
|
|
|
|
#include <kernel/building.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/race.h>
|
|
|
|
#include <kernel/region.h>
|
|
|
|
#include <kernel/unit.h>
|
|
|
|
|
2011-03-07 08:02:35 +01:00
|
|
|
static unsigned int get_markets(region * r, unit ** results, size_t size)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2015-01-30 20:37:14 +01:00
|
|
|
unsigned int n = 0;
|
|
|
|
building *b;
|
|
|
|
const building_type *btype = bt_find("market");
|
|
|
|
if (!btype)
|
2014-06-18 08:10:55 +02:00
|
|
|
return 0;
|
2015-01-30 20:37:14 +01:00
|
|
|
for (b = r->buildings; n < size && b; b = b->next) {
|
2015-11-16 02:13:48 +01:00
|
|
|
if (b->type == btype && building_is_active(b)) {
|
2015-01-30 20:37:14 +01:00
|
|
|
unit *u = building_owner(b);
|
2015-11-16 02:13:48 +01:00
|
|
|
/* I decided to omit check for inside_building(u) */
|
2015-01-30 20:37:14 +01:00
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; u && i != n; ++i) {
|
|
|
|
/* only one market per faction */
|
|
|
|
if (results[i]->faction == u->faction)
|
|
|
|
u = NULL;
|
|
|
|
}
|
|
|
|
if (u) {
|
|
|
|
results[n++] = u;
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
2015-01-30 20:37:14 +01:00
|
|
|
return n;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
2018-02-09 21:20:43 +01:00
|
|
|
static void free_market(variant *var)
|
2010-08-08 10:06:34 +02:00
|
|
|
{
|
2018-02-09 21:20:43 +01:00
|
|
|
item *items = (item *)var->v;
|
2015-01-30 20:37:14 +01:00
|
|
|
i_freeall(&items);
|
2018-02-09 21:20:43 +01:00
|
|
|
var->v = NULL;
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
attrib_type at_market = {
|
2015-01-30 20:37:14 +01:00
|
|
|
"script",
|
|
|
|
NULL, free_market, NULL,
|
2016-02-09 06:43:19 +01:00
|
|
|
NULL, NULL, NULL, ATF_UNIQUE
|
2010-08-08 10:06:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_MARKETS 128
|
2011-03-07 08:02:35 +01:00
|
|
|
#define MIN_PEASANTS 50 /* if there are at least this many peasants, you will get 1 good */
|
2010-08-08 10:06:34 +02:00
|
|
|
|
2016-11-16 22:30:59 +01:00
|
|
|
bool markets_module(void)
|
|
|
|
{
|
2017-11-06 21:04:30 +01:00
|
|
|
return (bool)config_get_int("modules.market", 0);
|
2016-11-16 22:30:59 +01:00
|
|
|
}
|
|
|
|
|
2010-08-08 10:06:34 +02:00
|
|
|
void do_markets(void)
|
|
|
|
{
|
2017-01-26 17:41:21 +01:00
|
|
|
selist *traders = 0;
|
2015-01-30 20:37:14 +01:00
|
|
|
unit *markets[MAX_MARKETS];
|
|
|
|
region *r;
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
if (r->land) {
|
|
|
|
faction *f = region_get_owner(r);
|
|
|
|
const struct race *rc = f ? f->race : NULL;
|
|
|
|
int p = rpeasants(r);
|
|
|
|
int numlux = rc_luxury_trade(rc), numherbs = rc_herb_trade(rc);
|
2015-11-09 18:06:11 +01:00
|
|
|
if (numlux>0) numlux = (p + numlux - MIN_PEASANTS) / numlux;
|
|
|
|
if (numherbs>0) numherbs = (p + numherbs - MIN_PEASANTS) / numherbs;
|
2015-01-30 20:37:14 +01:00
|
|
|
if (numlux > 0 || numherbs > 0) {
|
|
|
|
int d, nmarkets = 0;
|
|
|
|
const item_type *lux = r_luxury(r);
|
|
|
|
const item_type *herb = r->land->herbtype;
|
|
|
|
|
|
|
|
nmarkets += get_markets(r, markets + nmarkets, MAX_MARKETS - nmarkets);
|
|
|
|
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
|
|
|
region *r2 = rconnect(r, d);
|
|
|
|
if (r2 && r2->buildings) {
|
|
|
|
nmarkets +=
|
|
|
|
get_markets(r2, markets + nmarkets, MAX_MARKETS - nmarkets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nmarkets) {
|
|
|
|
while (lux && numlux--) {
|
|
|
|
int n = rng_int() % nmarkets;
|
|
|
|
unit *u = markets[n];
|
|
|
|
item *items;
|
|
|
|
attrib *a = a_find(u->attribs, &at_market);
|
|
|
|
if (a == NULL) {
|
|
|
|
a = a_add(&u->attribs, a_new(&at_market));
|
2017-01-26 17:41:21 +01:00
|
|
|
selist_push(&traders, u);
|
2015-01-30 20:37:14 +01:00
|
|
|
}
|
|
|
|
items = (item *)a->data.v;
|
|
|
|
i_change(&items, lux, 1);
|
|
|
|
a->data.v = items;
|
|
|
|
/* give 1 luxury */
|
|
|
|
}
|
|
|
|
while (herb && numherbs--) {
|
|
|
|
int n = rng_int() % nmarkets;
|
|
|
|
unit *u = markets[n];
|
|
|
|
item *items;
|
|
|
|
attrib *a = a_find(u->attribs, &at_market);
|
|
|
|
if (a == NULL) {
|
|
|
|
a = a_add(&u->attribs, a_new(&at_market));
|
2017-01-26 17:41:21 +01:00
|
|
|
selist_push(&traders, u);
|
2015-01-30 20:37:14 +01:00
|
|
|
}
|
|
|
|
items = (item *)a->data.v;
|
|
|
|
i_change(&items, herb, 1);
|
|
|
|
a->data.v = items;
|
|
|
|
/* give 1 herb */
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 20:37:14 +01:00
|
|
|
if (traders) {
|
2017-01-26 17:41:21 +01:00
|
|
|
selist *qliter = traders;
|
2015-01-30 20:37:14 +01:00
|
|
|
int qli = 0;
|
2017-01-26 17:41:21 +01:00
|
|
|
for (qli = 0; qliter; selist_advance(&qliter, &qli, 1)) {
|
|
|
|
unit *u = (unit *)selist_get(qliter, qli);
|
2015-01-30 20:37:14 +01:00
|
|
|
attrib *a = a_find(u->attribs, &at_market);
|
|
|
|
item *items = (item *)a->data.v;
|
|
|
|
|
|
|
|
a->data.v = NULL;
|
|
|
|
while (items) {
|
|
|
|
item *itm = items;
|
|
|
|
items = itm->next;
|
|
|
|
|
|
|
|
if (itm->number) {
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("buyamount",
|
|
|
|
"unit amount resource", u, itm->number, itm->type->rtype));
|
|
|
|
itm->next = NULL;
|
|
|
|
i_add(&u->items, itm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
i_free(itm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
a_remove(&u->attribs, a);
|
|
|
|
}
|
2017-01-26 17:41:21 +01:00
|
|
|
selist_free(traders);
|
2011-02-24 08:23:32 +01:00
|
|
|
}
|
2010-08-08 10:06:34 +02:00
|
|
|
}
|