1 /* ---------------------------------------------------------------------- *
2 * simulate.c
3 * This file is part of lincity.
4 * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5 * ---------------------------------------------------------------------- */
6
7 #include "lcconfig.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "lcstring.h"
11 #include <sys/types.h>
12 #include <fcntl.h>
13 #if defined (WIN32)
14 #include <winsock.h>
15 #include <io.h>
16 #include <direct.h>
17 #include <process.h>
18 #endif
19
20 #include <ctype.h>
21 #include "common.h"
22 #ifdef LC_X11
23 #include <X11/cursorfont.h>
24 #endif
25 #include "lctypes.h"
26 #include "lin-city.h"
27 #include "cliglobs.h"
28 #include "engglobs.h"
29 #include "screen.h"
30 #include "power.h"
31 #include "stats.h"
32 #include "pbar.h"
33 #include "module_buttons.h"
34
35 /* ---------------------------------------------------------------------- *
36 * Private Fn Prototypes
37 * ---------------------------------------------------------------------- */
38 static void do_periodic_events (void);
39 static void end_of_month_update (void);
40 static void start_of_year_update (void);
41 static void end_of_year_update (void);
42 static void random_start (int* originx, int* originy);
43 static void simulate_mappoints (void);
44 static void quick_start_add (int x, int y, short type, int size);
45
46 /* ---------------------------------------------------------------------- *
47 * Public Functions
48 * ---------------------------------------------------------------------- */
49 void
do_time_step(void)50 do_time_step (void)
51 {
52 /* Increment game time */
53 total_time++;
54 #ifdef DEBUG_ENGINE
55 printf ("In do_time_step (%d)\n", total_time);
56 #endif
57
58 /* Initialize daily accumulators */
59 init_daily();
60
61 /* Initialize monthly accumulators */
62 if (total_time % NUMOF_DAYS_IN_MONTH == 0) {
63 init_monthly();
64 }
65
66 /* Initialize yearly accumulators */
67 if ((total_time % NUMOF_DAYS_IN_YEAR) == 0) {
68 init_yearly();
69 }
70
71 /* Clear the power grid */
72 power_time_step ();
73
74 /* Run through simulation equations for each farm, residence, etc. */
75 simulate_mappoints ();
76
77 /* Now do the stuff that happens once a year, once a month, etc. */
78 do_periodic_events ();
79 }
80
81 void
clear_mappoint(short fill,int x,int y)82 clear_mappoint (short fill, int x, int y)
83 {
84 MP_TYPE(x,y) = fill;
85 MP_GROUP(x,y) = get_group_of_type(fill);
86 if (MP_GROUP(x,y) < 0) MP_GROUP(x,y) = GROUP_BARE;
87 MP_INFO(x,y).population = 0;
88 MP_INFO(x,y).flags = 0;
89 MP_INFO(x,y).int_1 = 0;
90 MP_INFO(x,y).int_2 = 0;
91 MP_INFO(x,y).int_3 = 0;
92 MP_INFO(x,y).int_4 = 0;
93 MP_INFO(x,y).int_5 = 0;
94 MP_INFO(x,y).int_6 = 0;
95 MP_INFO(x,y).int_7 = 0;
96 }
97
98 static void
simulate_mappoints(void)99 simulate_mappoints (void)
100 {
101 int xx, yy;
102 shuffle_mappoint_array ();
103 for (yy = 0; yy < WORLD_SIDE_LEN; yy++) {
104 /* indirection to rand array to stop lots of linear effects */
105 int y = mappoint_array_y[yy];
106 for (xx = 0; xx < WORLD_SIDE_LEN; xx++) {
107 int x = mappoint_array_x[xx];
108 short grp = MP_GROUP(x,y);
109 if (grp == GROUP_USED || grp == GROUP_BARE)
110 continue;
111 switch (grp) {
112 case GROUP_TRACK:
113 do_track (x, y);
114 break;
115 case GROUP_RAIL:
116 do_rail (x, y);
117 break;
118 case GROUP_ROAD:
119 do_road (x, y);
120 break;
121 case GROUP_ORGANIC_FARM:
122 do_organic_farm (x, y);
123 break;
124 case GROUP_MARKET:
125 do_market (x, y);
126 break;
127 case GROUP_RESIDENCE_LL:
128 do_residence (x, y);
129 break;
130 case GROUP_RESIDENCE_ML:
131 do_residence (x, y);
132 break;
133 case GROUP_RESIDENCE_HL:
134 do_residence (x, y);
135 break;
136 case GROUP_RESIDENCE_LH:
137 do_residence (x, y);
138 break;
139 case GROUP_RESIDENCE_MH:
140 do_residence (x, y);
141 break;
142 case GROUP_RESIDENCE_HH:
143 do_residence (x, y);
144 break;
145 case GROUP_POWER_LINE:
146 do_power_line (x, y);
147 break;
148 case GROUP_SOLAR_POWER:
149 do_power_source (x, y);
150 break;
151 case GROUP_SUBSTATION:
152 do_power_substation (x, y);
153 break;
154 case GROUP_COALMINE:
155 do_coalmine (x, y);
156 break;
157 case GROUP_COAL_POWER:
158 do_power_source_coal (x, y);
159 break;
160 case GROUP_INDUSTRY_L:
161 do_industry_l (x, y);
162 break;
163 case GROUP_INDUSTRY_H:
164 do_industry_h (x, y);
165 break;
166 case GROUP_COMMUNE:
167 do_commune (x, y);
168 break;
169 case GROUP_OREMINE:
170 do_oremine (x, y);
171 break;
172 case GROUP_PORT:
173 do_port (x, y);
174 break;
175 case GROUP_TIP:
176 do_tip (x, y);
177 break;
178 case GROUP_PARKLAND:
179 do_parkland (x, y);
180 break;
181 case GROUP_UNIVERSITY:
182 do_university (x, y);
183 break;
184 case GROUP_RECYCLE:
185 do_recycle (x, y);
186 break;
187 case GROUP_HEALTH:
188 do_health_centre (x, y);
189 break;
190 case GROUP_ROCKET:
191 do_rocket_pad (x, y);
192 break;
193 case GROUP_WINDMILL:
194 do_windmill (x, y);
195 break;
196 case GROUP_MONUMENT:
197 do_monument (x, y);
198 break;
199 case GROUP_SCHOOL:
200 do_school (x, y);
201 break;
202 case GROUP_BLACKSMITH:
203 do_blacksmith (x, y);
204 break;
205 case GROUP_MILL:
206 do_mill (x, y);
207 break;
208 case GROUP_POTTERY:
209 do_pottery (x, y);
210 break;
211 case GROUP_FIRESTATION:
212 do_firestation (x, y);
213 break;
214 case GROUP_CRICKET:
215 do_cricket (x, y);
216 break;
217 case GROUP_FIRE:
218 do_fire (x, y);
219 break;
220 case GROUP_SHANTY:
221 do_shanty (x, y);
222 break;
223 }
224 }
225 }
226 }
227
228 /* ---------------------------------------------------------------------- *
229 * Private Functions
230 * ---------------------------------------------------------------------- */
231 static void
do_periodic_events(void)232 do_periodic_events (void)
233 {
234 add_daily_to_monthly();
235
236
237 if ((total_time % NUMOF_DAYS_IN_YEAR) == 0) {
238 start_of_year_update ();
239 }
240 if ((total_time % DAYS_BETWEEN_FIRES) == 9
241 && tech_level > (GROUP_FIRESTATION_TECH * MAX_TECH_LEVEL / 1000)) {
242 do_random_fire (-1, -1, 1);
243 }
244 if ((total_time % DAYS_BETWEEN_COVER) == 75) {
245 clear_fire_health_and_cricket_cover ();
246 do_fire_health_and_cricket_cover ();
247 }
248 if ((total_time % DAYS_BETWEEN_SHANTY) == 85
249 && tech_level > (GROUP_HEALTH_TECH * MAX_TECH_LEVEL / 1000)) {
250 update_shanty ();
251 }
252 if (total_time % NUMOF_DAYS_IN_MONTH == (NUMOF_DAYS_IN_MONTH - 1)) {
253 end_of_month_update ();
254 }
255 if (total_time % NUMOF_DAYS_IN_YEAR == (NUMOF_DAYS_IN_YEAR - 1)) {
256 end_of_year_update ();
257 }
258 if ((total_time % DAYS_PER_POLLUTION) == 3) {
259 do_pollution ();
260 }
261 }
262
263
264 static void
end_of_month_update(void)265 end_of_month_update (void)
266 {
267 /* GCS FIX -- seems to be a bit of engine code embedded in
268 do_monthgraph(), such as coal_made, coal_used, etc.
269 Check it out soon... */
270 housed_population = (tpopulation / NUMOF_DAYS_IN_MONTH);
271 if ((housed_population + people_pool) > max_pop_ever)
272 max_pop_ever = housed_population + people_pool;
273
274 if (people_pool > 100) {
275 if (rand () % 1000 < people_pool)
276 people_pool -= 10;
277 }
278 if (people_pool < 0)
279 people_pool = 0;
280
281 if (tech_level > TECH_LEVEL_LOSS_START)
282 {
283 tech_level-=tech_level*(1./TECH_LEVEL_LOSS)
284 *(1+(tpopulation
285 *(1./NUMOF_DAYS_IN_MONTH/120
286 /(TECH_LEVEL_LOSS-200))));
287
288 }
289 else
290 tech_level += TECH_LEVEL_UNAIDED;
291 /* we can go over 100, but it's even more difficult */
292 if (tech_level > MAX_TECH_LEVEL)
293 tech_level-=(tech_level-MAX_TECH_LEVEL)
294 *(1./TECH_LEVEL_LOSS)
295 *(1+(tpopulation
296 *(1./NUMOF_DAYS_IN_MONTH/120
297 /(TECH_LEVEL_LOSS-100))));
298
299 if (highest_tech_level < tech_level)
300 highest_tech_level = tech_level;
301
302 deaths_cost += unnat_deaths * UNNAT_DEATHS_COST;
303
304 }
305
306
307 static void
start_of_year_update(void)308 start_of_year_update (void)
309 {
310 int u;
311
312 sustainability_test ();
313
314 pollution_deaths_history
315 -= pollution_deaths_history / 100.0;
316 starve_deaths_history
317 -= starve_deaths_history / 100.0;
318 unemployed_history
319 -= unemployed_history / 100.0;
320 u = count_groups (GROUP_UNIVERSITY);
321 if (u > 0) {
322 university_intake_rate = (count_groups (GROUP_SCHOOL) * 20) / u;
323 if (university_intake_rate > 100)
324 university_intake_rate = 100;
325 } else {
326 university_intake_rate = 50;
327 }
328
329 map_power_grid();
330 }
331
332
333 static void
end_of_year_update(void)334 end_of_year_update (void)
335 {
336 income_tax = (income_tax * income_tax_rate) / 100;
337 ly_income_tax = income_tax;
338 total_money += income_tax;
339
340 coal_tax = (coal_tax * coal_tax_rate) / 100;
341 ly_coal_tax = coal_tax;
342 total_money += coal_tax;
343
344 goods_tax = (goods_tax * goods_tax_rate) / 100;
345 goods_tax += (int) ((float) (goods_tax * goods_tax_rate)
346 * (float) tech_level / 2000000.0);
347 ly_goods_tax = goods_tax;
348 total_money += goods_tax;
349
350 /* The price of exports on the world market drops as you export more.
351 The exporters have to discount there wares, therefore the
352 tax take is less.
353 */
354 if (export_tax > ex_tax_dis[0])
355 {
356 int discount, disi;
357 discount = 0;
358 for (disi = 0; disi < NUMOF_DISCOUNT_TRIGGERS
359 && export_tax > ex_tax_dis[disi]; disi++)
360 discount += (export_tax - ex_tax_dis[disi]) / 10;
361 export_tax -= discount;
362 }
363 ly_export_tax = export_tax;
364 total_money += export_tax;
365
366 ly_university_cost = university_cost;
367 ly_recycle_cost = recycle_cost;
368 ly_deaths_cost = deaths_cost;
369 ly_health_cost = (health_cost * (tech_level / 10000)
370 * HEALTH_RUNNING_COST_MUL) / (MAX_TECH_LEVEL / 10000);
371 ly_rocket_pad_cost = rocket_pad_cost;
372 ly_school_cost = school_cost;
373 ly_windmill_cost = windmill_cost;
374 ly_fire_cost = (fire_cost * (tech_level / 10000)
375 * FIRESTATION_RUNNING_COST_MUL) / (MAX_TECH_LEVEL / 10000);
376 ly_cricket_cost = cricket_cost;
377 if (total_money < 0)
378 {
379 ly_interest = ((-total_money / 1000) * INTEREST_RATE);
380 if (ly_interest > 1000000)
381 ly_interest = 1000000;
382 }
383 else
384 ly_interest = 0;
385
386 other_cost = university_cost + recycle_cost + deaths_cost
387 + ly_health_cost + rocket_pad_cost + school_cost
388 + ly_interest + windmill_cost + ly_fire_cost
389 + ly_cricket_cost;
390 ly_other_cost = other_cost;
391 total_money -= other_cost;
392
393 unemployment_cost = (unemployment_cost * dole_rate) / 100;
394 ly_unemployment_cost = unemployment_cost;
395 total_money -= unemployment_cost;
396
397 transport_cost = (transport_cost * transport_cost_rate) / 100;
398 ly_transport_cost = transport_cost;
399 total_money -= transport_cost;
400
401 import_cost = (import_cost * import_cost_rate) / 100;
402 ly_import_cost = import_cost;
403 total_money -= import_cost;
404
405 if (total_money > 2000000000)
406 total_money = 2000000000;
407 else if (total_money < -2000000000)
408 total_money = -2000000000;
409
410 print_total_money ();
411 }
412
413
414 static void
clear_game(void)415 clear_game (void)
416 {
417 int x, y;
418 for (y = 0; y < WORLD_SIDE_LEN; y++) {
419 for (x = 0; x < WORLD_SIDE_LEN; x++) {
420 clear_mappoint (CST_GREEN, x, y);
421 MP_POL(x,y) = 0;
422 }
423 }
424 total_time = 0;
425 coal_survey_done = 0;
426 numof_shanties = 0;
427 numof_communes = 0;
428 numof_substations = 0;
429 numof_health_centres = 0;
430 numof_markets = 0;
431 max_pop_ever = 0;
432 total_evacuated = 0;
433 total_births = 0;
434 total_money = 0;
435 tech_level = 0;
436 init_inventory();
437 update_avail_modules(0);
438 }
439
440 void
new_city(int * originx,int * originy,int random_village)441 new_city (int* originx, int* originy, int random_village)
442 {
443 clear_game ();
444 coal_reserve_setup ();
445 setup_river ();
446 ore_reserve_setup ();
447 init_pbars ();
448
449 /* Initial population is 100 for empty board or 200
450 for random village (100 are housed). */
451 people_pool = 100;
452
453 if (random_village != 0) {
454 random_start (originx, originy);
455 update_pbar(PPOP,200,1); /* So pbars don't flash */
456 } else {
457 *originx = *originy = WORLD_SIDE_LEN/2 ;
458 update_pbar(PPOP,100,1);
459 }
460 connect_transport (1,1,WORLD_SIDE_LEN-2,WORLD_SIDE_LEN-2);
461 refresh_pbars ();
462 }
463
464 void
coal_reserve_setup(void)465 coal_reserve_setup (void)
466 {
467 int i, j, x, y, xx, yy;
468 for (i = 0; i < NUMOF_COAL_RESERVES / 5; i++)
469 {
470 x = (rand () % (WORLD_SIDE_LEN - 12)) + 6;
471 y = (rand () % (WORLD_SIDE_LEN - 10)) + 6;
472 do
473 {
474 xx = (rand () % 3) - 1;
475 yy = (rand () % 3) - 1;
476 }
477 while (xx == 0 && yy == 0);
478 for (j = 0; j < 5; j++)
479 {
480 MP_INFO(x,y).coal_reserve
481 += rand () % COAL_RESERVE_SIZE;
482 x += xx;
483 y += yy;
484 }
485 }
486 }
487
488 void
ore_reserve_setup(void)489 ore_reserve_setup (void)
490 {
491 int x, y;
492 for (y = 0; y < WORLD_SIDE_LEN; y++)
493 for (x = 0; x < WORLD_SIDE_LEN; x++)
494 MP_INFO(x,y).ore_reserve = ORE_RESERVE;
495 }
496
497 void
setup_river(void)498 setup_river (void)
499 {
500 int x, y, i, j;
501 x = WORLD_SIDE_LEN / 2;
502 y = WORLD_SIDE_LEN - 1;
503 i = (rand () % 12) + 6;
504 for (j = 0; j < i; j++) {
505 x += (rand () % 3) - 1;
506 MP_TYPE(x,y) = CST_WATER;
507 MP_GROUP(x,y) = GROUP_WATER;
508 MP_INFO(x,y).flags |= FLAG_IS_RIVER;
509 MP_TYPE(x+1,y) = CST_WATER;
510 MP_GROUP(x+1,y) = GROUP_WATER;
511 MP_INFO(x+1,y).flags |= FLAG_IS_RIVER;
512 MP_TYPE(x-1,y) = CST_WATER;
513 MP_GROUP(x-1,y) = GROUP_WATER;
514 MP_INFO(x-1,y).flags |= FLAG_IS_RIVER;
515 y--;
516 }
517 MP_TYPE(x,y) = CST_WATER;
518 MP_GROUP(x,y) = GROUP_WATER;
519 MP_INFO(x,y).flags |= FLAG_IS_RIVER;
520 MP_TYPE(x+1,y) = CST_WATER;
521 MP_GROUP(x+1,y) = GROUP_WATER;
522 MP_INFO(x+1,y).flags |= FLAG_IS_RIVER;
523 MP_TYPE(x-1,y) = CST_WATER;
524 MP_GROUP(x-1,y) = GROUP_WATER;
525 MP_INFO(x-1,y).flags |= FLAG_IS_RIVER;
526
527 setup_river2 (x - 1, y, -1); /* left tributary */
528 setup_river2 (x + 1, y, 1); /* right tributary */
529 }
530
531 void
setup_river2(int x,int y,int d)532 setup_river2 (int x, int y, int d)
533 {
534 int i, j, r;
535 i = (rand () % 55) + 15;
536 for (j = 0; j < i; j++)
537 {
538 r = (rand () % 3) - 1 + (d * (rand () % 3));
539 if (r < -1)
540 r = -1;
541 else if (r > 1)
542 r = 1;
543 x += r;
544 if (MP_TYPE(x+(d+d),y) != 0
545 || MP_TYPE(x+(d+d+d),y) != 0)
546 return;
547 if (x > 5 && x < WORLD_SIDE_LEN - 5)
548 {
549 MP_TYPE(x,y) = CST_WATER;
550 MP_GROUP(x,y) = GROUP_WATER;
551 MP_INFO(x,y).flags |= FLAG_IS_RIVER;
552 MP_TYPE(x + d,y) = CST_WATER;
553 MP_GROUP(x+d,y) = GROUP_WATER;
554 MP_INFO(x+d,y).flags |= FLAG_IS_RIVER;
555 }
556 if (--y < 10 || x < 5 || x > WORLD_SIDE_LEN - 5)
557 break;
558 }
559 if (y > 20)
560 {
561 if (x > 5 && x < WORLD_SIDE_LEN - 5)
562 setup_river2 (x, y, -1);
563 if (x > 5 && x < WORLD_SIDE_LEN - 5)
564 setup_river2 (x, y, 1);
565 }
566 }
567
568 int
count_groups(int g)569 count_groups (int g)
570 {
571 int x, y, i;
572 i = 0;
573 for (y = 0; y < WORLD_SIDE_LEN; y++)
574 for (x = 0; x < WORLD_SIDE_LEN; x++)
575 if (MP_GROUP(x,y) == g)
576 i++;
577 return (i);
578 }
579
580 void
count_all_groups(int * group_count)581 count_all_groups (int* group_count)
582 {
583 int x, y;
584 unsigned short t, g;
585 for (x = 0; x < NUM_OF_GROUPS; x++)
586 group_count[x] = 0;
587 for (y = 0; y < WORLD_SIDE_LEN; y++) {
588 for (x = 0; x < WORLD_SIDE_LEN; x++) {
589 t = MP_TYPE(x,y);
590 if (t != CST_USED && t != CST_GREEN) {
591 g = get_group_of_type(t);
592 group_count[g]++;
593 }
594 }
595 }
596 }
597
598 static void
random_start(int * originx,int * originy)599 random_start (int* originx, int* originy)
600 {
601 int x, y, xx, yy, flag, watchdog;
602
603 /* first find a place that has some water. */
604 watchdog = 90; /* if too many tries, random placement. */
605 do {
606 do {
607 xx = rand () % (WORLD_SIDE_LEN - 25);
608 yy = rand () % (WORLD_SIDE_LEN - 25);
609 flag = 0;
610 for (y = yy + 2; y < yy + 23; y++)
611 for (x = xx + 2; x < xx + 23; x++)
612 if (MP_GROUP(x,y) == GROUP_WATER)
613 {
614 flag = 1;
615 x = xx + 23; /* break out of loop */
616 y = yy + 23; /* break out of loop */
617 }
618 } while (flag == 0 || (--watchdog) < 1);
619 for (y = yy + 4; y < yy + 22; y++)
620 for (x = xx + 4; x < xx + 22; x++)
621 if (MP_GROUP(x,y) != GROUP_BARE) {
622 flag = 0;
623 x = xx + 22; /* break out of loop */
624 y = yy + 22; /* break out of loop */
625 }
626 } while (flag == 0 || (--watchdog) < 1);
627
628 /* These are going to be the main_screen_origin? vars */
629 *originx = xx;
630 *originy = yy;
631
632 /* Draw the start scene. */
633 quick_start_add (xx + 5, yy + 5, CST_FARM_O0, 4);
634 quick_start_add (xx + 9, yy + 6, CST_RESIDENCE_ML, 3);
635 MP_INFO(xx + 9,yy + 6).population = 50;
636 MP_INFO(xx + 9,yy + 6).flags |= (FLAG_FED + FLAG_EMPLOYED);
637 quick_start_add (xx + 7, yy + 9, CST_MARKET_EMPTY, 2);
638 marketx[numof_markets] = xx + 7;
639 markety[numof_markets] = yy + 9;
640 numof_markets++;
641 /* Bootstap markets with some stuff. */
642 MP_INFO(xx + 7,yy + 9).int_1 = 2000;
643 MP_INFO(xx + 7,yy + 9).int_2 = 10000;
644 MP_INFO(xx + 7,yy + 9).int_3 = 100;
645 MP_INFO(xx + 7,yy + 9).int_5 = 10000;
646 MP_INFO(xx + 7,yy + 9).flags
647 |= (FLAG_MB_FOOD + FLAG_MS_FOOD + FLAG_MB_JOBS
648 + FLAG_MS_JOBS + FLAG_MB_COAL + FLAG_MS_COAL + FLAG_MB_ORE
649 + FLAG_MS_ORE + FLAG_MB_GOODS + FLAG_MS_GOODS + FLAG_MB_STEEL
650 + FLAG_MS_STEEL);
651
652
653 quick_start_add (xx + 14, yy + 6, CST_RESIDENCE_ML, 3);
654 MP_INFO(xx + 14,yy + 6).population = 50;
655 MP_INFO(xx + 14,yy + 6).flags |= (FLAG_FED + FLAG_EMPLOYED);
656 quick_start_add (xx + 17, yy + 5, CST_FARM_O0, 4);
657 quick_start_add (xx + 17, yy + 9, CST_MARKET_EMPTY, 2);
658 marketx[numof_markets] = xx + 17;
659 markety[numof_markets] = yy + 9;
660 numof_markets++;
661 MP_INFO(xx + 17,yy + 9).int_1 = 2000;
662 MP_INFO(xx + 17,yy + 9).int_2 = 8000;
663 MP_INFO(xx + 17,yy + 9).flags
664 |= (FLAG_MB_FOOD + FLAG_MS_FOOD + FLAG_MB_JOBS
665 + FLAG_MS_JOBS + FLAG_MB_COAL + FLAG_MS_COAL + FLAG_MB_ORE
666 + FLAG_MS_ORE + FLAG_MB_GOODS + FLAG_MS_GOODS + FLAG_MB_STEEL
667 + FLAG_MS_STEEL);
668
669 for (x = 5; x < 19; x++)
670 {
671 quick_start_add (xx + x, yy + 11, CST_TRACK_LR, 1);
672 MP_INFO(xx + x,yy + 11).flags |= FLAG_IS_TRANSPORT;
673 }
674 for (y = 12; y < 18; y++)
675 {
676 quick_start_add (xx + 5, yy + y, CST_TRACK_LR, 1);
677 MP_INFO(xx + 5,yy + y).flags |= FLAG_IS_TRANSPORT;
678 }
679 quick_start_add (xx + 6, yy + 12, CST_COMMUNE_1, 4);
680 quick_start_add (xx + 6, yy + 17, CST_COMMUNE_1, 4);
681 quick_start_add (xx + 11, yy + 12, CST_COMMUNE_1, 4);
682 quick_start_add (xx + 11, yy + 17, CST_COMMUNE_1, 4);
683 quick_start_add (xx + 16, yy + 12, CST_COMMUNE_1, 4);
684 quick_start_add (xx + 16, yy + 17, CST_COMMUNE_1, 4);
685 for (x = 6; x < 17; x++)
686 {
687 quick_start_add (xx + x, yy + 16, CST_TRACK_LR, 1);
688 MP_INFO(xx + x,yy + 16).flags |= FLAG_IS_TRANSPORT;
689 }
690 for (y = 12; y < 16; y++)
691 {
692 quick_start_add (xx + 10, yy + y, CST_TRACK_LR, 1);
693 MP_INFO(xx + 10,yy + y).flags |= FLAG_IS_TRANSPORT;
694 quick_start_add (xx + 15, yy + y, CST_TRACK_LR, 1);
695 MP_INFO(xx + 15,yy + y).flags |= FLAG_IS_TRANSPORT;
696 }
697 quick_start_add (xx + 10, yy + 17, CST_TRACK_LR, 1);
698 MP_INFO(xx + 10,yy + 17).flags |= FLAG_IS_TRANSPORT;
699 quick_start_add (xx + 15, yy + 17, CST_TRACK_LR, 1);
700 MP_INFO(xx + 15,yy + 17).flags |= FLAG_IS_TRANSPORT;
701
702 quick_start_add (xx + 9, yy + 9, CST_POTTERY_0, 2);
703 }
704
705 /* XXX: WCK: What is up with this? Why not just use set_mappoint?! */
706 static void
quick_start_add(int x,int y,short type,int size)707 quick_start_add (int x, int y, short type, int size)
708 {
709 int xx, yy;
710 if (size == 1) {
711 MP_TYPE(x,y) = type;
712 MP_GROUP(x,y) = get_group_of_type(type);
713 return;
714 }
715 for (yy = 0; yy < size; yy++) {
716 for (xx = 0; xx < size; xx++) {
717 if (xx == 0 && yy == 0)
718 continue;
719 set_mappoint_used (x, y, x + xx, y + yy);
720 }
721 }
722 MP_TYPE(x,y) = type;
723 MP_GROUP(x,y) = get_group_of_type(type);
724 }
725
726 void
sustainability_test(void)727 sustainability_test (void)
728 {
729 int i;
730 if (sust_dig_ore_coal_tip_flag == 0)
731 {
732 sust_dig_ore_coal_tip_flag = 1;
733 sust_dig_ore_coal_count = 0;
734 }
735 else
736 sust_dig_ore_coal_count++;
737
738 if (sust_port_flag == 0)
739 {
740 sust_port_flag = 1;
741 sust_port_count = 0;
742 }
743 else
744 sust_port_count++;
745
746 /* Money must be going up or the same. (ie can't build.) */
747 if (sust_old_money > total_money)
748 sust_old_money_count = 0;
749 else
750 sust_old_money_count++;
751 sust_old_money = total_money;
752
753 /* population must be withing 2% of when it started. */
754 i = (housed_population + people_pool) - sust_old_population;
755 if (abs (i) > (sust_old_population / 40) /* 2.5% */
756 || (housed_population + people_pool) < SUST_MIN_POPULATION)
757 {
758 sust_old_population = (housed_population + people_pool);
759 sust_old_population_count = 0;
760 }
761 else
762 sust_old_population_count++;
763
764 /* tech level must be going up or not fall more than 0.5% from it's
765 highest during the sus count
766 */
767 i = tech_level - sust_old_tech;
768 if (i < 0 || tech_level < SUST_MIN_TECH_LEVEL)
769 {
770 i = -i;
771 if ((i > sust_old_tech / 100) || tech_level < SUST_MIN_TECH_LEVEL)
772 {
773 sust_old_tech_count = 0;
774 sust_old_tech = tech_level;
775 }
776 else
777 sust_old_tech_count++;
778 }
779 else
780 {
781 sust_old_tech_count++;
782 sust_old_tech = tech_level;
783 }
784
785 /* check fire cover only every three years */
786 if (total_time % (NUMOF_DAYS_IN_YEAR * 3) == 0)
787 {
788 if (sust_fire_cover () != 0)
789 sust_fire_count += 3;
790 else
791 sust_fire_count = 0;
792
793 }
794 }
795
796 int
sust_fire_cover(void)797 sust_fire_cover (void)
798 {
799 int x, y;
800 for (x = 0; x < WORLD_SIDE_LEN; x++)
801 for (y = 0; y < WORLD_SIDE_LEN; y++)
802 {
803 if (MP_GROUP(x,y) == GROUP_BARE
804 || MP_TYPE(x,y) == CST_USED
805 || MP_GROUP(x,y) == GROUP_WATER
806 || MP_GROUP(x,y) == GROUP_POWER_LINE
807 || MP_GROUP(x,y) == GROUP_OREMINE
808 || MP_GROUP(x,y) == GROUP_ROCKET
809 || MP_GROUP(x,y) == GROUP_MONUMENT
810 || MP_GROUP(x,y) == GROUP_BURNT)
811 ; /* do nothing */
812
813 else if ((MP_INFO(x,y).flags & FLAG_FIRE_COVER) == 0)
814 return (0);
815 }
816 return (1);
817 }
818
819 void
debug_mappoints(void)820 debug_mappoints (void)
821 {
822 int x, y;
823 for (x = 0; x < WORLD_SIDE_LEN; x++) {
824 for (y = 0; y < WORLD_SIDE_LEN; y++) {
825 if ((MP_TYPE(x,y) < 0) || (MP_TYPE(x,y) > 400)) {
826 printf ("Error in mappoint %d %d (%d)\n", x, y, MP_TYPE(x,y));
827 exit(-1);
828 }
829 }
830 }
831 }
832
833 void
initialize_tax_rates(void)834 initialize_tax_rates (void)
835 {
836 income_tax_rate = INCOME_TAX_RATE;
837 coal_tax_rate = COAL_TAX_RATE;
838 goods_tax_rate = GOODS_TAX_RATE;
839 dole_rate = DOLE_RATE;
840 transport_cost_rate = TRANSPORT_COST_RATE;
841 import_cost_rate = IM_PORT_COST_RATE;
842 }
843
844