static void prepare_starting_region(region * r) { int n, t; double p; assert(r->land); /* population between 30% and 60% of max */ p = rng_double(); n = (int)(r->terrain->size * (0.3 + p * 0.3)); rsetpeasants(r, n); /* trees: don't squash the peasants, and at least 5% should be forrest */ t = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE; if (t < r->terrain->size / 20 || t + n > r->terrain->size) { double p2 = 0.05 + rng_double() * (1.0 - p - 0.05); int maxtrees = (int)(r->terrain->size / 1.25 / TREESIZE); /* 1.25 = each young tree will take 1/2 the space of old trees */ int trees = (int)(p2 * maxtrees); rsettrees(r, 2, trees); rsettrees(r, 1, trees / 2); rsettrees(r, 0, trees / 4); } /* horses: between 1% and 2% */ p = rng_double(); rsethorses(r, (int)(r->terrain->size * (0.01 + p * 0.01))); if (!markets_module()) { fix_demand(r); } }
bool r_isforest(const region * r) { if (fval(r->terrain, FOREST_REGION)) { /* needs to be covered with at leas 48% trees */ int mincover = (int)(r->terrain->size * 0.48); int trees = rtrees(r, 2) + rtrees(r, 1); return (trees * TREESIZE >= mincover); } return false; }
static int do_potion(unit * u, region *r, const potion_type * ptype, int amount) { if (ptype == oldpotiontype[P_LIFE]) { int holz = 0; static int tree_type = -1; static int tree_count = -1; if (tree_type < 0) { tree_type = get_param_int(global.parameters, "rules.magic.wol_type", 1); tree_count = get_param_int(global.parameters, "rules.magic.wol_effect", 10); } /* mallorn is required to make mallorn forests, wood for regular ones */ if (fval(r, RF_MALLORN)) { holz = use_pooled(u, rt_find("mallorn"), GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount); } else { holz = use_pooled(u, rt_find("log"), GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, tree_count * amount); } if (r->land == 0) holz = 0; if (holz < tree_count * amount) { int x = holz / tree_count; if (holz % tree_count) ++x; if (x < amount) amount = x; } rsettrees(r, tree_type, rtrees(r, tree_type) + holz); ADDMSG(&u->faction->msgs, msg_message("growtree_effect", "mage amount", u, holz)); } else if (ptype == oldpotiontype[P_HEILWASSER]) { u->hp = _min(unit_max_hp(u) * u->number, u->hp + 400 * amount); } else if (ptype == oldpotiontype[P_PEOPLE]) { attrib *a = (attrib *) a_find(r->attribs, &at_peasantluck); if (!a) a = a_add(&r->attribs, a_new(&at_peasantluck)); a->data.i += amount; } else if (ptype == oldpotiontype[P_HORSE]) { attrib *a = (attrib *) a_find(r->attribs, &at_horseluck); if (!a) a = a_add(&r->attribs, a_new(&at_horseluck)); a->data.i += amount; } else if (ptype == oldpotiontype[P_WAHRHEIT]) { fset(u, UFL_DISBELIEVES); amount = 1; } else if (ptype == oldpotiontype[P_MACHT]) { /* Verfünffacht die HP von max. 10 Personen in der Einheit */ u->hp += _min(u->number, 10 * amount) * unit_max_hp(u) * 4; } else { change_effect(u, ptype, 10 * amount); } return amount; }
static int tolua_region_get_resource(lua_State * L) { region *r; const char *type; const resource_type *rtype; int result = 0; void * match; critbit_tree * cb = special_resources(); r = (region *)tolua_tousertype(L, 1, 0); LUA_ASSERT(r != NULL, "invalid parameter"); type = tolua_tostring(L, 2, 0); LUA_ASSERT(type != NULL, "invalid parameter"); if (cb_find_prefix(cb, type, strlen(type) + 1, &match, 1, 0)) { cb_get_kv(match, &result, sizeof(result)); switch (result) { case 0: case 1: case 2: result = rtrees(r, result); break; case 3: result = deathcount(r); break; case 4: result = get_chaoscount(r); break; } } else { rtype = rt_find(type); if (rtype) { result = region_getresource(r, rtype); } else { result = -1; } } lua_pushinteger(L, result); return 1; }
/* In a->data.ca[1] steht der Prozentsatz mit dem sich die Einheit * auflöst, in a->data.ca[0] kann angegeben werden, wohin die Personen * verschwinden. Passiert bereits in der ersten Runde! */ static void dissolve_units(void) { region *r; unit *u; int n; int i; 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; if (u->age == 0 && a->data.ca[1] < 100) continue; /* 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++; } } /* 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); } } } remove_empty_units(); }
void terraform_region(region * r, const terrain_type * terrain) { /* Resourcen, die nicht mehr vorkommen können, löschen */ const terrain_type *oldterrain = r->terrain; rawmaterial **lrm = &r->resources; assert(terrain); while (*lrm) { rawmaterial *rm = *lrm; const resource_type *rtype = NULL; if (terrain->production != NULL) { int i; for (i = 0; terrain->production[i].type; ++i) { if (rm->type->rtype == terrain->production[i].type) { rtype = rm->type->rtype; break; } } } if (rtype == NULL) { *lrm = rm->next; free(rm); } else { lrm = &rm->next; } } r->terrain = terrain; terraform_resources(r); if (!fval(terrain, LAND_REGION)) { region_setinfo(r, NULL); if (r->land != NULL) { i_freeall(&r->land->items); freeland(r->land); r->land = NULL; } rsettrees(r, 0, 0); rsettrees(r, 1, 0); rsettrees(r, 2, 0); rsethorses(r, 0); rsetpeasants(r, 0); rsetmoney(r, 0); freset(r, RF_ENCOUNTER); freset(r, RF_MALLORN); /* Beschreibung und Namen löschen */ return; } if (r->land) { int d; for (d = 0; d != MAXDIRECTIONS; ++d) { rsetroad(r, d, 0); } i_freeall(&r->land->items); } else { static struct surround { struct surround *next; const luxury_type *type; int value; } *trash = NULL, *nb = NULL; const luxury_type *ltype = NULL; direction_t d; int mnr = 0; r->land = calloc(1, sizeof(land_region)); r->land->ownership = NULL; region_set_morale(r, MORALE_DEFAULT, -1); region_setname(r, makename()); for (d = 0; d != MAXDIRECTIONS; ++d) { region *nr = rconnect(r, d); if (nr && nr->land) { struct demand *sale = r->land->demands; while (sale && sale->value != 0) sale = sale->next; if (sale) { struct surround *sr = nb; while (sr && sr->type != sale->type) sr = sr->next; if (!sr) { if (trash) { sr = trash; trash = trash->next; } else { sr = calloc(1, sizeof(struct surround)); } sr->next = nb; sr->type = sale->type; sr->value = 1; nb = sr; } else sr->value++; ++mnr; } } } if (!nb) { // TODO: this is really lame int i = get_maxluxuries(); if (i > 0) { i = rng_int() % i; ltype = luxurytypes; while (i--) ltype = ltype->next; } } else { int i = rng_int() % mnr; struct surround *srd = nb; while (i > srd->value) { i -= srd->value; srd = srd->next; } if (srd->type) setluxuries(r, srd->type); while (srd->next != NULL) srd = srd->next; srd->next = trash; trash = nb; nb = NULL; } } if (fval(terrain, LAND_REGION)) { const item_type *itype = NULL; 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[rng_int() % len]; } if (itype != NULL) { rsetherbtype(r, itype); rsetherbs(r, (short)(50 + rng_int() % 31)); } else { rsetherbtype(r, NULL); } if (oldterrain == NULL || !fval(oldterrain, LAND_REGION)) { if (rng_int() % 100 < 3) fset(r, RF_MALLORN); else freset(r, RF_MALLORN); if (rng_int() % 100 < ENCCHANCE) { fset(r, RF_ENCOUNTER); } } } if (oldterrain == NULL || terrain->size != oldterrain->size) { if (terrain == newterrain(T_PLAIN)) { rsethorses(r, rng_int() % (terrain->size / 50)); if (rng_int() % 100 < 40) { rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); } } else if (chance(0.2)) { rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); } else { rsettrees(r, 2, 0); } rsettrees(r, 1, rtrees(r, 2) / 4); rsettrees(r, 0, rtrees(r, 2) / 8); if (!fval(r, RF_CHAOTIC)) { int peasants; peasants = (maxworkingpeasants(r) * (20 + dice_rand("6d10"))) / 100; rsetpeasants(r, _max(100, peasants)); rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL, INT_MAX) + 1) + rng_int() % 5)); } } }