diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index 102c33254..ad2242080 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -161,6 +161,19 @@ reset_translations(void) #include "objtypes.h" +static void +print_items(FILE * F, item * items, const struct locale * lang) +{ + item * itm; + + for (itm=items; itm; itm=itm->next) { + int in = itm->number; + const char * ic = resourcename(itm->type->rtype, in); + if (itm==items) fputs("GEGENSTAENDE\n", F); + fprintf(F, "%d;%s\n", in, add_translation(ic, LOC(lang, ic))); + } +} + static void print_curses(FILE * F, const faction * viewer, const void * obj, typ_t typ) { @@ -1045,7 +1058,6 @@ report_computer(const char * filename, report_context * ctx) { int i; faction * f = ctx->f; - item * itm; const char * prefix; region * r; building *b; @@ -1127,12 +1139,7 @@ report_computer(const char * filename, report_context * ctx) fprintf(F, "\"%s\";Parteiname\n", f->name); fprintf(F, "\"%s\";email\n", f->email); fprintf(F, "\"%s\";banner\n", f->banner); - for (itm=f->items; itm; itm=itm->next) { - int in = itm->number; - const char * ic = resourcename(itm->type->rtype, in); - if (itm==f->items) fputs("GEGENSTAENDE\n", F); - fprintf(F, "%d;%s\n", in, add_translation(ic, LOC(f->locale, ic))); - } + print_items(F, f->items, f->locale); fputs("OPTIONEN\n", F); for (i=0;i!=MAXOPTIONS;++i) { fprintf(F, "%d;%s\n", (f->options&want(i))?1:0, options[i]); @@ -1335,6 +1342,9 @@ report_computer(const char * filename, report_context * ctx) } if (pos!=cbuf) fputs(cbuf, F); } + if (r->land) { + print_items(F, r->land->items, f->locale); + } print_curses(F, f, r, TYP_REGION); cr_borders(ctx->seen, r, f, sd->mode, F); if (sd->mode==see_unit && rplane(r)==get_astralplane() && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index 9fe636fca..2ee7169d6 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -1723,7 +1723,7 @@ make_cmd(unit * u, struct order * ord) static void free_luxuries(struct attrib * a) { - i_freeall((item*)a->data.v); + i_freeall((item**)&a->data.v); } const attrib_type at_luxuries = { diff --git a/src/common/kernel/equipment.c b/src/common/kernel/equipment.c index 953770e66..8796a6898 100644 --- a/src/common/kernel/equipment.c +++ b/src/common/kernel/equipment.c @@ -155,3 +155,34 @@ equip_unit(struct unit * u, const struct equipment * eq) } } } + +void +equip_items(struct item ** items, const struct equipment * eq) +{ + if (eq) { + itemdata * idata; + + for (idata=eq->items;idata!=NULL;idata=idata->next) { + int i = dice_rand(idata->value); + if (i>0) { + i_add(items, i_new(idata->itype, i)); + } + } + if (eq->subsets) { + int i; + for (i=0;eq->subsets[i].sets;++i) { + if (chance(eq->subsets[i].chance)) { + float rnd = 1000.0f / (1+rand() % 1000); + int k; + for (k=0;eq->subsets[i].sets[k].set;++k) { + if (rnd<=eq->subsets[i].sets[k].chance) { + equip_items(items, eq->subsets[i].sets[k].set); + break; + } + rnd -= eq->subsets[i].sets[k].chance; + } + } + } + } + } +} diff --git a/src/common/kernel/equipment.h b/src/common/kernel/equipment.h index a88db9d6b..1c62651ff 100644 --- a/src/common/kernel/equipment.h +++ b/src/common/kernel/equipment.h @@ -59,6 +59,7 @@ extern "C" { extern void equipment_addspell(struct equipment * eq, struct spell * sp); extern void equip_unit(struct unit * u, const struct equipment * eq); + extern void equip_items(struct item ** items, const struct equipment * eq); #ifdef __cplusplus } diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 01e44ba14..bca5d46b1 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -712,7 +712,7 @@ stripfaction (faction * f) while (f->attribs) a_remove (&f->attribs, f->attribs); - i_freeall(f->items); + i_freeall(&f->items); freelist(f->ursprung); funhash(f); diff --git a/src/common/kernel/item.c b/src/common/kernel/item.c index aed68d039..0ac74a673 100644 --- a/src/common/kernel/item.c +++ b/src/common/kernel/item.c @@ -526,13 +526,13 @@ i_free(item * i) { } void -i_freeall(item *i) { +i_freeall(item **i) { item *in; - while(i) { - in = i->next; - free(i); - i = in; + while(*i) { + in = (*i)->next; + free(*i); + *i = in; } } diff --git a/src/common/kernel/item.h b/src/common/kernel/item.h index 9dca0c002..ea5ebbbf5 100644 --- a/src/common/kernel/item.h +++ b/src/common/kernel/item.h @@ -210,7 +210,7 @@ extern item * i_add(item ** pi, item * it); extern void i_merge(item ** pi, item ** si); extern item * i_remove(item ** pi, item * it); extern void i_free(item * i); -extern void i_freeall(item * i); +extern void i_freeall(item ** i); extern item * i_new(const item_type * it, int number); /* convenience: */ diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index d274075be..242bb9957 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -27,6 +27,7 @@ #include "border.h" #include "building.h" #include "curse.h" +#include "equipment.h" #include "faction.h" #include "item.h" #include "message.h" @@ -895,6 +896,7 @@ terraform_region(region * r, const terrain_type * terrain) if (!fval(terrain, LAND_REGION)) { if (r->land!=NULL) { + i_freeall(&r->land->items); freeland(r->land); r->land = NULL; } @@ -910,7 +912,9 @@ terraform_region(region * r, const terrain_type * terrain) return; } - if (!r->land) { + if (r->land) { + i_freeall(&r->land->items); + } else { static struct surround { struct surround * next; const luxury_type * type; @@ -970,7 +974,13 @@ terraform_region(region * r, const terrain_type * terrain) if (fval(terrain, LAND_REGION)) { const item_type * itype = NULL; - if (r->terrain->herbs) { + char equip_hash[64]; + + /* TODO: put the equipment in struct terrain, faster */ + sprintf(equip_hash, "terrain_%s", terrain->_name); + equip_items(&r->land->items, get_equipment(equip_hash)); + + if (r->terrain->herbs) { int len=0; while (r->terrain->herbs[len]) ++len; if (len) itype = r->terrain->herbs[rand()%len]; diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h index 5a3b9b71f..f54667e10 100644 --- a/src/common/kernel/region.h +++ b/src/common/kernel/region.h @@ -76,6 +76,7 @@ typedef struct land_region { int peasants; int newpeasants; int money; + struct item * items; /* items that can be claimed */ } land_region; typedef struct donation { diff --git a/src/common/modules/museum.c b/src/common/modules/museum.c index fc6217d49..530695f53 100644 --- a/src/common/modules/museum.c +++ b/src/common/modules/museum.c @@ -102,7 +102,8 @@ a_initmuseumgiveback(attrib *a) static void a_finalizemuseumgiveback(attrib *a) { - i_freeall(((museumgiveback *)(a->data.v))->items); + museumgiveback *gb = (museumgiveback *)a->data.v; + i_freeall(&gb->items); free(a->data.v); } diff --git a/src/common/util/dice.c b/src/common/util/dice.c index 3c453ae40..2b816cbcc 100644 --- a/src/common/util/dice.c +++ b/src/common/util/dice.c @@ -49,13 +49,14 @@ int dice_rand(const char *s) { const char *c = s; - int m = 0, d = 0, k = 0, multi = 1; + int m = 0, d = 0, k = 0, term = 1, multi = 1; int state = 1; for (;;) { if (isdigit((int)*c)) { k = k*10+(*c-'0'); - } else if (*c=='+' || *c=='-' || *c==0) { + } + else if (*c=='+' || *c=='-' || *c==0 || *c=='*') { if (state==1) /* konstante k addieren */ m+=k*multi; else if (state==2) { /* dDk */ @@ -64,6 +65,10 @@ dice_rand(const char *s) for (i=0;i!=d;++i) m += (1 + rand() % k)*multi; } else assert(!"dice_rand: illegal token"); + if (*c=='*') { + term *= m; + m = 0; + } k = d = 0; state = 1; multi = (*c=='-')?-1:1; @@ -77,5 +82,5 @@ dice_rand(const char *s) if (*c==0) break; c++; } - return m; + return m*term; } diff --git a/src/eressea/lua/eressea.cpp b/src/eressea/lua/eressea.cpp index 3a045525b..43f68092c 100644 --- a/src/eressea/lua/eressea.cpp +++ b/src/eressea/lua/eressea.cpp @@ -34,6 +34,7 @@ // util includes #include #include +#include #include #include @@ -275,6 +276,7 @@ bind_eressea(lua_State * L) def("write_game", &write_game), def("write_passwords", &writepasswd), def("init_reports", &init_reports), + def("dice_roll", &dice_rand), def("write_reports", &lua_writereports), def("write_report", &lua_writereport), def("init_summary", &init_summary), diff --git a/src/eressea/lua/region.cpp b/src/eressea/lua/region.cpp index ad5c07489..6937e7cb3 100644 --- a/src/eressea/lua/region.cpp +++ b/src/eressea/lua/region.cpp @@ -124,10 +124,14 @@ static int region_getresource(const region& r, const char * type) { const resource_type * rtype = rt_find(type); - if (rtype==rt_find("money")) return rmoney(&r); - if (rtype==rt_find("peasant")) return rpeasants(&r); - if (strcmp(type, "grave")==0) return deathcount(&r); - if (strcmp(type, "chaos")==0) return chaoscount(&r); + if (rtype!=NULL) { + if (rtype==rt_find("money")) return rmoney(&r); + if (rtype==rt_find("peasant")) return rpeasants(&r); + } else { + if (strcmp(type, "tree")==0) return rtrees(&r, 2); + if (strcmp(type, "grave")==0) return deathcount(&r); + if (strcmp(type, "chaos")==0) return chaoscount(&r); + } return 0; } @@ -135,15 +139,19 @@ static void region_setresource(region& r, const char * type, int value) { const resource_type * rtype = rt_find(type); - if (rtype==rt_find("money")) rsetmoney(&r, value); - if (rtype==rt_find("peasant")) return rsetpeasants(&r, value); - if (strcmp(type, "grave")==0) { - int fallen = value-deathcount(&r); - deathcounts(&r, fallen); - } - if (strcmp(type, "chaos")==0) { - int fallen = value-chaoscount(&r); - chaoscounts(&r, fallen); + if (rtype!=NULL) { + if (rtype==rt_find("money")) rsetmoney(&r, value); + if (rtype==rt_find("peasant")) return rsetpeasants(&r, value); + } else { + if (strcmp(type, "tree")==0) { + rsettrees(&r, 2, value); + } else if (strcmp(type, "grave")==0) { + int fallen = value-deathcount(&r); + deathcounts(&r, fallen); + } else if (strcmp(type, "chaos")==0) { + int fallen = value-chaoscount(&r); + chaoscounts(&r, fallen); + } } } @@ -253,6 +261,26 @@ region_move(region& r, short x, short y) rhash(&r); } +static eressea::list +region_items(const region& r) { + if (r.land) { + return eressea::list(r.land->items); + } else { + return eressea::list(NULL); + } +} + +static int +region_additem(region& r, const char * iname, int number) +{ + const item_type * itype = it_find(iname); + if (itype!=NULL && r.land) { + item * i = i_change(&r.land->items, itype, number); + return i?i->number:0; + } // if (itype!=NULL) + return -1; +} + void bind_region(lua_State * L) { @@ -286,6 +314,8 @@ bind_region(lua_State * L) .def_readonly("x", ®ion::x) .def_readonly("y", ®ion::y) .def_readwrite("age", ®ion::age) + .def("add_item", ®ion_additem) + .property("items", ®ion_items, return_stl_iterator) .property("plane_id", ®ion_plane) .property("units", ®ion_units, return_stl_iterator) .property("buildings", ®ion_buildings, return_stl_iterator) diff --git a/src/res/kingdoms/terrains.xml b/src/res/kingdoms/terrains.xml index 0a29867d4..378e397bd 100644 --- a/src/res/kingdoms/terrains.xml +++ b/src/res/kingdoms/terrains.xml @@ -6,4 +6,7 @@ + + + diff --git a/src/scripts/kingdoms-run.lua b/src/scripts/kingdoms-run.lua index b54c096e3..5ec5981a6 100644 --- a/src/scripts/kingdoms-run.lua +++ b/src/scripts/kingdoms-run.lua @@ -26,6 +26,24 @@ function write_emails() end end +function update_resources() +-- remaining contents of region pool rots +-- wood falls from trees + local r + for r in regions() do + local item + for item in r.items do + local num = math.ceil(r:get_item(item)/2) + r:add_item(item, -num) + end + + local wood = math.floor(r:get_resource("tree")/20) + if wood>0 then + r.add_item("log", wood) + end + end +end + function update_owners() -- update the region's owners. currently uses the owner of -- the largest castle. @@ -60,6 +78,7 @@ function process(orders) process_orders() update_owners() + update_resources() -- use newfactions file to place out new players autoseed(basepath .. "/newfactions", true)