1 /* ---------------------------------------------------------------------- *
2  * residence.c
3  * This file is part of lincity.
4  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5  * (c) Corey Keasling, 2004
6  * ---------------------------------------------------------------------- */
7 
8 #include "modules.h"
9 #include "residence.h"
10 #include "waterwell.h"
11 #include <stdlib.h>
12 
do_residence(int x,int y)13 void do_residence(int x, int y)
14 {
15     /*
16        // int_1 is a job swingometer to choose +/- JOB_SWING% of normal
17        // int_2 is the date of the last starve
18        // int_3 unused
19        // int_4 is the birth rate modifier.
20        // int_5 is the death rate modifier.
21        // int_6 unused
22        // int_7 unused Could be FLAG_HAD_POWER which is specific to residences, and will free 1 flag.
23        //                btw, FLAG_POWERED and FLAG_GOT_POWER means the same thing. => free 1 more flag.
24        //
25      */
26     int p;                      /* population */
27     int bad = 35, good = 30;    /* (un)desirability of living here */
28     int r, po, swing;
29     int hc = 0;                 /* have health cover ? */
30     int brm = 0, drm = 0;       /* birth/death rate modifier */
31     int cc = 0;
32     int birth_flag = 0;
33 
34     p = MP_INFO(x, y).population;
35     if ((MP_INFO(x, y).flags & FLAG_HEALTH_COVER) != 0) {
36         brm += RESIDENCE_BRM_HEALTH;
37         good += 15;
38         hc = 1;
39     }
40     if ((MP_INFO(x, y).flags & FLAG_FIRE_COVER) == 0)
41         bad += 5;
42     else
43         good += 15;
44     if ((MP_INFO(x, y).flags & FLAG_CRICKET_COVER) != 0) {
45         good += 20;
46         cc = CRICKET_JOB_SWING;
47     }
48     /* normal deaths + pollution deaths */
49     po = ((MP_POL(x, y) / 50) + 1);
50     if ((RESIDENCE_BASE_DR - MP_INFO(x, y).int_5 - po) > 1)
51         r = rand() % (RESIDENCE_BASE_DR - MP_INFO(x, y).int_5 - po);
52     else
53         r = 2;
54     if (p > 0 && (r < po)) {
55         if (r == 0 || hc == 0)
56             p--;
57         else if (hc != 0 && po > 10 && rand() % 4 == 0) {
58             p--;
59             unnat_deaths++;
60             total_pollution_deaths++;
61             pollution_deaths_history += 1.0;
62             bad += 100;
63         }
64         if (r > 0 && hc == 0) {
65             unnat_deaths++;
66             total_pollution_deaths++;
67             pollution_deaths_history += 1.0;
68             bad += 100;
69         }
70     }
71     /* normal births - must have food, water and jobs... and people */
72     if (use_waterwell && (total_time >= deadline) )
73         birth_flag = FLAG_FED + FLAG_WATERWELL_COVER + FLAG_EMPLOYED;
74     else
75         birth_flag = FLAG_FED + FLAG_EMPLOYED;
76 
77     if (((MP_INFO(x, y).flags & birth_flag) == birth_flag)
78         && (rand() % (RESIDENCE_BASE_BR + MP_INFO(x, y).int_4) == 1)
79         && (p > 0)) {
80 #ifdef DEBUG_WATERWELL
81         fprintf(stderr, " birth ok, we are fed. use_waterwell= %i\n", use_waterwell);
82 #endif
83         p++;
84         total_births++;
85         good += 50;
86     }
87     /* are people starving or lacking water ? */
88     if (((MP_INFO(x, y).flags & FLAG_FED) == 0)
89         | (use_waterwell & ((MP_INFO(x, y).flags & FLAG_WATERWELL_COVER) == 0))
90         && p > 0) {
91         if (total_time > deadline) {
92 #ifdef DEBUG_WATERWELL
93             fprintf(stderr, " hey, we are dying: lack of food or water!, use_waterwell=%i\n", use_waterwell);
94 #endif
95 
96             if (rand() % DAYS_PER_STARVE == 1) {
97                 p--;
98                 unnat_deaths++;
99                 total_starve_deaths++;
100                 starve_deaths_history += 1.0;
101             }
102             starving_population += p;
103             bad += 250;
104             drm += 100;
105         }
106         MP_INFO(x, y).int_2 = total_time;       /* for the starve screen */
107     }
108     /* kick one out if overpopulated */
109     if (MP_TYPE(x, y) == CST_RESIDENCE_LL) {
110         brm += RESIDENCE1_BRM;
111         drm += p * 8;
112         if (p > 50) {
113             p--;
114             people_pool++;
115             brm += 20;
116         }
117     } else if (MP_TYPE(x, y) == CST_RESIDENCE_ML) {
118         brm += RESIDENCE2_BRM;
119         drm += p * 3;
120         if (p > 100) {
121             p--;
122             people_pool++;
123             brm += 10;
124         }
125     } else if (MP_TYPE(x, y) == CST_RESIDENCE_HL) {
126         brm += RESIDENCE3_BRM;
127         drm += p;
128         good += 40;
129         if (p > 200) {
130             p--;
131             people_pool++;
132             brm += 10;
133         }
134     } else if (MP_TYPE(x, y) == CST_RESIDENCE_LH) {
135         brm += RESIDENCE4_BRM;
136         drm += p * 5;
137         if (p > 100) {
138             p--;
139             people_pool++;
140             brm += 20;
141         }
142     } else if (MP_TYPE(x, y) == CST_RESIDENCE_MH) {
143         brm += RESIDENCE5_BRM;
144         drm += p / 2;
145         if (p > 200) {
146             p--;
147             people_pool++;
148             brm += 10;
149         }
150     } else if (MP_TYPE(x, y) == CST_RESIDENCE_HH) {
151         good += 100;
152         brm += RESIDENCE6_BRM;
153         drm += p;
154         if (p > 400) {
155             p--;
156             people_pool++;
157             brm += 10;
158         }
159     }
160 
161     /* XXX AL1: this is daily accumulator used stats.cpp, and maybe pop graph */
162     population += p;
163 
164     /* now get power */
165     if (get_power(x, y, POWER_RES_OVERHEAD + (POWER_USE_PER_PERSON * p), 0) != 0) {
166         MP_INFO(x, y).flags |= FLAG_POWERED;
167         MP_INFO(x, y).flags |= FLAG_HAD_POWER;
168         good += 10;
169     } else {
170         MP_INFO(x, y).flags &= (0xffffffff - FLAG_POWERED);
171         bad += 15;
172         if ((MP_INFO(x, y).flags & FLAG_HAD_POWER) != 0)
173             bad += 50;
174     }
175     /* now get fed */
176     /* AL1: could be done earlier, before check for starvation */
177     /*      this will be taken into account at next turn */
178     if ( get_food(x, y, p) != 0 ) {
179         if (p>0)
180             MP_INFO(x, y).flags |= FLAG_FED;
181         good += 10;
182     } else {
183         MP_INFO(x, y).flags &= (0xffffffff - FLAG_FED);
184         //MP_INFO(x,y).int_2 = total_time;
185     }
186 
187     /* now supply jobs and buy goods if employed */
188     if (MP_INFO(x, y).int_1 > 0)
189         swing = JOB_SWING + (hc * HC_JOB_SWING) + cc;
190     else
191         swing = -(JOB_SWING + (hc * HC_JOB_SWING) + cc);
192 
193     if (put_jobs(x, y, ((p * (WORKING_POP_PERCENT + swing)) / 100)) != 0) {
194         MP_INFO(x, y).flags |= FLAG_EMPLOYED;
195         MP_INFO(x, y).int_1++;
196         if (MP_INFO(x, y).int_1 > 10)
197             MP_INFO(x, y).int_1 = 10;
198         good += 20;
199         if (get_goods(x, y, p / 4) != 0) {
200             good += 10;
201             if (get_power(x, y, p / 2, 0) != 0) {
202                 good += 5;
203                 brm += 10;
204                 /*     buy more goods if got power for them */
205                 if (get_goods(x, y, p / 4) != 0)
206                     good += 5;
207             } else
208                 bad += 5;
209         }
210     } else if (MP_INFO(x, y).int_1 < 10) {
211         MP_INFO(x, y).flags &= (0xffffffff - FLAG_EMPLOYED);
212         MP_INFO(x, y).int_1 -= 11;
213         if (MP_INFO(x, y).int_1 < -300)
214             MP_INFO(x, y).int_1 = -300;
215         unemployed_population += p;
216         total_unemployed_days += p;
217         if (total_unemployed_days >= NUMOF_DAYS_IN_YEAR) {
218             total_unemployed_years++;
219             /* think we're ok doing this, max of about 120 added each time. */
220             total_unemployed_days -= NUMOF_DAYS_IN_YEAR;
221             unemployed_history += 1.0;
222         }
223         unemployment_cost += p; /* hmmm */
224         bad += 70;
225     } else {
226         MP_INFO(x, y).int_1 -= 20;
227         bad += 50;
228     }
229     drm += p / 4;
230     /* people_pool stuff */
231     bad += p / 2;
232     bad += MP_POL(x, y) / 20;
233     good += people_pool / 27;
234     r = rand() % ((good + bad) * RESIDENCE_PPM);
235     if (r < bad) {
236         if (p > MIN_RES_POPULATION) {
237             p--;
238             people_pool++;
239         }
240     } else if (people_pool > 0
241                && r > ((good + bad) * (RESIDENCE_PPM - 1) + bad)) {     /* r > (rmax - good) */
242         p++;
243         people_pool--;
244     }
245     MP_INFO(x, y).population = p;
246     MP_INFO(x, y).int_4 = brm;
247     MP_INFO(x, y).int_5 = drm;
248 }
249 
mps_residence(int x,int y)250 void mps_residence(int x, int y)
251 {
252     int i = 0;
253     const char *p;
254 
255     mps_store_title(i++, _("Residence"));
256 
257     i++;
258 
259     mps_store_sd(i++, _("People"), MP_INFO(x, y).population);
260 
261     if (use_waterwell) {
262         p = ((MP_INFO(x, y).flags & FLAG_WATERWELL_COVER) != 0)
263             ? _("YES") : _("NO");
264         mps_store_ss(i++, _("Water"), p);
265     }
266 
267     p = ((MP_INFO(x, y).flags & FLAG_FED) != 0) ? _("YES") : _("NO");
268     mps_store_ss(i++, _("Fed"), p);
269 
270     p = ((MP_INFO(x, y).flags & FLAG_POWERED) != 0) ? _("YES") : _("NO");
271     mps_store_ss(i++, _("Power"), p);
272 
273     p = ((MP_INFO(x, y).flags & FLAG_EMPLOYED) != 0) ? _("YES") : _("NO");
274     mps_store_ss(i++, _("Employed"), p);
275 
276     p = (MP_INFO(x, y).int_1 >= 10) ? _("good") : _("poor");
277     mps_store_ss(i++, _("Job"), p);
278 
279     p = ((MP_INFO(x, y).flags & FLAG_HEALTH_COVER) != 0) ? _("YES") : _("NO");
280     mps_store_ss(i++, _("Health Cvr"), p);
281 
282     p = ((MP_INFO(x, y).flags & FLAG_FIRE_COVER) != 0) ? _("YES") : _("NO");
283     mps_store_ss(i++, _("Fire"), p);
284 
285     p = ((MP_INFO(x, y).flags & FLAG_CRICKET_COVER) != 0) ? _("YES") : _("NO");
286     mps_store_ss(i++, _("Sport"), p);
287 
288     mps_store_sd(i++, _("Pollution"), MP_POL(x, y));
289 
290 }
291