/* * Copyright (C) 2003 Tim Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include "utils.h" #include "population.h" #include "player.h" #include "map.h" #include "senkenconfig.h" #include "landvalue.h" #include "connections.h" #include "game.h" #include "companies.h" #include "investment.h" #include "vars.h" #include "happy.h" static short uid = 1; extern tiles_t *tiles; extern map_t *map; extern game_t *game; extern companies_t *companies; int g_population_change_month = 0; int g_left_month = 0; float g_food_production_month = 0; extern mapobj_t *entertainment_types_list; extern mapobj_t *commercial_types_list; extern int commercial_types_len; typedef struct agegroup_s { popgroup_t group; } agegroup_t; struct population_s { agegroup_t *age[MAXAGE+1]; int total_population; }; static int find_school(person_t *person, map_t *map, mapspot_list_t **list); static int find_house(person_t *person, map_t *map, mapspot_list_t **list); static int find_job(person_t *person, map_t *map, mapspot_list_t **list); typedef struct getvar_struct_s { int x; int y; map_t *map; } getvar_struct_t; static int getvariable_cb(char *name, void *rock) { getvar_struct_t *rstruct = (getvar_struct_t *)rock; return map_getvariable_cb(name, rstruct->map, rstruct->x, rstruct->y); } static int add_person(population_t *pop, int age, int edlevel, person_t *parent, person_t **newperson) { popgroup_t *group = &pop->age[age]->group; int pnum = group->size; person_t *person; group->size++; pop->total_population++; if (group->size > group->allocsize) { if (group->allocsize == 0) { group->allocsize = 4; } else { group->allocsize *= 2; } group->data = realloc(group->data, group->allocsize*sizeof(person_t)); } person = &group->data[pnum]; if (parent) { person->uid = parent->uid; } else { person->uid = uid++; } person->livex = -1; person->livey = -1; person->workx = -1; person->worky = -1; person->happy = 100; person->flags = 0; person->edlevel = edlevel; /* xxx */ person->savings = 100; if (newperson) { *newperson = person; } return 0; } static int add_random_person(population_t *pop, int minage, int maxage, int life_expectancy) { int range = maxage - minage; float deathrate = 50./life_expectancy * 100; int prob_kids; person_t *parent = NULL; while (1) { int age = rand()%range + minage; int i; int edlevel; for (i = 0; i < age; i++) { if (rand()%(100*100) <= deathrate) { continue; } } edlevel = 8 + (rand()%6 + rand()%6); add_person(pop, age, edlevel, NULL, &parent); if (age >= 18) { find_house(parent, map, &game->avail_houses_list); find_job(parent, map, &game->avail_job_list); } else { find_school(parent, map, &game->schools_list); } break; } prob_kids = config_getint("probability_have_kids", 50); /* xxx doesn't handle prob_kids being > 1.0 */ if (rand()%100 <= prob_kids) { int min_working_age = config_getint("min_work_age", 18); person_t *child = NULL; int age = rand() % min_working_age; add_person(pop, age, age - 4, parent, &child); parent->flags |= PERSON_FLAG_HASCHILD; find_school(child, map, &game->schools_list); } return 0; } static void quit_job(map_t *map, person_t *person) { if (person->workx != -1) { companies_quitjob(companies, person->workx, person->worky, person->worklevel); } person->workx = -1; person->worky = -1; } static void moveout(map_t *map, person_t *person, int age) { if (person->livex != -1) { if (age < 18) { map_leave_school(map, person->livex, person->livey); } else { map_unrent(map, person->livex, person->livey); } } person->livex = -1; person->livey = -1; } static void remove_one_person(population_t *pop, map_t *map, int age, popgroup_t *group, int index) { person_t *person = &group->data[index]; quit_job(map, person); moveout(map, person, age); memmove(&group->data[index], &group->data[index+1], (group->size - index -1) * sizeof(person_t)); group->size--; pop->total_population--; } extern void population_foreach_child(population_t *pop, short uid, child_iterate_func *func, void *rock) { int i; int min_working_age = config_getint("min_work_age", 18); for (i = 0; i < min_working_age; i++) { int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *child = &group->data[k]; if (child->uid == uid) { func(child, rock); } } } } static person_t * find_parent(population_t *pop, short uid) { int i; for (i = 18; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *parent = &group->data[k]; if ((parent->uid == uid) && (parent->flags & PERSON_FLAG_HASCHILD)) { return parent; } } } return NULL; } static void remove_children(population_t *pop, map_t *map, short uid) { int i; int found = 0; for (i = 0; i < 18; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *child = &group->data[k]; if (child->uid == uid) { remove_one_person(pop, map, i, group, k); found++; } } } if (!found) { printf(_("didn't find any children for uid %d\n"), uid); } } static void remove_person(population_t *pop, map_t *map, int age, popgroup_t *group, int index, int andchildren) { person_t *parent = &group->data[index]; if ((andchildren) && (parent->flags & PERSON_FLAG_HASCHILD)) { /* find children and remove them */ remove_children(pop, map, parent->uid); } remove_one_person(pop, map, age, group, index); } int population_init(population_t **pop) { population_t *ret; int i; int initial_population = config_getfunction_evaluate("initial_population", &vars_population_getvariable, NULL, 0); int life_expectancy = config_getint("life_expectancy", 50); int min_working_age = config_getint("min_work_age", 18); int r; ret = calloc(1, sizeof(population_t)); if (!ret) return -1; for (i = 0; i <= MAXAGE; i++) { agegroup_t *agegroup = calloc(1, sizeof(agegroup_t)); ret->age[i] = agegroup; } /* * XXX Uniform education level */ for (i = 0; i < initial_population; i++) { int r; r = add_random_person(ret, min_working_age, MAXAGE, life_expectancy); if (r) return r; } r = investment_init(); if (r) return r; *pop = ret; return 0; } int population_imigrate(population_t *pop, int days) { int num; int life_expectancy = config_getint("life_expectancy", 50); int min_working_age = config_getint("min_work_age", 18); int i; float numf; static float immigrate_remainer = 0.0; numf = ((float)config_getfunction_evaluate("immigrants_month", &vars_population_getvariable, NULL, 0) * days) / ((float)DAYS_MONTH) + immigrate_remainer; if (numf < 0.0) numf = 0.0; num = numf; immigrate_remainer = numf - num; /* * XXX Uniform education level */ for (i = 0; i < num; i++) { int r; r = add_random_person(pop, min_working_age, MAXAGE, life_expectancy); if (r) { printf("Error adding random person: %d\n", r); } } /*printf("%d people arrived in the last %d days\n", num, days);*/ return num; } int population_exigrate(population_t *pop, map_t *map, int days) { int i; int min_working_age = config_getint("min_work_age", 18); int left = 0; int totalhappy = 0; int totalpop = 0; game->totalkids = 0; /* just count the young'ins */ for (i = 0; i < min_working_age; i++) { int k; popgroup_t *group = &pop->age[i]->group; totalpop += group->size; game->totalkids += group->size; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; totalhappy += person->happy; } } for (i = min_working_age; i < MAXAGE; i++) { popgroup_t *group = &pop->age[i]->group; int k; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; int remove = 0; if (person->happy <= 50) { /*printf("happiness too low (%d). person leaving\n", person->happy);*/ remove = 1; } else if (person->savings < 0) { /*printf("savings too low (%d). person leaving\n", person->savings);*/ remove = 1; } if (remove) { /* xxx doesn't count kids leaving */ remove_person(pop, map, i, group, k, 1); k--; left++; continue; } totalhappy += person->happy; totalpop++; } } game->totalpop = totalpop; g_left_month += left; /*printf("%d people left in the last %d days\n", left, days);*/ return left; } int population_getproduction(population_t *pop) { return g_food_production_month; } float population_homeless_rate(population_t *pop) { if (game->totalpop) { return ((float)game->homeless) / ((float)game->totalpop); } else { return 0.0; } } float population_unemployment_rate(population_t *pop) { if (game->totalpop) { return ((float)labor_count(&game->needjobs)) / ((float)game->totalpop); } else { return 0.0; } } int population_age1year(population_t *pop, map_t *map) { int i; int min_working_age = config_getint("min_work_age", 18); /* * Everyone MAXAGE old dies */ while (pop->age[MAXAGE]->group.size > 0) { remove_person(pop, map, MAXAGE, &pop->age[MAXAGE]->group, 0, 0); /* xxx remove last person */ } /* * Everyone gets 1 year older */ for (i = MAXAGE; i >= 1; i--) { pop->age[i] = pop->age[i-1]; /* * People going to school get smarter */ if (i <= min_working_age) { int k; for (k = 0; k < pop->age[i]->group.size; k++) { person_t *person = &pop->age[i]->group.data[k]; if (person->livex != -1) { person->edlevel++; } } } /* * when turn 18 no longer dependent on parents * * also no longer go to school */ if (i == min_working_age) { int k; for (k = 0; k < pop->age[i]->group.size; k++) { person_t *child = &pop->age[i]->group.data[k]; person_t *parent; /* find parent and unlink them */ parent = find_parent(pop, child->uid); if (parent) { parent->flags &= ~PERSON_FLAG_HASCHILD; parent->uid = 0; } child->uid = 0; /* leave school. find house */ if (child->livex != -1) { map_leave_school(map, child->livex, child->livey); } find_house(child, map, &game->avail_houses_list); find_job(child, map, &game->avail_job_list); } } } pop->age[0] = calloc(1, sizeof(agegroup_t)); /* * XXX nobody dies */ return 0; } int population_born(population_t *pop, int days) { int i; int birth_rate = config_getint("birth_rate", 0); int born = 0; /* * XXX everyone 20-40 has equal chance of giving birth * */ for (i = 20; i < 40; i++) { int k; for (k = 0; k < pop->age[i]->group.size; k++) { if (rand()%(12*1000*DAYS_MONTH/days) <= birth_rate) { person_t *parent = &pop->age[i]->group.data[k]; parent->flags |= PERSON_FLAG_HASCHILD; add_person(pop, 0, 0, parent, NULL); born++; } } } return born; } static int house_is_suitable(int mapx, int mapy, void *data, float dist, void *rock) { person_t *person = (person_t *)rock; int r; int owner; r = map_rent(map, mapx, mapy,&owner); if (r) { printf(_("Error renting %d,%d\n"), mapx, mapy); return 0; } person->livex = mapx; person->livey = mapy; happy_upto(person, 100, 5, REASON_FIND_HOUSING); return 1; } static int find_house(person_t *person, map_t *map, mapspot_list_t **list) { int r; r = mapspot_within_iterate(*list, 0, 0, MAXFLOAT, &house_is_suitable, person); if (r) { if (!map_isvacant(map, person->livex, person->livey)) { mapspot_list_remove(list, person->livex, person->livey); } return 0; } else { return 1; } } static int school_is_suitable(int mapx, int mapy, void *data, float dist, void *rock) { person_t *person = (person_t *)rock; int r; r = map_attend_school(map, mapx, mapy); if (r) { return 0; } person->livex = mapx; person->livey = mapy; /* xxx make parents happy too */ happy_upto(person, 100, 5, REASON_FIND_HOUSING); /* XXX */ return 1; } static int find_school(person_t *person, map_t *map, mapspot_list_t **list) { int r; r = mapspot_within_iterate(*list, 0, 0, MAXFLOAT, &school_is_suitable, person); if (r) { if (map_is_school_full(map, person->livex, person->livey)) { mapspot_list_remove(list, person->livex, person->livey); } return 0; } else { return 1; } } static int job_is_suitable(int mapx, int mapy, void *data, float dist, void *rock) { person_t *person = (person_t *)rock; int r; enum labor_skill skill = (enum labor_skill)data; /* * Don't take job can't do */ if (person->edlevel < labor_table[skill].edlevel) { /*printf("not smart enough to take job (%d < %d)\n", person->edlevel, labor_table[skill].edlevel);*/ return 0; } /* * If overqualified don't take the job unless very unhappy */ if ((person->edlevel - 4 > labor_table[skill].edlevel) && (person->happy > 80)) { /* printf("won't degrade to work at that level %d vs %d\n", person->edlevel, labor_table[skill].edlevel);*/ return 0; } r = companies_takejob(companies, mapx, mapy, skill); if (r) { printf(_("Error taking job at %d,%d\n"), mapx, mapy); return 0; } person->workx = mapx; person->worky = mapy; person->worklevel = skill; happy_upto(person, 100, 5, REASON_FIND_WORK); /* XXX */ return 1; } static int find_job(person_t *person, map_t *map, mapspot_list_t **list) { int r; r = mapspot_within_iterate(*list, 0, 0, MAXFLOAT, &job_is_suitable, person); if (r) { if (!companies_hasopening(companies, person->workx, person->worky, person->worklevel)) { mapspot_list_remove_data(list, person->workx, person->worky, (void *)person->worklevel); } return 0; } else { return 1; } } int population_movehousing(population_t *pop, map_t *map) { int i; int min_working_age = config_getint("min_work_age", 18); int homeless = 0; /* * kids try to find schools */ if (game->schools_list) { mapspot_list_free(game->schools_list); game->schools_list = NULL; } game->schoolless = 0; game->schools_list = map_find_tile_list(map, MAPTYPE_SCHOOL); for (i = 0; i < min_working_age; i++) { popgroup_t *group = &pop->age[i]->group; int k; for (k = 0; k < group->size; k++) { if (group->data[k].livex == -1) { if (find_school(&group->data[k], map, &game->schools_list) != 0) { game->schoolless++; } } } } /* * First people without homes try to find homes * */ if (game->avail_houses_list) { mapspot_list_free(game->avail_houses_list); game->avail_houses_list = NULL; } game->avail_houses_list = map_find_vacant_list(map); for (i = min_working_age; i < MAXAGE; i++) { popgroup_t *group = &pop->age[i]->group; int k; for (k = 0; k < group->size; k++) { if (group->data[k].livex == -1) { if (find_house(&group->data[k], map, &game->avail_houses_list) != 0) { /* xxx remove_person(pop, map, group, k);*/ homeless++; } } } } /* XXX move */ return 0; } int population_changejobs(population_t *pop, map_t *map) { int i; int min_working_age = config_getint("min_work_age", 18); /* * First people without jobs try to find them * */ game->avail_job_list = companies_find_openings_list(companies); for (i = min_working_age; i < MAXAGE; i++) { popgroup_t *group = &pop->age[i]->group; int k; for (k = 0; k < group->size; k++) { if (group->data[k].workx == -1) { if (find_job(&group->data[k], map, &game->avail_job_list) != 0) { /* xxx remove_person(pop, map, group, k);*/ } } } } /* XXX change jobs */ return 0; } void population_calculate_happiness(population_t *pop) { int i; happy_t *happy = happy_init(); int totalhappy = 0; int cnt = 0; int per = 1000/(MAXAGE-game->min_working_age); for (i = game->min_working_age; i < MAXAGE; i++) { popgroup_t *group = &pop->age[i]->group; int k; int numtodo = per; if (numtodo > group->size) { numtodo = group->size; } for (k = 0; k < numtodo; k++) { person_t *person = &group->data[rand()%group->size]; totalhappy += happy_calc_person(happy, person); cnt++; } } /* calc average happy */ if (cnt) { int newavg = ((float)totalhappy)/((float)cnt); game->avghappy = (game->avghappy + newavg + 1)/2; } else { game->avghappy = 100; } happy_free(happy); } static void pay_salary(person_t *person, map_t *map) { int owner; float salary; float tax; if (person->workx == -1) { return; } owner = map_get_owner(map, person->workx, person->worky); salary = companies_getsalary(companies, person->workx, person->worky, person->worklevel)/12; game->month_gdp += salary; player_reducemoney_num(owner, COST_SALARY, salary); tax = salary * ((float)game->tax_rates[TAX_TYPE_INCOME]/100.0); salary -= tax; person->savings += (salary - tax)/100; /* xxx who is paid tax? */ player_addmoney_num(game->government_player, INCOME_TAX, tax); } int population_paysalaries(population_t *pop, map_t *map) { int i; for (i = 0; i < MAXAGE; i++) { int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { pay_salary(&group->data[k], map); } } return 0; } static void pay_rent(person_t *person, map_t *map) { int owner; float rent; if (person->livex == -1) { return; } rent = map_getrent(map, person->livex, person->livey)/12; owner = map_getowner(map, person->livex, person->livey); /* xxx what if don't have enough? */ person->savings -= (rent/100); player_addmoney_num(owner, INCOME_RENT, rent); game->month_gdp += rent; /* xxx decide to move? */ } typedef struct patronige_s { int visits; person_t *person; } patronige_t; static int patronize_cb(int mapx, int mapy, void *data, float dist, void *rock) { patronige_t *pat = (patronige_t *)rock; if (pat->visits > 0) { return -1; } if (map_patronize(map, mapx, mapy) == 0) { pat->visits++; } return 0; } static void patronize(person_t *person, mapspot_list_t **lists) { patronige_t pat; int i; int nobuy = 0; memset(&pat, 0, sizeof(patronige_t)); pat.person = person; i = 0; while (commercial_types_list[i] != MAPOBJ_INVALID) { pat.visits = 0; if (rand()%100 <= tiles_getpatronperc(tiles, commercial_types_list[i]) * 100) { mapspot_within_iterate(lists[i], person->livex, person->livey, tiles_getrange(tiles, commercial_types_list[i]), &patronize_cb, &pat); if (pat.visits == 0) { nobuy++; } } i++; } if (nobuy) { happy_down(person, nobuy, REASON_NOBUY); } } int population_patronize(population_t *pop, map_t *map) { int i; mapspot_list_t **lists; map_clear_patronige(map); lists = malloc(sizeof(mapspot_list_t *) * commercial_types_len); i = 0; while (commercial_types_list[i] != MAPOBJ_INVALID) { lists[i] = map_find_tile_list_obj(map, commercial_types_list[i]); i++; } for (i = 0; i < MAXAGE; i++) { int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { patronize(&group->data[k], lists); } } return 0; } int population_payrent(population_t *pop, map_t *map) { int i; for (i = 0; i < MAXAGE; i++) { int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { pay_rent(&group->data[k], map); } } return 0; } popgroup_t * population_getgroup(population_t *pop, int age) { return &pop->age[age]->group; } static void pay_upkeep(map_t *map, int mapx, int mapy, int owner, int upkeep, void *rock) { upkeep /= 12; game->month_gdp += upkeep; player_reducemoney_num(owner, COST_UPKEEP, upkeep); } void population_payupkeep(population_t *pop, map_t *map) { map_upkeep_iterate(map, &pay_upkeep, NULL); } static void make_revenue(company_t *company, int owner, int revenue, int costs, float food_production, void *rock) { int salestax; int profit; revenue = revenue/12; costs = costs/12; game->month_gdp += revenue; salestax = revenue * ((float)game->tax_rates[TAX_TYPE_SALES]/100.0); revenue -= salestax; profit = revenue - costs; if (company) { company->lastprofit = profit; company->cash += profit/100; } if (profit > 0) { int incometax = profit * ((float)game->tax_rates[TAX_TYPE_BUS_INCOME]/100.0); revenue -= incometax; player_addmoney_num(game->government_player, INCOME_TAX, incometax); } player_addmoney_num(owner, INCOME_REVENUE, revenue); player_addmoney_num(game->government_player, INCOME_TAX, salestax); g_food_production_month += ((float)food_production)/((float)12); } static void is_field_callback(map_t *map, int mapx, int mapy, int owner, mapobj_t obj, void *rock) { int food_production; int revenue; int upkeep; getvar_struct_t rstruct; mapobj_t fieldobj = *(mapobj_t *)rock; if (obj != fieldobj) return; rstruct.map = map; rstruct.x = mapx; rstruct.y = mapy; revenue = tiles_getrevenue(tiles, obj, &getvariable_cb, &rstruct); food_production = tiles_getproduction(tiles, obj, &getvariable_cb, &rstruct); upkeep = tiles_getupkeep(tiles, obj, &getvariable_cb, &rstruct); make_revenue(NULL, map_get_owner(map, mapx, mapy), revenue, upkeep, food_production, NULL); } void population_revenue(population_t *pop, map_t *map) { mapobj_t fieldobj = map_item_name2obj("Field"); game->month_gdp = 0; g_food_production_month = 0; companies_revenue_iterate(companies, &make_revenue, NULL); map_iterate(map, MAP_ITERATE_NORMAL, 0, 0, 0, NULL, NULL, NULL, NULL, &is_field_callback, &fieldobj); } extern int population_calculate_adults(population_t *pop) { int adults = 0; int i; for (i = 20; i < MAXAGE; i++) { /* xxx */ popgroup_t *group = &pop->age[i]->group; adults += group->size; } return adults; } extern int population_calculate_needhousing(population_t *pop) { int homeless = 0; int i; for (i = 20; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if (person->livex == -1) homeless++; } } return homeless; } extern void population_calculate_unemployed(population_t *pop, labor_t *labor) { int i; memset(labor, 0, sizeof(labor_t)); for (i = 18; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if (person->workx == -1) { int j; for (j = 1; j < LABOR_NUMGROUPS; j++) { if (person->edlevel < labor_table[j].edlevel) { break; } } labor->workers[j-1]++; } } } } static long total = 0; /* xxx */ int population_investment_available(population_t *pop) { return total; } extern void population_center(population_t *pop, int *x, int *y) { int i; int totx = 0; int toty = 0; int totpeople = 0; for (i = 0; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if (person->livex != -1) { totx += person->livex; toty += person->livey; totpeople++; } } } if (totpeople > 0) { *x = totx / totpeople; *y = toty / totpeople; } else { *x = 0; *y = 0; } } static void corp_poperty_tax_callback(map_t *map, int mapx, int mapy, int owner, mapobj_t obj, void *rock) { int property_value; int tax; if (!map_item_gettype(obj) != MAPTYPE_COMMERCIAL) return; /* xxx need to pay for whole area */ property_value = government_calculate_onelandvalue(map, tiles, mapx, mapy) / 12; tax = ((float)property_value)*((float)game->tax_rates[TAX_TYPE_PROPERTY]/100.0); player_addmoney_num(game->government_player, INCOME_TAX, tax); } int population_property_tax(population_t *pop) { int nominal_tax = config_getint("nominal_property_taxrate", 1); float taxrate = ((float)game->tax_rates[TAX_TYPE_PROPERTY]/100.0); int i; /* * People pay property tax */ for (i = game->min_working_age; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if (person->livex != -1) { int property_value = government_calculate_onelandvalue(map, tiles, person->livex, person->livey) / 12; int numlive = map_occupancy(map, person->livex, person->livey); int tax; if (!numlive) { printf("Error. person lives at %d,%d but occupancy zero\n", person->livex, person->livey); continue; } tax = ((float)(property_value/numlive))*taxrate; person->savings -= tax / 100; if (game->tax_rates[TAX_TYPE_PROPERTY] > nominal_tax) { happy_down(person, (game->tax_rates[TAX_TYPE_PROPERTY] - nominal_tax) * 2, REASON_TAXES); } player_addmoney_num(game->government_player, INCOME_TAX, tax); } } } /* * Now corporations */ map_iterate(map, MAP_ITERATE_NORMAL, 0, 0, 0, NULL, NULL, NULL, NULL, &corp_poperty_tax_callback, NULL); return 0; } int population_fire_everybody(population_t *pop, int x, int y) { int i; for (i = 0; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if ((person->workx == x) && (person->worky == y)) { person->workx = -1; person->worky = -1; happy_down(person, 30, REASON_UNEMPLOYED); } } } return 0; } int population_evict_everybody(population_t *pop, int x, int y) { int i; for (i = 0; i < MAXAGE; i++) { /* xxx */ int k; popgroup_t *group = &pop->age[i]->group; for (k = 0; k < group->size; k++) { person_t *person = &group->data[k]; if ((person->livex == x) && (person->livey == y)) { person->livex = -1; person->livey = -1; happy_down(person, 30, REASON_HOMELESS); } } } return 0; } static char *reason_table[] = {"Found housing", "Found work", "Employed", "Unemployed", "Taxes", "Economy", "Homeless", "Nature", "Police", "Fire", "Hospital", "Housed", "Schools", "Nowhere to shop", "Social", "Not enough schools", "Underemployed", "Not enough power", "Not enough water", "Garbage not being collected", NULL}; char * population_reason_string(happy_reason_t reason) { return reason_table[reason]; } void population_newmonth(void) { int i; for (i = 0; i < NUM_REASONS; i++) { game->reasons_last[i] = game->reasons[i]; game->reasons[i] = 0; } game->left_lastmonth = g_left_month; g_left_month = 0; game->popchange_lastmonth = g_population_change_month; g_population_change_month = 0; }