/* * 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 "companies.h" #include "population.h" #include "connections.h" #include "senkenconfig.h" #include "vars.h" #define HASH_SIZE 107 extern tiles_t *tiles; extern map_t *map; extern population_t *population; struct companies_s { company_t *list[HASH_SIZE]; }; static int hashit(int x, int y) { return ((x * 63) + (y * 43)) % HASH_SIZE; } /* * Get company starting margin */ static float margin_init(company_t *c) { vars_t vars; int margin; memset(&vars, 0, sizeof(vars_t)); vars.c = c; margin = config_getfunction_evaluate("company_startmargin", &vars_getvariable, &vars, 125); return ((float)margin)/((float)100.0); } static void margin_update(company_t *c) { c->margin -= .01; if (c->lastprofit < 0) { if (c->cash < abs(3 * c->lastprofit)) { /* * chance of turning things around */ if (rand() % 3 == 0) { c->margin += (float)(rand() % 12)/((float)100); } } } } int companies_init(companies_t **companies) { companies_t *ret; ret = calloc(1, sizeof(companies_t)); if (!ret) return -1; *companies = ret; return 0; } int companies_add(companies_t *companies, int x, int y, int obj) { int hash = hashit(x, y); company_t *c; int startcash; c = calloc(1, sizeof(company_t)); if (!c) return -1; c->obj = obj; c->x = x; c->y = y; startcash = config_getfunction_evaluate("company_startcash", &vars_company_getvariable, c, -1); if (startcash == -1) { int upkeep; int i; labor_t *maxlabor = tiles_getemploy(tiles, c->obj); /* * Comapnies start with enough cash to hire employees and * operate for 3 months (salaries and upkeep) */ upkeep = tiles_getupkeep(tiles, obj, &vars_company_getvariable, c); startcash = 3 * upkeep; for (i = 0; i < LABOR_NUMGROUPS; i++) { startcash += (maxlabor->workers[i] * labor_table[i].salary/12) * 3; startcash += maxlabor->workers[i] * HIRECOST; } } c->cash = startcash / 100; c->margin = margin_init(c); c->next = companies->list[hash]; companies->list[hash] = c; return 0; } int companies_remove(companies_t *companies, int x, int y) { int hash = hashit(x, y); company_t *c; company_t *last = NULL; c = companies->list[hash]; while (c) { if ((c->x == x) && (c->y == y)) { if (last) { last->next = c->next; } else { companies->list[hash] = c->next; } free(c); return 0; } last = c; c = c->next; } return -1; } company_t * companies_find(companies_t *companies, int x, int y) { int hash = hashit(x, y); company_t *c; c = companies->list[hash]; while (c) { if ((c->x == x) && (c->y == y)) { return c; } c = c->next; } return NULL; } static int numemploy(company_t *c) { int i; int cnt = 0; for (i = 0; i < LABOR_NUMGROUPS; i++) { cnt += c->labor.workers[i]; } return cnt; } extern int company_numemploy(company_t *c) { return numemploy(c); } labor_t * companies_maxemploy(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); if (!c) return 0; return tiles_getemploy(tiles, c->obj); } int companies_openings(companies_t *companies, int x, int y, enum labor_skill skill) { company_t *c = companies_find(companies, x, y); labor_t *maxlabor; if (!c) return 0; maxlabor = tiles_getemploy(tiles, c->obj); return maxlabor->workers[skill] - c->labor.workers[skill]; } int companies_hasopening(companies_t *companies, int x, int y, enum labor_skill skill) { int openings = companies_openings(companies, x, y, skill); return (openings > 0); } int companies_takejob(companies_t *companies, int x, int y, enum labor_skill skill) { company_t *c = companies_find(companies, x, y); if (!c) return -1; if (!companies_hasopening(companies, x, y, skill)) { printf(_("Can't work there\n")); return -1; } c->labor.workers[skill]++; c->cash -= HIRECOST/100; return 0; } int companies_quitjob(companies_t *companies, int x, int y, enum labor_skill skill) { company_t *c = companies_find(companies, x, y); if (!c) { printf(_("No company there to quit job from\n")); return -1; } if (c->labor.workers[skill] <= 0) { printf(_("Nobody works there\n")); return -1; } c->labor.workers[skill]--; return 0; } labor_t * companies_employ(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); if (!c) return 0; return &c->labor; } mapspot_list_t * companies_find_openings_list(companies_t *companies) { int i; mapspot_list_t *ret = NULL; for (i = 0; i < HASH_SIZE; i++) { company_t *c = companies->list[i]; while (c) { labor_t *maxlabor = tiles_getemploy(tiles, c->obj); int j; for (j = 0; j < LABOR_NUMGROUPS; j++) { if (maxlabor->workers[j] > c->labor.workers[j]) { mapspot_list_add(&ret, c->x, c->y, (void *)j); } } c = c->next; } } return ret; } int companies_gettotalsalary(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); int total = 0; int i; if (!c) return 0; for (i = 0; i < LABOR_NUMGROUPS; i++) { total += c->labor.workers[i] * labor_table[i].salary; } return total; } void companies_positions_avail(companies_t *companies, labor_t *labor) { int i; memset(labor, 0, sizeof(labor_t)); for (i = 0; i < HASH_SIZE; i++) { company_t *c = companies->list[i]; while (c) { int j; for (j = 0; j < LABOR_NUMGROUPS; j++) { labor->workers[j] += companies_openings(companies, c->x, c->y, j); } c = c->next; } } } int companies_total_positions(companies_t *companies) { int i; int cnt = 0; for (i = 0; i < HASH_SIZE; i++) { company_t *c = companies->list[i]; while (c) { cnt += numemploy(c); c = c->next; } } return cnt; } void company_revenue(company_t *company, revenue_iterate_callback *callback, void *rock) { int revenue = 0; float food_production = 0; int costs = 0; int i; /* * Revenue */ if ((!map_isflagset(map, company->x, company->y, MAPFLAG_NOPOWER)) && (!map_isflagset(map, company->x, company->y, MAPFLAG_NOWATER))) { revenue = tiles_getrevenue(tiles, company->obj, &vars_company_getvariable, company) * company->margin; food_production = tiles_getproduction(tiles, company->obj, &vars_company_getvariable, company) * company->margin; } /* * Update margin */ margin_update(company); /* * Building upkeep */ costs += tiles_getupkeep(tiles, company->obj, &vars_company_getvariable, company); /* * Salaries */ for (i = 0; i < LABOR_NUMGROUPS; i++) { costs += company->labor.workers[i] * labor_table[i].salary; } { int maxemploy = tiles_getnumemploy(tiles, company->obj); int employ = numemploy(company); int owner = map_get_owner(map, company->x, company->y); if (maxemploy > 0) { revenue *= employ/maxemploy; food_production *= employ/maxemploy; } callback(company, owner, revenue, costs, food_production, rock); } } int companies_get_revenue(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); if (!c) return 0; return tiles_getrevenue(tiles, c->obj, &vars_company_getvariable, c); } void companies_revenue_iterate(companies_t *companies, revenue_iterate_callback *callback, void *rock) { int i; for (i = 0; i < HASH_SIZE; i++) { company_t *c = companies->list[i]; while (c) { company_revenue(c, callback, rock); c = c->next; } } } int companies_get_cash(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); if (!c) return -1; return c->cash*100; } int companies_get_lastprofit(companies_t *companies, int x, int y) { company_t *c = companies_find(companies, x, y); if (!c) return -1; return c->lastprofit; } int companies_out_of_business(companies_t *companies) { int i; for (i = 0; i < HASH_SIZE; i++) { company_t *c = companies->list[i]; company_t *last = NULL; while (c) { company_t *next = c->next; if (map_item_gettype(c->obj) == MAPTYPE_FARM) { /* farms don't go out of business */ c = next; continue; } if ((c->cash < 0) && (map_get_owner(map, c->x, c->y) == 0)) { mapspot_t spot; mapobj_t newobj = MAPOBJ_ACTION_DEMOLISH; int sx; int sy; int j; int k; population_fire_everybody(population, c->x, c->y); #if 0 switch (map_get_kind(c->obj)) { case MAPTYPE_ENTERTAINMENT: case MAPTYPE_GOVERNMENT: case MAPTYPE_HOUSE: case MAPTYPE_EMPTY: newobj = MAPOBJ_DEMOLISH; break; case MAPTYPE_COMMERCIAL: newobj = MAPOBJ_ZONE_COMMERCIAL; break; case MAPTYPE_OFFICE: newobj = MAPOBJ_ZONE_OFFICE; break; case MAPTYPE_INDUSTRIAL: newobj = MAPOBJ_ZONE_INDUSTRIAL; break; case MAPTYPE_FARM: newobj = MAPOBJ_ZONE_FARM; break; } #endif /* 0 */ newobj = MAPOBJ_ACTION_DEMOLISH; tiles_getsize(tiles, c->obj, &sx, &sy); for (j = 0; j < sx; j++) { for (k = 0; k < sy; k++) { map_set_type(map, c->x + j, c->y + k, newobj, 1); memset(&spot, 255, sizeof(mapspot_t)); spot.mapobj = newobj; connections_send_to_all("* BOARDSPOT %d %d %s\r\n", c->x + j,c->y + k, map_spot2string(&spot)); } } free(c); if (last) { last->next = next; } else { companies->list[i] = next; } } else { last = c; } c = next; } } return 0; } int companies_getsalary(companies_t *companies, int x, int y, enum labor_skill skill) { return labor_table[skill].salary; }