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