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