]> cvs.zerfleddert.de Git - micropolis/blame - src/sim/sim.c
prevent forking a huge number of player processes by limiting them to
[micropolis] / src / sim / sim.c
CommitLineData
6a5fa4e0
MG
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
67char *MicropolisVersion = "4.0";
68Sim *sim = NULL;
69int sim_loops = 0;
70int sim_delay = 50;
71int sim_skips = 0;
72int sim_skip = 0;
73int sim_paused = 0;
74int sim_paused_speed = 3;
75int sim_tty = 0;
76#ifdef CAM
77int sim_just_cam = 0;
78#endif
79int heat_steps = 0;
80int heat_flow = -7;
81int heat_rule = 0;
82int heat_wrap = 3;
83struct timeval start_time, now_time, beat_time, last_now_time;
84char *CityFileName = NULL;
85int Startup = 0;
86int StartupGameLevel = 0;
87char *StartupName = NULL;
88int WireMode = 0;
89int MultiPlayerMode = 0;
90int SugarMode = 0;
91int TilesAnimated = 0;
92int DoAnimation = 1;
93int DoMessages = 1;
94int DoNotices = 1;
95char *Displays = NULL;
96char *FirstDisplay = NULL;
97int ExitReturn = 0;
98
99
100sim_exit(int val)
101{
102 tkMustExit = 1;
103 ExitReturn = val;
104}
105
106
107sim_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
132void
133env_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
166void
167sim_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
222int triedToBailOnce = 0;
223
224void
225SignalExitHandler()
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
239signal_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
248void
249sim_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
270sim_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
288sim_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
322sim_update_graphs(void)
323{
324 graphDoer();
325}
326
327
328sim_update_budgets(void)
329{
330 if ((sim_skips != 0) &&
331 (sim_skip != 0)) {
332 return;
333 }
334
335 UpdateBudgetWindow();
336}
337
338
339sim_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
352sim_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
371short *CellSrc = NULL;
372short *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
409void
410sim_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
550void
551sim_timeout_loop(short doSim)
552{
553 if (SimSpeed) {
554 sim_loop(doSim);
555 }
556 DoTimeoutListen();
557}
558
559
560sim_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
596int
597MatchArg(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
613int
614main(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