]> git.zerfleddert.de Git - micropolis/blob - src/sim/sim.c
79a7817903ecc907a10208e5ecf3e015edbf99ca
[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
65 /* Sim City */
66
67 char *MicropolisVersion = "4.0";
68 Sim *sim = NULL;
69 int sim_loops = 0;
70 int sim_delay = 50;
71 int sim_skips = 0;
72 int sim_skip = 0;
73 int sim_paused = 0;
74 int sim_paused_speed = 3;
75 int sim_tty = 0;
76 #ifdef CAM
77 int sim_just_cam = 0;
78 #endif
79 int heat_steps = 0;
80 int heat_flow = -7;
81 int heat_rule = 0;
82 int heat_wrap = 3;
83 struct timeval start_time, now_time, beat_time, last_now_time;
84 char *CityFileName = NULL;
85 int Startup = 0;
86 int StartupGameLevel = 0;
87 char *StartupName = NULL;
88 int WireMode = 0;
89 int MultiPlayerMode = 0;
90 int SugarMode = 0;
91 int TilesAnimated = 0;
92 int DoAnimation = 1;
93 int DoMessages = 1;
94 int DoNotices = 1;
95 char *Displays = NULL;
96 char *FirstDisplay = NULL;
97 int ExitReturn = 0;
98
99
100 sim_exit(int val)
101 {
102 tkMustExit = 1;
103 ExitReturn = val;
104 }
105
106
107 sim_really_exit(int val)
108 {
109 DoStopMicropolis();
110
111 exit(val);
112 }
113
114
115 #define COPY(FROM, TO) \
116 TO = ckalloc(strlen(FROM) + 1); \
117 strcpy(TO, FROM);
118
119
120 #define TESTDIR(DIR, NAME) \
121 if ((stat(DIR, &statbuf) == -1) || \
122 !(S_ISDIR(statbuf.st_mode))) { \
123 fprintf(stderr, \
124 "Can't find the directory \"%s\"!\n", DIR); \
125 fprintf(stderr, \
126 "The environment variable \"%s\" should name a directory.\n", \
127 NAME); \
128 lost = 1; \
129 }
130
131
132 void
133 env_init(void)
134 {
135 char dir[256];
136 char *s;
137 struct stat statbuf;
138 int lost = 0;
139
140 if ((s = getenv("SIMHOME")) == NULL) {
141 s = ".";
142 }
143 COPY(s, HomeDir);
144 TESTDIR(HomeDir, "$SIMHOME");
145
146 sprintf(dir, "%s/res/", HomeDir);
147 COPY(dir, ResourceDir);
148 TESTDIR(ResourceDir, "$SIMHOME/res");
149
150 { extern char *TCL_Library, *TK_Library;
151 TCL_Library = TK_Library = ResourceDir;
152 }
153
154 if (lost) {
155 fprintf(stderr,
156 "Please check the environment or reinstall Micropolis and try again! Sorry!\n");
157 sim_exit(1); // Just sets tkMustExit and ExitReturn
158 return;
159 }
160
161 gettimeofday(&now_time, NULL);
162 last_now_time = now_time;
163 }
164
165
166 void
167 sim_init(void)
168 {
169 gettimeofday(&start_time, NULL);
170 gettimeofday(&beat_time, NULL);
171
172 signal_init();
173
174 UserSoundOn = 1;
175 MustUpdateOptions = 1;
176 HaveLastMessage = 0;
177 ScenarioID = 0;
178 StartingYear = 1900;
179 tileSynch = 0x01;
180 sim_skips = sim_skip = 0;
181 autoGo = 1;
182 CityTax = 7;
183 CityTime = 50;
184 NoDisasters = 0;
185 PunishCnt = 0;
186 autoBulldoze = 1;
187 autoBudget = 1;
188 MesNum = 0;
189 LastMesTime = 0;
190 flagBlink = 1;
191 SimSpeed = 3;
192 ChangeEval();
193 MessagePort = 0;
194 MesX = 0;
195 MesY = 0;
196 sim_paused = 0;
197 sim_loops = 0;
198 InitSimLoad = 2;
199 tkMustExit = 0;
200 ExitReturn = 0;
201
202 InitializeSound();
203 initMapArrays();
204 initGraphs();
205 InitFundingLevel();
206 #if 0
207 loadObjectData();
208 #endif
209 setUpMapProcs();
210 StopEarthquake();
211 ResetMapState();
212 ResetEditorState();
213 ClearMap();
214 InitWillStuff();
215 SetFunds(5000);
216 SetGameLevelFunds(StartupGameLevel);
217 setSpeed(0);
218 setSkips(0);
219 }
220
221
222 int triedToBailOnce = 0;
223
224 void
225 SignalExitHandler()
226 {
227 if (triedToBailOnce) {
228 exit(-1);
229 } else {
230 triedToBailOnce = 1;
231 fprintf(stderr, "\nMicropolis has been terminated by a signal.\n");
232 fprintf(stderr, "Pick a window -- you're leaving!\n\n");
233 fflush(stderr);
234 sim_really_exit(-1);
235 }
236 }
237
238
239 signal_init()
240 {
241 signal(SIGHUP, (void (*)())SignalExitHandler);
242 signal(SIGINT, (void (*)())SignalExitHandler);
243 signal(SIGQUIT, (void (*)())SignalExitHandler);
244 signal(SIGTERM, (void (*)())SignalExitHandler);
245 }
246
247
248 void
249 sim_update()
250 {
251 gettimeofday(&now_time, NULL);
252
253 flagBlink = (now_time.tv_usec < 500000) ? 1 : -1;
254
255 if (SimSpeed && !heat_steps) {
256 TilesAnimated = 0;
257 }
258
259 sim_update_editors();
260
261 sim_update_maps();
262 sim_update_graphs();
263 sim_update_budgets();
264 sim_update_evaluations();
265
266 UpdateFlush();
267 }
268
269
270 sim_update_editors(void)
271 {
272 SimView *view;
273
274 for (view = sim->editor; view != NULL; view = view->next) {
275 #if 1
276 CancelRedrawView(view);
277 view->invalid = 1;
278 DoUpdateEditor(view);
279 #else
280 EventuallyRedrawView(view);
281 #endif
282 }
283
284 DoUpdateHeads();
285 }
286
287
288 sim_update_maps(void)
289 {
290 SimView *view;
291 int i;
292
293 for (view = sim->map; view != NULL; view = view->next) {
294 int mustUpdateMap =
295 NewMapFlags[view->map_state] || NewMap || ShakeNow;
296 if (mustUpdateMap) {
297 view->invalid = 1;
298 }
299 if (view->invalid) {
300 #if 1
301 if (mustUpdateMap) {
302 //fprintf(stderr, "sim_update_maps mustUpdateMap\n");
303 // view->skip = 0;
304 }
305 if (DoUpdateMap(view)) {
306 // CancelRedrawView(view);
307 // view->invalid = 1;
308 }
309 #else
310 EventuallyRedrawView(view);
311 #endif
312 }
313 }
314
315 NewMap = 0;
316 for (i = 0; i < NMAPS; i++) {
317 NewMapFlags[i] = 0;
318 }
319 }
320
321
322 sim_update_graphs(void)
323 {
324 graphDoer();
325 }
326
327
328 sim_update_budgets(void)
329 {
330 if ((sim_skips != 0) &&
331 (sim_skip != 0)) {
332 return;
333 }
334
335 UpdateBudgetWindow();
336 }
337
338
339 sim_update_evaluations(void)
340 {
341 if ((sim_skips != 0) &&
342 (sim_skip != 0)) {
343 return;
344 }
345
346 scoreDoer();
347 }
348
349
350 #ifdef CAM
351
352 sim_update_cams(void)
353 {
354 SimCam *scam;
355
356 if ((sim_skips != 0) &&
357 (sim_skip != 0)) {
358 return;
359 }
360
361 for (scam = sim->scam; scam != NULL; scam = scam->next) {
362 CancelRedrawView(scam);
363 scam->invalid = 1;
364 handle_scam(scam);
365 }
366 }
367
368 #endif /* CAM */
369
370
371 short *CellSrc = NULL;
372 short *CellDst = NULL;
373
374 #define SRCCOL (WORLD_Y + 2)
375 #define DSTCOL WORLD_Y
376
377 #define CLIPPER_LOOP_BODY(CODE) \
378 src = CellSrc; dst = CellDst; \
379 for (x = 0; x < WORLD_X;) { \
380 short nw, n, ne, w, c, e, sw, s, se; \
381 \
382 src = CellSrc + (x * SRCCOL); dst = CellDst + (x * DSTCOL); \
383 w = src[0]; c = src[SRCCOL]; e = src[2 * SRCCOL]; \
384 sw = src[1]; s = src[SRCCOL + 1]; se = src[(2 * SRCCOL) + 1]; \
385 \
386 for (y = 0; y < WORLD_Y; y++) { \
387 nw = w; w = sw; sw = src[2]; \
388 n = c; c = s; s = src[SRCCOL + 2]; \
389 ne = e; e = se; se = src[(2 * SRCCOL) + 2]; \
390 { CODE } \
391 src++; dst++; \
392 } \
393 x++; /* src += SRCCOL - 3; dst += DSTCOL - 1; */ \
394 src = CellSrc + ((x + 1) * SRCCOL) - 3; dst = CellDst + ((x + 1) * DSTCOL) - 1; \
395 \
396 nw = src[1]; n = src[SRCCOL + 1]; ne = src[(2 * SRCCOL) + 1]; \
397 w = src[2]; c = src[SRCCOL + 2]; e = src[(2 * SRCCOL) + 2]; \
398 \
399 for (y = WORLD_Y - 1; y >= 0; y--) { \
400 sw = w; w = nw; nw = src[0]; \
401 s = c; c = n; n = src[SRCCOL]; \
402 se = e; e = ne; ne = src[2 * SRCCOL]; \
403 { CODE } \
404 src--; dst--; \
405 } \
406 x++; /* src += SRCCOL + 3; dst += DSTCOL + 1; */ \
407 }
408
409 void
410 sim_heat(void)
411 {
412 int x, y, l, r, u, d;
413 static int a = 0;
414 short *src, *dst;
415 register int fl = heat_flow;
416
417 if (CellSrc == NULL) {
418 CellSrc = (short *)ckalloc((WORLD_X + 2) * (WORLD_Y + 2) * sizeof (short));
419 CellDst = &Map[0][0];
420 }
421
422 src = CellSrc + SRCCOL + 1;
423 dst = CellDst;
424
425 /*
426 * Copy wrapping edges:
427 *
428 * 0 ff f0 f1 ... fe ff f0
429 *
430 * 1 0f 00 01 ... 0e 0f 00
431 * 2 1f 10 11 ... 1e 1f 10
432 * .. .. .. .. .. ..
433 * ef e0 e1 ... ee ef e0
434 * h ff f0 f1 ... fe ff f0
435 *
436 * h+1 0f 00 01 ... 0e 0f 00
437 *
438 * wrap value: effect:
439 * 0 no effect
440 * 1 copy future=>past, no wrap
441 * 2 no copy, wrap edges
442 * 3 copy future=>past, wrap edges
443 * 4 copy future=>past, same edges
444 */
445
446 switch (heat_wrap) {
447 case 0:
448 break;
449 case 1:
450 for (x = 0; x < WORLD_X; x++) {
451 memcpy(src, dst, WORLD_Y * sizeof (short));
452 src += SRCCOL;
453 dst += DSTCOL;
454 }
455 break;
456 case 2:
457 for (x = 0; x < WORLD_X; x++) {
458 src[-1] = src[WORLD_Y - 1];
459 src[WORLD_Y] = src[0];
460 src += SRCCOL;
461 dst += DSTCOL;
462 }
463 memcpy(CellSrc,CellSrc + (SRCCOL * WORLD_X),
464 SRCCOL * sizeof (short));
465 memcpy(CellSrc + SRCCOL * (WORLD_X + 1), CellSrc + SRCCOL,
466 SRCCOL * sizeof (short));
467 break;
468 case 3:
469 for (x = 0; x < WORLD_X; x++) {
470 memcpy(src, dst, WORLD_Y * sizeof (short));
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 4:
482 src[0] = dst[0];
483 src[1 + WORLD_Y] = dst[WORLD_Y - 1];
484 src[(1 + WORLD_X) * SRCCOL] = dst[(WORLD_X - 1) * DSTCOL];
485 src[((2 + WORLD_X) * SRCCOL) - 1] = dst[(WORLD_X * WORLD_Y) - 1];
486 for (x = 0; x < WORLD_X; x++) {
487 memcpy(src, dst, WORLD_Y * sizeof (short));
488 src[-1] = src[0];
489 src[WORLD_Y] = src[WORLD_Y - 1];
490 src += SRCCOL;
491 dst += DSTCOL;
492 }
493 memcpy(CellSrc + (SRCCOL * (WORLD_X + 1)), CellSrc + (SRCCOL * WORLD_X),
494 SRCCOL * sizeof (short));
495 memcpy(CellSrc, CellSrc + SRCCOL,
496 SRCCOL * sizeof (short));
497 break;
498 }
499
500
501 switch (heat_rule) {
502
503 case 0:
504 #define HEAT \
505 a += nw + n + ne + w + e + sw + s + se + fl; \
506 dst[0] = ((a >> 3) & LOMASK) | \
507 (ANIMBIT | BURNBIT | BULLBIT); \
508 a &= 7;
509
510 CLIPPER_LOOP_BODY(HEAT);
511 break;
512
513 case 1:
514 #define ECOMASK 0x3fc
515 #define ECO \
516 c -= fl; n -= fl; s -= fl; e -= fl; w -= fl; \
517 ne -= fl; nw -= fl; se -= fl; sw -= fl; \
518 \
519 /* anneal */ \
520 { int sum = (c&1) + (n&1) + (s&1) + (e&1) + (w&1) + \
521 (ne&1) + (nw&1) + (se&1) + (sw&1), cell; \
522 if (((sum > 5) || (sum == 4))) { \
523 /* brian's brain */ \
524 cell = ((c <<1) & (0x3fc)) | \
525 (((((c >>1)&3) == 0) && \
526 (((n&2) + (s&2) + (e&2) + (w&2) + \
527 (ne&2) + (nw&2) + (se&2) + (sw&2)) == (2 <<1)) \
528 ) ? 2 : 0) | \
529 1; \
530 } else { \
531 /* anti-life */ \
532 sum = ((n&2) + (s&2) + (e&2) + (w&2) + \
533 (ne&2) + (nw&2) + (se&2) + (sw&2)) >>1; \
534 cell = (((c ^ 2) <<1) & ECOMASK) | \
535 ((c&2) ? ((sum != 5) ? 2 : 0) \
536 : (((sum != 5) && (sum != 6)) ? 2 : 0)); \
537 } \
538 dst[0] = ((fl + cell) & LOMASK) | \
539 (ANIMBIT | BURNBIT | BULLBIT); \
540 } \
541 c += fl; n += fl; s += fl; e += fl; w += fl; \
542 ne += fl; nw += fl; se += fl; sw += fl;
543
544 CLIPPER_LOOP_BODY(ECO);
545 break;
546 }
547 }
548
549
550 void
551 sim_timeout_loop(short doSim)
552 {
553 if (SimSpeed) {
554 sim_loop(doSim);
555 }
556 DoTimeoutListen();
557 }
558
559
560 sim_loop(int doSim)
561 {
562 #ifdef CAM
563 if (!sim_just_cam) {
564 #endif
565 if (heat_steps) {
566 int j;
567
568 for (j = 0; j < heat_steps; j++) {
569 sim_heat();
570 }
571
572 MoveObjects();
573 /*
574 InvalidateMaps();
575 */
576 NewMap = 1;
577 } else {
578 if (doSim) {
579 SimFrame();
580 }
581 MoveObjects();
582 }
583
584 sim_loops++;
585 sim_update();
586 #ifdef CAM
587 } else {
588 sim_update_cams();
589 UpdateFlush();
590 DoTimeoutListen();
591 }
592 #endif
593 }
594
595
596 int
597 MatchArg(char *arg, char *pat)
598 {
599 while (*pat && *arg) {
600 if (tolower(*arg) != tolower(*pat)) {
601 if (*pat == '_') {
602 pat++;
603 continue;
604 }
605 return (0);
606 }
607 arg++; pat++;
608 }
609 return (*arg == '\0');
610 }
611
612
613 int
614 main(int argc, char *argv[])
615 {
616 int c, errflg = 0;
617 extern int isatty();
618
619 printf("Welcome to X11 Multi Player Micropolis version %s by Will Wright, Don Hopkins.\n",
620 MicropolisVersion);
621 printf("Copyright (C) 2002 by Electronic Arts, Maxis. All rights reserved.\n");
622
623 while (!errflg &&
624 !tkMustExit &&
625 (c = getopt(argc, argv, "tcwmSR:gs:l:")) != -1) {
626 switch (c) {
627
628 case 't': /* TTY mode */
629 sim_tty = isatty(0);
630 break;
631
632 case 'c': /* Create Own Colormap */
633 { extern int TK_CreateColormap;
634 TK_CreateColormap = 1;
635 }
636 break;
637
638 case 'w': /* Wire Mode (don't use shared memory) */
639 WireMode = 1;
640 break;
641
642 case 'm': /* Multi Player Mode */
643 MultiPlayerMode = 1;
644 break;
645
646 case 'S': /* Sugar Mode */
647 SugarMode = 1;
648 break;
649
650 case 'R': /* Root Window ID */
651 c = atoi(optarg);
652 if (c) {
653 tk_RootWindow = c;
654 } else {
655 errflg = 1;
656 }
657 break;
658
659 case 'g': /* Generate New Terrain */
660 if (Startup) {
661 errflg = 1;
662 } else {
663 Startup = -1;
664 }
665 break;
666
667 case 'l': /* Level */
668 c = atoi(optarg);
669 if (!c) {
670 if (MatchArg(optarg, "easy")) {
671 c = 1;
672 } else if (MatchArg(optarg, "medium")) {
673 c = 2;
674 } else if (MatchArg(optarg, "hard")) {
675 c = 3;
676 }
677 }
678 if ((c < 1) || (c > 3)) {
679 errflg = 1;
680 } else {
681 StartupGameLevel = c - 1;
682 }
683 break;
684
685 case 's': /* Scenario <name> */
686 if (Startup)
687 errflg++;
688 else {
689 c = atoi(optarg);
690 if (!c) {
691 if (MatchArg(optarg, "Dullsville")) {
692 c = 1;
693 } else if (MatchArg(optarg, "San_Francisco")) {
694 c = 2;
695 } else if (MatchArg(optarg, "Hamburg")) {
696 c = 3;
697 } else if (MatchArg(optarg, "Bern")) {
698 c = 4;
699 } else if (MatchArg(optarg, "Tokyo")) {
700 c = 5;
701 } else if (MatchArg(optarg, "Detroit")) {
702 c = 6;
703 } else if (MatchArg(optarg, "Boston")) {
704 c = 7;
705 } else if (MatchArg(optarg, "Rio_de_Janeiro")) {
706 c = 8;
707 }
708 }
709 if ((c < 1) || (c > 8)) {
710 errflg = 1;
711 } else {
712 Startup = c;
713 }
714 }
715 break;
716
717 case 'd': /* Display <name> */
718 { char *d = Displays;
719
720 if (d == NULL) {
721 Displays = malloc(strlen(optarg) + 3);
722 sprintf(Displays, "{%s}", optarg);
723
724 if (strchr(optarg, ':') != NULL) {
725 FirstDisplay = malloc(strlen(optarg) + 1);
726 strcpy(FirstDisplay, optarg);
727 } else {
728 FirstDisplay = malloc(strlen(optarg) + 3);
729 sprintf(FirstDisplay, "%s:0", optarg);
730 }
731 } else {
732 /* Implicitly set multi player mode if multiple displays given. */
733 MultiPlayerMode = 1;
734 Displays = malloc(strlen(Displays) + strlen(optarg) + 4);
735 sprintf(Displays, "%s {%s}", d, optarg);
736 free(d);
737 }
738 }
739 break;
740
741 case '?':
742 errflg++;
743 break;
744 }
745 }
746
747 if (!errflg &&
748 !tkMustExit) {
749 if ((Startup == -1) ||
750 (Startup == -2)) {
751 /* Generate New City */
752 if ((optind != argc) && (optind != argc - 1)) {
753 errflg = 1;
754 } else {
755 if (optind == argc - 1)
756 StartupName = argv[optind];
757 }
758 } else if (Startup > 0) {
759 /* Scenario */
760 } else if (optind == argc - 1) {
761 /* Load City */
762 Startup = -2;
763 StartupName = argv[optind];
764 } else if (optind == argc) {
765 /* No arguments */
766 } else {
767 errflg = 1;
768 }
769 }
770
771 if (errflg) {
772 fprintf(stderr,
773 "usage: %s\n", argv[0]);
774 fprintf(stderr,
775 " [-s(cenario) number|name]\n");
776 fprintf(stderr,
777 " [-g(enerate random map and start playing)\n");
778 fprintf(stderr,
779 " [-l(evel) number|name]\n");
780 fprintf(stderr,
781 " [-w(ire mode: use X11 networking without shared memory)]\n");
782 fprintf(stderr,
783 " [-t(ty mode: interactive TCL session on stdin/stdout)]\n");
784 fprintf(stderr,
785 " [-c(olormap mode: create own X11 colormap on 8 bit screens)]\n");
786 fprintf(stderr,
787 " [-S(ugar mode: enable OLPC Sugar user interface integration)]\n");
788 fprintf(stderr,
789 " [-m(ulti player mode: enable adding multiple players via X11)]\n");
790 fprintf(stderr,
791 " [NewCityName]\n");
792 fprintf(stderr,
793 " [SavedFileName.city]\n");
794 fprintf(stderr,
795 "The game level and NewCityName argument are optional, and only apply when\n");
796 fprintf(stderr,
797 "starting a new city or generating new terrain.\n");
798 fprintf(stderr,
799 "Game levels include: 1: Easy, 2: Medium, 3: Hard\n");
800 fprintf(stderr,
801 "Scenarios include: 1: Dullsville, 2: San_Francisco, 3: Hamburg, 4: Bern,\n");
802 fprintf(stderr,
803 " 5: Tokyo, 6: Detroit, 7: Boston, 8: Rio_de_Janeiro\n");
804 fflush(stderr);
805 sim_exit(0); // Just sets tkMustExit and ExitReturn
806 }
807
808 if ((!tkMustExit) &&
809 (Displays == NULL)) {
810 char *d = getenv("DISPLAY");
811
812 if (d == NULL) d = ":0";
813
814 Displays = malloc(strlen(d) + 3);
815 sprintf(Displays, "{%s}", d);
816 if (strchr(d, ':') != NULL) {
817 FirstDisplay = malloc(strlen(d) + 1);
818 strcpy(FirstDisplay, d);
819 } else {
820 FirstDisplay = malloc(strlen(d) + 3);
821 sprintf(FirstDisplay, "%s:0", d);
822 }
823 }
824
825 if (!tkMustExit) {
826 env_init();
827 }
828
829 if (!tkMustExit) {
830 tk_main();
831 }
832
833 exit (ExitReturn);
834 }
Impressum, Datenschutz