1 /* ---------------------------------------------------------------------- *
2 * mps.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 #include "lcconfig.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <math.h>
10 #include "lcstring.h"
11 #include "common.h"
12 #include "lctypes.h"
13 #include "lin-city.h"
14 #include "mps.h"
15 #include "engglobs.h"
16 #include "mouse.h"
17 #include "screen.h"
18 #include "power.h"
19 #include "engine.h"
20 #include "lclib.h"
21 #include "lcintl.h"
22 #include "stats.h"
23 #include <modules.h>
24 #include <mouse.h>
25 #include <lclib.h>
26
27 char mps_info[MAPPOINT_STATS_LINES][MPS_INFO_CHARS];
28 int mps_global_style;
29
30 static int mps_style;
31
32 static int mps_x;
33 static int mps_y;
34
35 static Mouse_Handle * mps_handle;
36
37
38 /*
39 * ----------------------------------------------------------------------
40 * * New, simplified mps routines. All drawing is offloaded to
41 * mps_refresh and mps_redraw, with the various mps_module routines -
42 * called from mps_update - merely updating an array of strings:
43 * mps_info (see above)
44 * ----------------------------------------------------------------------
45 * */
46
47 void
mps_handler(int x,int y,int button)48 mps_handler(int x, int y, int button)
49 {
50 if (button == LC_MOUSE_LEFTBUTTON) {
51 if (mps_style == MPS_GLOBAL) {
52 mps_global_advance();
53 } else {
54 mps_set(0,0,MPS_GLOBAL);
55 }
56 } else if (button == LC_MOUSE_RIGHTBUTTON) {
57 /* XXX: Pop help here, depending on selected style */
58 }
59 }
60
61 /* mps_init(): Initialize mps vars and mouse handles */
62
63 void
mps_init()64 mps_init()
65 {
66 mps_style = MPS_GLOBAL;
67 mps_global_style = MPS_GLOBAL_FINANCE;
68
69 mps_x = 0;
70 mps_y = 0;
71
72 mps_handle = mouse_register(&scr.mappoint_stats,&mps_handler);
73 }
74
75
76 /* mps_set(): Main entry to mps system. Sets mps to display status
77 for a square or global information. If we are setting mps to
78 the same square it was set for, return 1, otherwise 0.
79 */
80
81 int
mps_set(int x,int y,int style)82 mps_set(int x, int y, int style)
83 {
84 int same_square = 0;
85 mps_style = style;
86 switch(style) {
87 case MPS_MAP:
88 case MPS_ENV:
89 if (mps_x == x && mps_y == y) {
90 same_square = 1;
91 }
92 mps_x = x;
93 mps_y = y;
94 break;
95 default:
96 mps_x = 0;
97 mps_y = 0;
98 }
99
100 mps_update();
101 mps_refresh();
102 return same_square;
103 }
104
105
106 void
mps_redraw(void)107 mps_redraw(void)
108 {
109 Rect* mps = &scr.mappoint_stats;
110
111 draw_small_bezel (mps->x, mps->y, mps->w, mps->h, yellow(0));
112 mps_refresh();
113 }
114
115 void
mps_refresh(void)116 mps_refresh(void)
117 {
118 int i;
119
120 Rect * mps = &scr.mappoint_stats;
121
122 Fgl_fillbox (mps->x, mps->y, mps->w + 1, mps->h + 1, 14);
123 Fgl_setfontcolors (14, TEXT_FG_COLOUR);
124
125 for (i = 0; i < MAPPOINT_STATS_LINES; i++) {
126 Fgl_write (mps->x + 4, mps->y + (i * 8) + 4, mps_info[i]);
127 }
128
129 Fgl_setfontcolors (TEXT_BG_COLOUR, TEXT_FG_COLOUR);
130
131
132 }
133
134 void
mps_update(void)135 mps_update(void)
136 {
137 int i;
138
139 for (i = 0; i < MAPPOINT_STATS_LINES; i++) {
140 strcpy(mps_info[i],"");
141 }
142
143 switch (mps_style) {
144 case MPS_MAP:
145 {
146 switch(MP_GROUP(mps_x, mps_y)) {
147 case (GROUP_BLACKSMITH):
148 mps_blacksmith (mps_x, mps_y);
149 break;
150 case (GROUP_COALMINE):
151 mps_coalmine (mps_x, mps_y);
152 break;
153 case GROUP_COAL_POWER:
154 mps_coal_power (mps_x, mps_y);
155 break;
156 case (GROUP_COMMUNE):
157 mps_commune (mps_x, mps_y);
158 break;
159 case (GROUP_CRICKET):
160 mps_cricket (mps_x, mps_y);
161 break;
162 case (GROUP_FIRESTATION):
163 mps_firestation (mps_x, mps_y);
164 break;
165 case (GROUP_HEALTH):
166 mps_health_centre (mps_x, mps_y);
167 break;
168 case (GROUP_INDUSTRY_H):
169 mps_heavy_industry (mps_x, mps_y);
170 break;
171 case (GROUP_INDUSTRY_L):
172 mps_light_industry (mps_x, mps_y);
173 break;
174 case (GROUP_MILL):
175 mps_mill (mps_x, mps_y);
176 break;
177 case (GROUP_MONUMENT):
178 mps_monument (mps_x, mps_y);
179 break;
180 case (GROUP_OREMINE):
181 mps_oremine (mps_x, mps_y);
182 break;
183 case GROUP_ORGANIC_FARM:
184 mps_organic_farm(mps_x, mps_y);
185 break;
186 case (GROUP_PORT):
187 mps_port (mps_x, mps_y);
188 break;
189 case (GROUP_POTTERY):
190 mps_pottery (mps_x, mps_y);
191 break;
192 case GROUP_POWER_LINE:
193 mps_power_line (mps_x, mps_y);
194 break;
195 case (GROUP_RAIL):
196 mps_rail (mps_x, mps_y);
197 break;
198 case (GROUP_RECYCLE):
199 mps_recycle (mps_x, mps_y);
200 break;
201 case GROUP_RESIDENCE_LL:
202 case GROUP_RESIDENCE_ML:
203 case GROUP_RESIDENCE_HL:
204 case GROUP_RESIDENCE_LH:
205 case GROUP_RESIDENCE_MH:
206 case GROUP_RESIDENCE_HH:
207 mps_residence(mps_x, mps_y);
208 break;
209 case (GROUP_ROAD):
210 mps_road (mps_x, mps_y);
211 break;
212 case (GROUP_ROCKET):
213 mps_rocket (mps_x, mps_y);
214 break;
215 case (GROUP_SCHOOL):
216 mps_school (mps_x, mps_y);
217 break;
218 case GROUP_SOLAR_POWER:
219 mps_solar_power (mps_x, mps_y);
220 break;
221 case (GROUP_SUBSTATION):
222 mps_substation (mps_x, mps_y);
223 break;
224 case (GROUP_TIP):
225 mps_tip (mps_x, mps_y);
226 break;
227 case (GROUP_TRACK):
228 mps_track(mps_x, mps_y);
229 break;
230 case (GROUP_MARKET):
231 mps_market (mps_x, mps_y);
232 break;
233 case (GROUP_UNIVERSITY):
234 mps_university (mps_x, mps_y);
235 break;
236 case (GROUP_WATER):
237 mps_water (mps_x, mps_y);
238 break;
239 case (GROUP_WINDMILL):
240 mps_windmill (mps_x, mps_y);
241 break;
242 default:
243 printf("MPS unimplemented for that module\n");
244 }
245 }
246 break;
247 case MPS_ENV:
248 mps_right (mps_x, mps_y);
249 break;
250 case MPS_GLOBAL:
251 {
252 switch (mps_global_style) {
253 case MPS_GLOBAL_FINANCE:
254 mps_global_finance();
255 break;
256 case MPS_GLOBAL_OTHER_COSTS:
257 mps_global_other_costs();
258 break;
259 case MPS_GLOBAL_HOUSING:
260 mps_global_housing();
261 break;
262 default:
263 printf("MPS unimplemented for global display\n");
264 break;
265 }
266 }
267 break;
268 }
269
270 mps_refresh();
271 }
272
273 /* Cycle through the various global styles, but only update and display
274 if global info display is active */
275
276 void
mps_global_advance(void)277 mps_global_advance(void)
278 {
279 mps_global_style++;
280 mps_global_style %= MPS_GLOBAL_STYLES;
281
282 if (mps_style == MPS_GLOBAL) {
283 mps_update();
284 }
285 }
286
287 /* MPS String storage routines.
288 These handle the tedium of formatting
289 strings for mps display. Single argument forms center that
290 argument. Double arg forms offset them. Triple arg forms divide
291 the space into three columns.
292
293 */
294
295 void
mps_store_title(int i,char * t)296 mps_store_title(int i, char * t)
297 {
298 int c;
299 int l;
300
301 l = strlen(t);
302 c = (int)((MPS_INFO_CHARS - l) / 2) + l;
303 snprintf(mps_info[i],MPS_INFO_CHARS,"%*s", c, t);
304 }
305
306 void
mps_store_fp(int i,double f)307 mps_store_fp(int i, double f)
308 {
309 int c;
310 int l;
311 char s[12];
312
313 snprintf(s, sizeof(s), "%.1f%%",f);
314 l = strlen(s);
315 c = (int)((MPS_INFO_CHARS - l) / 2) + l;
316 snprintf(mps_info[i],MPS_INFO_CHARS,"%*s", c, s);
317 }
318
319 void
mps_store_f(int i,double f)320 mps_store_f(int i, double f)
321 {
322 int c;
323 int l;
324 char s[12];
325
326 snprintf(s, sizeof(s), "%.1f",f);
327 l = strlen(s);
328 c = (int)((MPS_INFO_CHARS - l) / 2) + l;
329 snprintf(mps_info[i],MPS_INFO_CHARS,"%*s", c, s);
330 }
331
332 void
mps_store_d(int i,int d)333 mps_store_d(int i, int d)
334 {
335 int c;
336 int l;
337 char s[12];
338
339 snprintf(s, sizeof(s), "%d",d);
340 l = strlen(s);
341 c = (int)((MPS_INFO_CHARS - l) / 2) + l;
342 snprintf(mps_info[i],MPS_INFO_CHARS,"%*s", c, s);
343 }
344
345 void
mps_store_ss(int i,char * s1,char * s2)346 mps_store_ss(int i, char * s1, char * s2)
347 {
348 int l;
349 l = snprintf(mps_info[i], MPS_INFO_CHARS, "%s", s1);
350 snprintf(&mps_info[i][l], MPS_INFO_CHARS - l, "%*s",
351 (MPS_INFO_CHARS - l - 1), s2);
352 }
353
354 void
mps_store_sss(int i,char * s1,char * s2,char * s3)355 mps_store_sss(int i, char * s1, char * s2, char * s3)
356 {
357
358 int l, e; /* Length and End of the strings */
359 int c = (MPS_INFO_CHARS) / 3;
360 int m = (MPS_INFO_CHARS) % 3;
361
362 if (i > MAPPOINT_STATS_LINES) {
363 return;
364 }
365
366 l = snprintf(mps_info[i], c + m, "%s", s1);
367 e = l;
368 l = snprintf(&mps_info[i][e], (c * 2) + m - e, "%*s",
369 (c * 2) + m - e - 1, s2);
370 e += l;
371 snprintf(&mps_info[i][e], (c * 3) + m - e, "%*s",
372 (c * 3) + m - e - 1, s3);
373 }
374
375 void
mps_store_sd(int i,char * s,int d)376 mps_store_sd(int i, char * s, int d)
377 {
378 int l;
379
380 if (i > MAPPOINT_STATS_LINES) {
381 return;
382 }
383
384 l = snprintf(mps_info[i], MPS_INFO_CHARS, "%s", s);
385 snprintf(&mps_info[i][l], MPS_INFO_CHARS, "%*d",
386 (MPS_INFO_CHARS - 1 - l), d);
387 }
388
389 void
mps_store_sfp(int i,char * s,double fl)390 mps_store_sfp(int i, char * s, double fl)
391 {
392 int l;
393 l = snprintf(mps_info[i], MPS_INFO_CHARS, "%s", s);
394 snprintf(&mps_info[i][l], MPS_INFO_CHARS, "%*.1f%%",
395 MPS_INFO_CHARS - 2 - l, fl);
396 }
397
398 /* MPS Global routines */
399
400 void
mps_right(int x,int y)401 mps_right (int x, int y)
402 {
403 int i = 0;
404 char s[12];
405 char * p;
406 int g;
407
408 snprintf(s,sizeof(s),"%d,%d",x,y);
409 mps_store_title(i++,s);
410 i++;
411 mps_store_title(i++,_("Coverage"));
412 p = (MP_INFO(x,y).flags & FLAG_FIRE_COVER) ? _("Yes") : _("No");
413 mps_store_ss(i++,_("Fire"),p);
414
415 p = (MP_INFO(x,y).flags & FLAG_HEALTH_COVER) ? _("Yes") : _("No");
416 mps_store_ss(i++,_("Health"),p);
417
418 p = (MP_INFO(x,y).flags & FLAG_CRICKET_COVER) ? _("Yes") : _("No");
419 mps_store_ss(i++,_("Cricket"),p);
420 i++;
421 mps_store_title(i++,_("Pollution"));
422
423 if (MP_POL(x,y) < 10)
424 p = _("clear");
425 else if (MP_POL(x,y) < 25)
426 p = _("good");
427 else if (MP_POL(x,y) < 70)
428 p = _("fair");
429 else if (MP_POL(x,y) < 190)
430 p = _("smelly");
431 else if (MP_POL(x,y) < 450)
432 p = _("smokey");
433 else if (MP_POL(x,y) < 1000)
434 p = _("smoggy");
435 else if (MP_POL(x,y) < 1700)
436 p = _("bad");
437 else if (MP_POL(x,y) < 3000)
438 p = _("very bad");
439 else
440 p = _("death!");
441
442 mps_store_sd(i++,p,MP_POL(x,y));
443 i++;
444
445 mps_store_title(i++,_("Bulldoze Cost"));
446 g = MP_GROUP(x,y);
447 if (g == 0) { /* Can't bulldoze grass. */
448 mps_store_title(i++,_("N/A"));
449 } else {
450 if (g < 7)
451 g--; /* translate into button type */
452 mps_store_d(i++,main_groups[g].bul_cost);
453 }
454 }
455
456
457
mps_global_finance(void)458 void mps_global_finance(void) {
459 int i = 0;
460 char s[12];
461
462 int cashflow = 0;
463
464 mps_store_title(i++,_("Tax Income"));
465
466 cashflow += ly_income_tax;
467 num_to_ansi (s, 12, ly_income_tax);
468 mps_store_ss(i++,_("Income"), s);
469
470 cashflow += ly_coal_tax;
471 num_to_ansi(s, 12, ly_coal_tax);
472 mps_store_ss(i++,_("Coal"), s);
473
474 cashflow += ly_goods_tax;
475 num_to_ansi(s, 12, ly_goods_tax);
476 mps_store_ss(i++,_("Goods"), s);
477
478 cashflow += ly_export_tax;
479 num_to_ansi(s, 12, ly_export_tax);
480 mps_store_ss(i++,_("Export"), s);
481
482 i++;
483
484 mps_store_title(i++,_("Expenses"));
485
486 cashflow -= ly_unemployment_cost;
487 num_to_ansi(s, 12, ly_unemployment_cost);
488 mps_store_ss(i++,_("Unemp."), s);
489
490 cashflow -= ly_transport_cost;
491 num_to_ansi(s, 12, ly_transport_cost);
492 mps_store_ss(i++,_("Transport"), s);
493
494 cashflow -= ly_import_cost;
495 num_to_ansi(s, 12, ly_import_cost);
496 mps_store_ss(i++,_("Imports"), s);
497
498 cashflow -= ly_other_cost;
499 num_to_ansi(s, 12, ly_other_cost);
500 mps_store_ss(i++,_("Others"), s);
501
502 i++;
503
504 num_to_ansi(s, 12, cashflow);
505 mps_store_ss(i++,_("Net"), s);
506 }
507
508 void
mps_global_other_costs(void)509 mps_global_other_costs (void)
510 {
511 int i = 0;
512 int year;
513 char s[12];
514
515 mps_store_title(i++,_("Other Costs"));
516
517 /* Don't write year if it's negative. */
518 year = (total_time / NUMOF_DAYS_IN_YEAR) - 1;
519 if (year >= 0) {
520 mps_store_sd(i++, _("For year"), year);
521 }
522 i++;
523 num_to_ansi(s,sizeof(s),ly_interest);
524 mps_store_ss(i++,_("Interest"),s);
525 num_to_ansi(s,sizeof(s),ly_school_cost);
526 mps_store_ss(i++,_("Schools"),s);
527 num_to_ansi(s,sizeof(s),ly_university_cost);
528 mps_store_ss(i++,_("Univers."),s);
529 num_to_ansi(s,sizeof(s),ly_deaths_cost);
530 mps_store_ss(i++,_("Deaths"),s);
531 num_to_ansi(s,sizeof(s),ly_windmill_cost);
532 mps_store_ss(i++,_("Windmill"),s);
533 num_to_ansi(s,sizeof(s),ly_health_cost);
534 mps_store_ss(i++,_("Hospital"),s);
535 num_to_ansi(s,sizeof(s),ly_rocket_pad_cost);
536 mps_store_ss(i++,_("Rockets"),s);
537 num_to_ansi(s,sizeof(s),ly_fire_cost);
538 mps_store_ss(i++,_("Fire Stn"),s);
539 num_to_ansi(s,sizeof(s),ly_cricket_cost);
540 mps_store_ss(i++,_("Cricket"),s);
541 num_to_ansi(s,sizeof(s),ly_recycle_cost);
542 mps_store_ss(i++,_("Recycle"),s);
543 }
544
545
546 void
mps_global_housing(void)547 mps_global_housing (void)
548 {
549 int i = 0;
550 int tp = housed_population + people_pool;
551
552 mps_store_title(i++,_("Population"));
553 i++;
554 mps_store_sd(i++,_("Total"),tp);
555 mps_store_sd(i++,_("Housed"),housed_population);
556 mps_store_sd(i++,_("Homeless"),people_pool);
557 mps_store_sd(i++,_("Shanties"),numof_shanties);
558 mps_store_sd(i++,_("Unn Dths"),unnat_deaths);
559 mps_store_title(i++,_("Unemployment"));
560 mps_store_sd(i++,_("Claims"),tunemployed_population);
561 mps_store_sfp(i++,_("Rate"),
562 ((tunemployed_population * 100.0) / tp));
563 mps_store_title(i++,_("Starvation"));
564 mps_store_sd(i++,_("Cases"),tstarving_population);
565
566 mps_store_sfp(i++,_("Rate"),
567 ((tstarving_population * 100.0) / tp));
568 }
569
570
571 #ifdef old_mps
572
573 void
mps_global_pop_setup(void)574 mps_global_pop_setup (void)
575 {
576 Rect* mps = &scr.mappoint_stats;
577 Fgl_write (mps->x + 32, mps->y + 2, _("PEOPLE"));
578 Fgl_write (mps->x + 4, mps->y + 14, _("Pop"));
579 Fgl_write (mps->x + 4, mps->y + 30, _("Unnat death"));
580 }
581
582
583
584 void
mps_global_tech_setup(void)585 mps_global_tech_setup (void)
586 {
587 Rect* mps = &scr.mappoint_stats;
588 Fgl_write (mps->x + 32, mps->y + 2, "TECH");
589 Fgl_write (mps->x + 4, mps->y + 14, "Tech lvl");
590 Fgl_write (mps->x + 4, mps->y + 22, "Schools");
591 Fgl_write (mps->x + 4, mps->y + 30, "Univers");
592 Fgl_write (mps->x + 4, mps->y + 38, "Rockets");
593 }
594
595 void
mps_global_food_setup(void)596 mps_global_food_setup (void)
597 {
598 Rect* mps = &scr.mappoint_stats;
599 Fgl_write (mps->x + 32, mps->y + 2, "FOOD");
600 Fgl_write (mps->x + 4, mps->y + 14, "Foodstore");
601 Fgl_write (mps->x + 4, mps->y + 22, "Farms");
602 Fgl_write (mps->x + 4, mps->y + 30, "Starv %");
603 }
604
605 void
mps_global_jobs_setup(void)606 mps_global_jobs_setup (void)
607 {
608 Rect* mps = &scr.mappoint_stats;
609 Fgl_write (mps->x + 32, mps->y + 2, "JOBS");
610 Fgl_write (mps->x + 4, mps->y + 14, "Jobs");
611 Fgl_write (mps->x + 4, mps->y + 22, "% Unemp");
612 }
613
614
615 #endif
616
617
618
619
620