void morale_update(region *r) { int morale = region_get_morale(r); assert(r->land); if (r->land->ownership && r->land->ownership->owner) { int stability = turn - r->land->ownership->morale_turn; int maxmorale = MORALE_DEFAULT; building *b = largestbuilding(r, cmp_taxes, false); if (b) { int bsize = buildingeffsize(b, false); assert(b->type->taxes>0); maxmorale = (bsize + 1) * MORALE_TAX_FACTOR / b->type->taxes; } if (morale < maxmorale) { if (stability > MORALE_COOLDOWN && r->land->ownership->owner && morale < MORALE_MAX) { double ch = popularity(); if (is_cursed(r->attribs, &ct_generous)) { ch *= 1.2; /* 20% improvement */ } if (stability >= MORALE_AVERAGE * 2 || chance(ch)) { region_set_morale(r, morale + 1, turn); } } } else if (morale > maxmorale) { region_set_morale(r, morale - 1, turn); } } else if (morale > MORALE_DEFAULT) { region_set_morale(r, morale - 1, turn); } }
faction *update_owners(region * r) { faction *f = NULL; assert(rule_region_owners()); if (r->land) { building *bowner = largestbuilding(r, &cmp_current_owner, false); building *blargest = largestbuilding(r, &cmp_taxes, false); if (blargest) { if (!bowner || bowner->size < blargest->size) { /* region owners update? */ unit *u = building_owner(blargest); f = region_get_owner(r); if (u == NULL) { if (f) { region_set_owner(r, NULL, turn); r->land->ownership->flags |= OWNER_MOURNING; f = NULL; } } else if (u->faction != f) { if (!r->land->ownership) { /* there has never been a prior owner */ region_set_morale(r, MORALE_DEFAULT, turn); } else { alliance *al = region_get_alliance(r); if (al && u->faction->alliance == al) { int morale = _max(0, r->land->morale - MORALE_TRANSFER); region_set_morale(r, morale, turn); } else { region_set_morale(r, MORALE_TAKEOVER, turn); if (f) { r->land->ownership->flags |= OWNER_MOURNING; } } } region_set_owner(r, u->faction, turn); f = u->faction; } } } else if (r->land->ownership && r->land->ownership->owner) { r->land->ownership->flags |= OWNER_MOURNING; region_set_owner(r, NULL, turn); f = NULL; } } return f; }
void morale_change(region *r, int value) { int morale = region_get_morale(r); if (morale > 0) { morale = morale - value; if (morale < 0) morale = 0; region_set_morale(r, morale, turn); } }
static int tolua_region_set_morale(lua_State * L) { region *r = (region *)tolua_tousertype(L, 1, 0); region_set_morale(r, (int)tolua_tonumber(L, 2, 0), turn); return 0; }
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)); } } }