]> git.zerfleddert.de Git - micropolis/blob - src/sim/sim.c
4b2748c0a75563f92b8cbfe915cba660d3d92651
[micropolis] / src / sim / sim.c
1 /* sim.c
2 *
3 * Micropolis, Unix Version. This game was released for the Unix platform
4 * in or about 1990 and has been modified for inclusion in the One Laptop
5 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6 * you need assistance with this program, you may contact:
7 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. You should have received a
18 * copy of the GNU General Public License along with this program. If
19 * not, see <http://www.gnu.org/licenses/>.
20 *
21 * ADDITIONAL TERMS per GNU GPL Section 7
22 *
23 * No trademark or publicity rights are granted. This license does NOT
24 * give you any right, title or interest in the trademark SimCity or any
25 * other Electronic Arts trademark. You may not distribute any
26 * modification of this program using the trademark SimCity or claim any
27 * affliation or association with Electronic Arts Inc. or its employees.
28 *
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
31 *
32 * If you convey this program (or any modifications of it) and assume
33 * contractual liability for the program to recipients of it, you agree
34 * to indemnify Electronic Arts for any liability that those contractual
35 * assumptions impose on Electronic Arts.
36 *
37 * You may not misrepresent the origins of this program; modified
38 * versions of the program must be marked as such and not identified as
39 * the original program.
40 *
41 * This disclaimer supplements the one included in the General Public
42 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60 * NOT APPLY TO YOU.
61 */
62 #include "sim.h"
63
64 void signal_init();
65 void sim_update_evaluations(void);
66 void sim_update_editors(void);
67 void sim_update_budgets(void);
68 void sim_update_graphs(void);
69 void sim_update_maps(void);
70
71 /* Sim City */
72
73 char *MicropolisVersion = "4.0";
74 Sim *sim = NULL;
75 int sim_loops = 0;
76 int sim_delay = 50;
77 int sim_skips = 0;
78 int sim_skip = 0;
79 int sim_paused = 0;
80 int sim_paused_speed = 3;
81 int sim_tty = 0;
82 #ifdef CAM
83 int sim_just_cam = 0;
84 #endif
85 int heat_steps = 0;
86 int heat_flow = -7;
87 int heat_rule = 0;
88 int heat_wrap = 3;
89 struct timeval start_time, now_time, beat_time, last_now_time;
90 char *CityFileName = NULL;
91 int Startup = 0;
92 int StartupGameLevel = 0;
93 char *StartupName = NULL;
94 int WireMode = 0;
95 int MultiPlayerMode = 0;
96 int SugarMode = 0;
97 int TilesAnimated = 0;
98 int DoAnimation = 1;
99 int DoMessages = 1;
100 int DoNotices = 1;
101 char *Displays = NULL;
102 char *FirstDisplay = NULL;
103 int ExitReturn = 0;
104
105
106 void
107 sim_exit(int val)
108 {
109 tkMustExit = 1;
110 ExitReturn = val;
111 }
112
113
114 void sim_really_exit(int val)
115 {
116 DoStopMicropolis();
117
118 exit(val);
119 }
120
121
122 #define COPY(FROM, TO) \
123 TO = ckalloc(strlen(FROM) + 1); \
124 strcpy(TO, FROM);
125
126
127 #define TESTDIR(DIR, NAME) \
128 if ((stat(DIR, &statbuf) == -1) || \
129 !(S_ISDIR(statbuf.st_mode))) { \
130 fprintf(stderr, \
131 "Can't find the directory \"%s\"!\n", DIR); \
132 fprintf(stderr, \
133 "The environment variable \"%s\" should name a directory.\n", \
134 NAME); \
135 lost = 1; \
136 }
137
138
139 void
140 env_init(void)
141 {
142 char dir[256];
143 char *s;
144 struct stat statbuf;
145 int lost = 0;
146
147 if ((s = getenv("SIMHOME")) == NULL) {
148 s = ".";
149 }
150 COPY(s, HomeDir);
151 TESTDIR(HomeDir, "$SIMHOME");
152
153 sprintf(dir, "%s/res/", HomeDir);
154 COPY(dir, ResourceDir);
155 TESTDIR(ResourceDir, "$SIMHOME/res");
156
157 { extern char *TCL_Library, *TK_Library;
158 TCL_Library = TK_Library = ResourceDir;
159 }
160
161 if (lost) {
162 fprintf(stderr,
163 "Please check the environment or reinstall Micropolis and try again! Sorry!\n");
164 sim_exit(1); // Just sets tkMustExit and ExitReturn
165 return;
166 }
167
168 gettimeofday(&now_time, NULL);
169 last_now_time = now_time;
170 }
171
172
173 void
174 sim_init(void)
175 {
176 gettimeofday(&start_time, NULL);
177 gettimeofday(&beat_time, NULL);
178
179 signal_init();
180
181 UserSoundOn = 1;
182 MustUpdateOptions = 1;
183 HaveLastMessage = 0;
184 ScenarioID = 0;
185 StartingYear = 1900;
186 tileSynch = 0x01;
187 sim_skips = sim_skip = 0;
188 autoGo = 1;
189 CityTax = 7;
190 CityTime = 50;
191 NoDisasters = 0;
192 PunishCnt = 0;
193 autoBulldoze = 1;
194 autoBudget = 1;
195 MesNum = 0;
196 LastMesTime = 0;
197 flagBlink = 1;
198 SimSpeed = 3;
199 ChangeEval();
200 MessagePort = 0;
201 MesX = 0;
202 MesY = 0;
203 sim_paused = 0;
204 sim_loops = 0;
205 InitSimLoad = 2;
206 tkMustExit = 0;
207 ExitReturn = 0;
208
209 InitializeSound();
210 initMapArrays();
211 initGraphs();
212 InitFundingLevel();
213 #if 0
214 loadObjectData();
215 #endif
216 setUpMapProcs();
217 StopEarthquake();
218 ResetMapState();
219 ResetEditorState();
220 ClearMap();
221 InitWillStuff();
222 SetFunds(5000);
223 SetGameLevelFunds(StartupGameLevel);
224 setSpeed(0);
225 setSkips(0);
226 }
227
228
229 int triedToBailOnce = 0;
230
231 void
232 SignalExitHandler()
233 {
234 if (triedToBailOnce) {
235 exit(-1);
236 } else {
237 triedToBailOnce = 1;
238 fprintf(stderr, "\nMicropolis has been terminated by a signal.\n");
239 fprintf(stderr, "Pick a window -- you're leaving!\n\n");
240 fflush(stderr);
241 sim_really_exit(-1);
242 }
243 }
244
245
246 void
247 signal_init()
248 {
249 signal(SIGHUP, (void (*)())SignalExitHandler);
250 signal(SIGINT, (void (*)())SignalExitHandler);
251 signal(SIGQUIT, (void (*)())SignalExitHandler);
252 signal(SIGTERM, (void (*)())SignalExitHandler);
253 }
254
255
256 void
257 sim_update(void)
258 {
259 gettimeofday(&now_time, NULL);
260
261 flagBlink = (now_time.tv_usec < 500000) ? 1 : -1;
262
263 if (SimSpeed && !heat_steps) {
264 TilesAnimated = 0;
265 }
266
267 sim_update_editors();
268
269 sim_update_maps();
270 sim_update_graphs();
271 sim_update_budgets();
272 sim_update_evaluations();
273
274 UpdateFlush();
275 }
276
277
278 void
279 sim_update_editors(void)
280 {
281 SimView *view;
282
283 for (view = sim->editor; view != NULL; view = view->next) {
284 #if 1
285 CancelRedrawView(view);
286 view->invalid = 1;
287 DoUpdateEditor(view);
288 #else
289 EventuallyRedrawView(view);
290 #endif
291 }
292
293 DoUpdateHeads();
294 }
295
296
297 void
298 sim_update_maps(void)
299 {
300 SimView *view;
301 int i;
302
303 for (view = sim->map; view != NULL; view = view->next) {
304 int mustUpdateMap =
305 NewMapFlags[view->map_state] || NewMap || ShakeNow;
306 if (mustUpdateMap) {
307 view->invalid = 1;
308 }
309 if (view->invalid) {
310 #if 1
311 if (mustUpdateMap) {
312 //fprintf(stderr, "sim_update_maps mustUpdateMap\n");
313 // view->skip = 0;
314 }
315 if (DoUpdateMap(view)) {
316 // CancelRedrawView(view);
317 // view->invalid = 1;
318 }
319 #else
320 EventuallyRedrawView(view);
321 #endif
322 }
323 }
324
325 NewMap = 0;
326 for (i = 0; i < NMAPS; i++) {
327 NewMapFlags[i] = 0;
328 }
329 }
330
331
332 void
333 sim_update_graphs(void)
334 {
335 graphDoer();
336 }
337
338
339 void
340 sim_update_budgets(void)
341 {
342 if ((sim_skips != 0) &&
343 (sim_skip != 0)) {
344 return;
345 }
346
347 UpdateBudgetWindow();
348 }
349
350
351 void
352 sim_update_evaluations(void)
353 {
354 if ((sim_skips != 0) &&
355 (sim_skip != 0)) {
356 return;
357 }
358
359 scoreDoer();
360 }
361
362
363 #ifdef CAM
364
365 sim_update_cams(void)
366 {
367 SimCam *scam;
368
369 if ((sim_skips != 0) &&
370 (sim_skip != 0)) {
371 return;
372 }
373
374 for (scam = sim->scam; scam != NULL; scam = scam->next) {
375 CancelRedrawView(scam);
376 scam->invalid = 1;
377 handle_scam(scam);
378 }
379 }
380
381 #endif /* CAM */
382
383
384 short *CellSrc = NULL;
385 short *CellDst = NULL;
386
387 #define SRCCOL (WORLD_Y + 2)
388 #define DSTCOL WORLD_Y
389
390 #define CLIPPER_LOOP_BODY(CODE) \
391 src = CellSrc; dst = CellDst; \
392 for (x = 0; x < WORLD_X;) { \
393 short nw, n, ne, w, c, e, sw, s, se; \
394 \
395 src = CellSrc + (x * SRCCOL); dst = CellDst + (x * DSTCOL); \
396 w = src[0]; c = src[SRCCOL]; e = src[2 * SRCCOL]; \
397 sw = src[1]; s = src[SRCCOL + 1]; se = src[(2 * SRCCOL) + 1]; \
398 \
399 for (y = 0; y < WORLD_Y; y++) { \
400 nw = w; w = sw; sw = src[2]; \
401 n = c; c = s; s = src[SRCCOL + 2]; \
402 ne = e; e = se; se = src[(2 * SRCCOL) + 2]; \
403 { CODE } \
404 src++; dst++; \
405 } \
406 x++; /* src += SRCCOL - 3; dst += DSTCOL - 1; */ \
407 src = CellSrc + ((x + 1) * SRCCOL) - 3; dst = CellDst + ((x + 1) * DSTCOL) - 1; \
408 \
409 nw = src[1]; n = src[SRCCOL + 1]; ne = src[(2 * SRCCOL) + 1]; \
410 w = src[2]; c = src[SRCCOL + 2]; e = src[(2 * SRCCOL) + 2]; \
411 \
412 for (y = WORLD_Y - 1; y >= 0; y--) { \
413 sw = w; w = nw; nw = src[0]; \
414 s = c; c = n; n = src[SRCCOL]; \
415 se = e; e = ne; ne = src[2 * SRCCOL]; \
416 { CODE } \
417 src--; dst--; \
418 } \
419 x++; /* src += SRCCOL + 3; dst += DSTCOL + 1; */ \
420 }
421
422 void
423 sim_heat(void)
424 {
425 int x, y;
426 static int a = 0;
427 short *src, *dst;
428 register int fl = heat_flow;
429
430 if (CellSrc == NULL) {
431 CellSrc = (short *)ckalloc((WORLD_X + 2) * (WORLD_Y + 2) * sizeof (short));
432 CellDst = &Map[0][0];
433 }
434
435 src = CellSrc + SRCCOL + 1;
436 dst = CellDst;
437
438 /*
439 * Copy wrapping edges:
440 *
441 * 0 ff f0 f1 ... fe ff f0
442 *
443 * 1 0f 00 01 ... 0e 0f 00
444 * 2 1f 10 11 ... 1e 1f 10
445 * .. .. .. .. .. ..
446 * ef e0 e1 ... ee ef e0
447 * h ff f0 f1 ... fe ff f0
448 *
449 * h+1 0f 00 01 ... 0e 0f 00
450 *
451 * wrap value: effect:
452 * 0 no effect
453 * 1 copy future=>past, no wrap
454 * 2 no copy, wrap edges
455 * 3 copy future=>past, wrap edges
456 * 4 copy future=>past, same edges
457 */
458
459 switch (heat_wrap) {
460 case 0:
461 break;
462 case 1:
463 for (x = 0; x < WORLD_X; x++) {
464 memcpy(src, dst, WORLD_Y * sizeof (short));
465 src += SRCCOL;
466 dst += DSTCOL;
467 }
468 break;
469 case 2:
470 for (x = 0; x < WORLD_X; x++) {
471 src[-1] = src[WORLD_Y - 1];
472 src[WORLD_Y] = src[0];
473 src += SRCCOL;
474 dst += DSTCOL;
475 }
476 memcpy(CellSrc,CellSrc + (SRCCOL * WORLD_X),
477 SRCCOL * sizeof (short));
478 memcpy(CellSrc + SRCCOL * (WORLD_X + 1), CellSrc + SRCCOL,
479 SRCCOL * sizeof (short));
480 break;
481 case 3:
482 for (x = 0; x < WORLD_X; x++) {
483 memcpy(src, dst, WORLD_Y * sizeof (short));
484 src[-1] = src[WORLD_Y - 1];
485 src[WORLD_Y] = src[0];
486 src += SRCCOL;
487 dst += DSTCOL;
488 }
489 memcpy(CellSrc, CellSrc + (SRCCOL * WORLD_X),
490 SRCCOL * sizeof (short));
491 memcpy(CellSrc + SRCCOL * (WORLD_X + 1), CellSrc + SRCCOL,
492 SRCCOL * sizeof (short));
493 break;
494 case 4:
495 src[0] = dst[0];
496 src[1 + WORLD_Y] = dst[WORLD_Y - 1];
497 src[(1 + WORLD_X) * SRCCOL] = dst[(WORLD_X - 1) * DSTCOL];
498 src[((2 + WORLD_X) * SRCCOL) - 1] = dst[(WORLD_X * WORLD_Y) - 1];
499 for (x = 0; x < WORLD_X; x++) {
500 memcpy(src, dst, WORLD_Y * sizeof (short));
501 src[-1] = src[0];
502 src[WORLD_Y] = src[WORLD_Y - 1];
503 src += SRCCOL;
504 dst += DSTCOL;
505 }
506 memcpy(CellSrc + (SRCCOL * (WORLD_X + 1)), CellSrc + (SRCCOL * WORLD_X),
507 SRCCOL * sizeof (short));
508 memcpy(CellSrc, CellSrc + SRCCOL,
509 SRCCOL * sizeof (short));
510 break;
511 }
512
513
514 switch (heat_rule) {
515
516 case 0:
517 #define HEAT \
518 a += nw + n + ne + w + e + sw + s + se + fl; \
519 dst[0] = ((a >> 3) & LOMASK) | \
520 (ANIMBIT | BURNBIT | BULLBIT); \
521 a &= 7;
522
523 CLIPPER_LOOP_BODY(HEAT);
524 break;
525
526 case 1:
527 #define ECOMASK 0x3fc
528 #define ECO \
529 c -= fl; n -= fl; s -= fl; e -= fl; w -= fl; \
530 ne -= fl; nw -= fl; se -= fl; sw -= fl; \
531 \
532 /* anneal */ \
533 { int sum = (c&1) + (n&1) + (s&1) + (e&1) + (w&1) + \
534 (ne&1) + (nw&1) + (se&1) + (sw&1), cell; \
535 if (((sum > 5) || (sum == 4))) { \
536 /* brian's brain */ \
537 cell = ((c <<1) & (0x3fc)) | \
538 (((((c >>1)&3) == 0) && \
539 (((n&2) + (s&2) + (e&2) + (w&2) + \
540 (ne&2) + (nw&2) + (se&2) + (sw&2)) == (2 <<1)) \
541 ) ? 2 : 0) | \
542 1; \
543 } else { \
544 /* anti-life */ \
545 sum = ((n&2) + (s&2) + (e&2) + (w&2) + \
546 (ne&2) + (nw&2) + (se&2) + (sw&2)) >>1; \
547 cell = (((c ^ 2) <<1) & ECOMASK) | \
548 ((c&2) ? ((sum != 5) ? 2 : 0) \
549 : (((sum != 5) && (sum != 6)) ? 2 : 0)); \
550 } \
551 dst[0] = ((fl + cell) & LOMASK) | \
552 (ANIMBIT | BURNBIT | BULLBIT); \
553 } \
554 c += fl; n += fl; s += fl; e += fl; w += fl; \
555 ne += fl; nw += fl; se += fl; sw += fl;
556
557 CLIPPER_LOOP_BODY(ECO);
558 break;
559 }
560 }
561
562 void
563 sim_timeout_loop(short doSim)
564 {
565 if (SimSpeed) {
566 sim_loop(doSim);
567 }
568 DoTimeoutListen();
569 }
570
571
572 void
573 sim_loop(int doSim)
574 {
575 #ifdef CAM
576 if (!sim_just_cam) {
577 #endif
578 if (heat_steps) {
579 int j;
580
581 for (j = 0; j < heat_steps; j++) {
582 sim_heat();
583 }
584
585 MoveObjects();
586 /*
587 InvalidateMaps();
588 */
589 NewMap = 1;
590 } else {
591 if (doSim) {
592 SimFrame();
593 }
594 MoveObjects();
595 }
596
597 sim_loops++;
598 sim_update();
599 #ifdef CAM
600 } else {
601 sim_update_cams();
602 UpdateFlush();
603 DoTimeoutListen();
604 }
605 #endif
606 }
607
608
609 int
610 MatchArg(char *arg, char *pat)
611 {
612 while (*pat && *arg) {
613 if (tolower(*arg) != tolower(*pat)) {
614 if (*pat == '_') {
615 pat++;
616 continue;
617 }
618 return (0);
619 }
620 arg++; pat++;
621 }
622 return (*arg == '\0');
623 }
624
625
626 int
627 main(int argc, char *argv[])
628 {
629 int c, errflg = 0;
630 extern int isatty();
631
632 printf("Welcome to X11 Multi Player Micropolis version %s by Will Wright, Don Hopkins.\n",
633 MicropolisVersion);
634 printf("Copyright (C) 2002 by Electronic Arts, Maxis. All rights reserved.\n");
635
636 while (!errflg &&
637 !tkMustExit &&
638 (c = getopt(argc, argv, "tcwmSR:gs:l:")) != -1) {
639 switch (c) {
640
641 case 't': /* TTY mode */
642 sim_tty = isatty(0);
643 break;
644
645 case 'c': /* Create Own Colormap */
646 { extern int TK_CreateColormap;
647 TK_CreateColormap = 1;
648 }
649 break;
650
651 case 'w': /* Wire Mode (don't use shared memory) */
652 WireMode = 1;
653 break;
654
655 case 'm': /* Multi Player Mode */
656 MultiPlayerMode = 1;
657 break;
658
659 case 'S': /* Sugar Mode */
660 SugarMode = 1;
661 break;
662
663 case 'R': /* Root Window ID */
664 c = atoi(optarg);
665 if (c) {
666 tk_RootWindow = c;
667 } else {
668 errflg = 1;
669 }
670 break;
671
672 case 'g': /* Generate New Terrain */
673 if (Startup) {
674 errflg = 1;
675 } else {
676 Startup = -1;
677 }
678 break;
679
680 case 'l': /* Level */
681 c = atoi(optarg);
682 if (!c) {
683 if (MatchArg(optarg, "easy")) {
684 c = 1;
685 } else if (MatchArg(optarg, "medium")) {
686 c = 2;
687 } else if (MatchArg(optarg, "hard")) {
688 c = 3;
689 }
690 }
691 if ((c < 1) || (c > 3)) {
692 errflg = 1;
693 } else {
694 StartupGameLevel = c - 1;
695 }
696 break;
697
698 case 's': /* Scenario <name> */
699 if (Startup)
700 errflg++;
701 else {
702 c = atoi(optarg);
703 if (!c) {
704 if (MatchArg(optarg, "Dullsville")) {
705 c = 1;
706 } else if (MatchArg(optarg, "San_Francisco")) {
707 c = 2;
708 } else if (MatchArg(optarg, "Hamburg")) {
709 c = 3;
710 } else if (MatchArg(optarg, "Bern")) {
711 c = 4;
712 } else if (MatchArg(optarg, "Tokyo")) {
713 c = 5;
714 } else if (MatchArg(optarg, "Detroit")) {
715 c = 6;
716 } else if (MatchArg(optarg, "Boston")) {
717 c = 7;
718 } else if (MatchArg(optarg, "Rio_de_Janeiro")) {
719 c = 8;
720 }
721 }
722 if ((c < 1) || (c > 8)) {
723 errflg = 1;
724 } else {
725 Startup = c;
726 }
727 }
728 break;
729
730 case 'd': /* Display <name> */
731 { char *d = Displays;
732
733 if (d == NULL) {
734 Displays = malloc(strlen(optarg) + 3);
735 sprintf(Displays, "{%s}", optarg);
736
737 if (strchr(optarg, ':') != NULL) {
738 FirstDisplay = malloc(strlen(optarg) + 1);
739 strcpy(FirstDisplay, optarg);
740 } else {
741 FirstDisplay = malloc(strlen(optarg) + 3);
742 sprintf(FirstDisplay, "%s:0", optarg);
743 }
744 } else {
745 /* Implicitly set multi player mode if multiple displays given. */
746 MultiPlayerMode = 1;
747 Displays = malloc(strlen(Displays) + strlen(optarg) + 4);
748 sprintf(Displays, "%s {%s}", d, optarg);
749 free(d);
750 }
751 }
752 break;
753
754 case '?':
755 errflg++;
756 break;
757 }
758 }
759
760 if (!errflg &&
761 !tkMustExit) {
762 if ((Startup == -1) ||
763 (Startup == -2)) {
764 /* Generate New City */
765 if ((optind != argc) && (optind != argc - 1)) {
766 errflg = 1;
767 } else {
768 if (optind == argc - 1)
769 StartupName = argv[optind];
770 }
771 } else if (Startup > 0) {
772 /* Scenario */
773 } else if (optind == argc - 1) {
774 /* Load City */
775 Startup = -2;
776 StartupName = argv[optind];
777 } else if (optind == argc) {
778 /* No arguments */
779 } else {
780 errflg = 1;
781 }
782 }
783
784 if (errflg) {
785 fprintf(stderr,
786 "usage: %s\n", argv[0]);
787 fprintf(stderr,
788 " [-s(cenario) number|name]\n");
789 fprintf(stderr,
790 " [-g(enerate random map and start playing)\n");
791 fprintf(stderr,
792 " [-l(evel) number|name]\n");
793 fprintf(stderr,
794 " [-w(ire mode: use X11 networking without shared memory)]\n");
795 fprintf(stderr,
796 " [-t(ty mode: interactive TCL session on stdin/stdout)]\n");
797 fprintf(stderr,
798 " [-c(olormap mode: create own X11 colormap on 8 bit screens)]\n");
799 fprintf(stderr,
800 " [-S(ugar mode: enable OLPC Sugar user interface integration)]\n");
801 fprintf(stderr,
802 " [-m(ulti player mode: enable adding multiple players via X11)]\n");
803 fprintf(stderr,
804 " [NewCityName]\n");
805 fprintf(stderr,
806 " [SavedFileName.city]\n");
807 fprintf(stderr,
808 "The game level and NewCityName argument are optional, and only apply when\n");
809 fprintf(stderr,
810 "starting a new city or generating new terrain.\n");
811 fprintf(stderr,
812 "Game levels include: 1: Easy, 2: Medium, 3: Hard\n");
813 fprintf(stderr,
814 "Scenarios include: 1: Dullsville, 2: San_Francisco, 3: Hamburg, 4: Bern,\n");
815 fprintf(stderr,
816 " 5: Tokyo, 6: Detroit, 7: Boston, 8: Rio_de_Janeiro\n");
817 fflush(stderr);
818 sim_exit(0); // Just sets tkMustExit and ExitReturn
819 }
820
821 if ((!tkMustExit) &&
822 (Displays == NULL)) {
823 char *d = getenv("DISPLAY");
824
825 if (d == NULL) d = ":0";
826
827 Displays = malloc(strlen(d) + 3);
828 sprintf(Displays, "{%s}", d);
829 if (strchr(d, ':') != NULL) {
830 FirstDisplay = malloc(strlen(d) + 1);
831 strcpy(FirstDisplay, d);
832 } else {
833 FirstDisplay = malloc(strlen(d) + 3);
834 sprintf(FirstDisplay, "%s:0", d);
835 }
836 }
837
838 if (!tkMustExit) {
839 env_init();
840 }
841
842 if (!tkMustExit) {
843 tk_main();
844 }
845
846 exit (ExitReturn);
847 }
Impressum, Datenschutz