]> git.zerfleddert.de Git - micropolis/blame - src/sim/sim.c
begin suppport for smaller screens, currently just prints a warning
[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
6f214ac0
MG
64void signal_init();
65void sim_update_evaluations(void);
66void sim_update_editors(void);
67void sim_update_budgets(void);
68void sim_update_graphs(void);
69void sim_update_maps(void);
6a5fa4e0
MG
70
71/* Sim City */
72
73char *MicropolisVersion = "4.0";
74Sim *sim = NULL;
75int sim_loops = 0;
76int sim_delay = 50;
77int sim_skips = 0;
78int sim_skip = 0;
79int sim_paused = 0;
80int sim_paused_speed = 3;
81int sim_tty = 0;
82#ifdef CAM
83int sim_just_cam = 0;
84#endif
85int heat_steps = 0;
86int heat_flow = -7;
87int heat_rule = 0;
88int heat_wrap = 3;
89struct timeval start_time, now_time, beat_time, last_now_time;
90char *CityFileName = NULL;
91int Startup = 0;
92int StartupGameLevel = 0;
93char *StartupName = NULL;
94int WireMode = 0;
95int MultiPlayerMode = 0;
96int SugarMode = 0;
97int TilesAnimated = 0;
98int DoAnimation = 1;
99int DoMessages = 1;
100int DoNotices = 1;
101char *Displays = NULL;
102char *FirstDisplay = NULL;
103int ExitReturn = 0;
104
105
6f214ac0 106void
6a5fa4e0
MG
107sim_exit(int val)
108{
109 tkMustExit = 1;
110 ExitReturn = val;
111}
112
113
6f214ac0 114void sim_really_exit(int val)
6a5fa4e0
MG
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
139void
140env_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
173void
174sim_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
229int triedToBailOnce = 0;
230
231void
232SignalExitHandler()
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
6f214ac0 246void
6a5fa4e0
MG
247signal_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
256void
6f214ac0 257sim_update(void)
6a5fa4e0
MG
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
6f214ac0 278void
6a5fa4e0
MG
279sim_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
6f214ac0 297void
6a5fa4e0
MG
298sim_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
6f214ac0 332void
6a5fa4e0
MG
333sim_update_graphs(void)
334{
335 graphDoer();
336}
337
338
6f214ac0 339void
6a5fa4e0
MG
340sim_update_budgets(void)
341{
342 if ((sim_skips != 0) &&
343 (sim_skip != 0)) {
344 return;
345 }
346
347 UpdateBudgetWindow();
348}
349
350
6f214ac0 351void
6a5fa4e0
MG
352sim_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
365sim_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
384short *CellSrc = NULL;
385short *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
422void
423sim_heat(void)
424{
6f214ac0 425 int x, y;
6a5fa4e0
MG
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
6a5fa4e0
MG
562void
563sim_timeout_loop(short doSim)
564{
565 if (SimSpeed) {
566 sim_loop(doSim);
567 }
568 DoTimeoutListen();
569}
570
571
6f214ac0 572void
6a5fa4e0
MG
573sim_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
609int
610MatchArg(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
626int
627main(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");
38b72baa 635 printf("Support for newer Unix systems and new bugs added by Michael Gernoth.\n");
6a5fa4e0
MG
636
637 while (!errflg &&
638 !tkMustExit &&
639 (c = getopt(argc, argv, "tcwmSR:gs:l:")) != -1) {
640 switch (c) {
641
642 case 't': /* TTY mode */
643 sim_tty = isatty(0);
644 break;
645
646 case 'c': /* Create Own Colormap */
647 { extern int TK_CreateColormap;
648 TK_CreateColormap = 1;
649 }
650 break;
651
652 case 'w': /* Wire Mode (don't use shared memory) */
653 WireMode = 1;
654 break;
655
656 case 'm': /* Multi Player Mode */
657 MultiPlayerMode = 1;
658 break;
659
660 case 'S': /* Sugar Mode */
661 SugarMode = 1;
662 break;
663
664 case 'R': /* Root Window ID */
665 c = atoi(optarg);
666 if (c) {
667 tk_RootWindow = c;
668 } else {
669 errflg = 1;
670 }
671 break;
672
673 case 'g': /* Generate New Terrain */
674 if (Startup) {
675 errflg = 1;
676 } else {
677 Startup = -1;
678 }
679 break;
680
681 case 'l': /* Level */
682 c = atoi(optarg);
683 if (!c) {
684 if (MatchArg(optarg, "easy")) {
685 c = 1;
686 } else if (MatchArg(optarg, "medium")) {
687 c = 2;
688 } else if (MatchArg(optarg, "hard")) {
689 c = 3;
690 }
691 }
692 if ((c < 1) || (c > 3)) {
693 errflg = 1;
694 } else {
695 StartupGameLevel = c - 1;
696 }
697 break;
698
699 case 's': /* Scenario <name> */
700 if (Startup)
701 errflg++;
702 else {
703 c = atoi(optarg);
704 if (!c) {
705 if (MatchArg(optarg, "Dullsville")) {
706 c = 1;
707 } else if (MatchArg(optarg, "San_Francisco")) {
708 c = 2;
709 } else if (MatchArg(optarg, "Hamburg")) {
710 c = 3;
711 } else if (MatchArg(optarg, "Bern")) {
712 c = 4;
713 } else if (MatchArg(optarg, "Tokyo")) {
714 c = 5;
715 } else if (MatchArg(optarg, "Detroit")) {
716 c = 6;
717 } else if (MatchArg(optarg, "Boston")) {
718 c = 7;
719 } else if (MatchArg(optarg, "Rio_de_Janeiro")) {
720 c = 8;
721 }
722 }
723 if ((c < 1) || (c > 8)) {
724 errflg = 1;
725 } else {
726 Startup = c;
727 }
728 }
729 break;
730
731 case 'd': /* Display <name> */
732 { char *d = Displays;
733
734 if (d == NULL) {
735 Displays = malloc(strlen(optarg) + 3);
736 sprintf(Displays, "{%s}", optarg);
737
738 if (strchr(optarg, ':') != NULL) {
739 FirstDisplay = malloc(strlen(optarg) + 1);
740 strcpy(FirstDisplay, optarg);
741 } else {
742 FirstDisplay = malloc(strlen(optarg) + 3);
743 sprintf(FirstDisplay, "%s:0", optarg);
744 }
745 } else {
746 /* Implicitly set multi player mode if multiple displays given. */
747 MultiPlayerMode = 1;
748 Displays = malloc(strlen(Displays) + strlen(optarg) + 4);
749 sprintf(Displays, "%s {%s}", d, optarg);
750 free(d);
751 }
752 }
753 break;
754
755 case '?':
756 errflg++;
757 break;
758 }
759 }
760
761 if (!errflg &&
762 !tkMustExit) {
763 if ((Startup == -1) ||
764 (Startup == -2)) {
765 /* Generate New City */
766 if ((optind != argc) && (optind != argc - 1)) {
767 errflg = 1;
768 } else {
769 if (optind == argc - 1)
770 StartupName = argv[optind];
771 }
772 } else if (Startup > 0) {
773 /* Scenario */
774 } else if (optind == argc - 1) {
775 /* Load City */
776 Startup = -2;
777 StartupName = argv[optind];
778 } else if (optind == argc) {
779 /* No arguments */
780 } else {
781 errflg = 1;
782 }
783 }
784
785 if (errflg) {
786 fprintf(stderr,
787"usage: %s\n", argv[0]);
788 fprintf(stderr,
789" [-s(cenario) number|name]\n");
790 fprintf(stderr,
791" [-g(enerate random map and start playing)\n");
792 fprintf(stderr,
793" [-l(evel) number|name]\n");
794 fprintf(stderr,
795" [-w(ire mode: use X11 networking without shared memory)]\n");
796 fprintf(stderr,
797" [-t(ty mode: interactive TCL session on stdin/stdout)]\n");
798 fprintf(stderr,
799" [-c(olormap mode: create own X11 colormap on 8 bit screens)]\n");
800 fprintf(stderr,
801" [-S(ugar mode: enable OLPC Sugar user interface integration)]\n");
802 fprintf(stderr,
803" [-m(ulti player mode: enable adding multiple players via X11)]\n");
804 fprintf(stderr,
805" [NewCityName]\n");
806 fprintf(stderr,
807" [SavedFileName.city]\n");
808 fprintf(stderr,
809"The game level and NewCityName argument are optional, and only apply when\n");
810 fprintf(stderr,
811"starting a new city or generating new terrain.\n");
812 fprintf(stderr,
813"Game levels include: 1: Easy, 2: Medium, 3: Hard\n");
814 fprintf(stderr,
815"Scenarios include: 1: Dullsville, 2: San_Francisco, 3: Hamburg, 4: Bern,\n");
816 fprintf(stderr,
817" 5: Tokyo, 6: Detroit, 7: Boston, 8: Rio_de_Janeiro\n");
818 fflush(stderr);
819 sim_exit(0); // Just sets tkMustExit and ExitReturn
820 }
821
822 if ((!tkMustExit) &&
823 (Displays == NULL)) {
824 char *d = getenv("DISPLAY");
825
826 if (d == NULL) d = ":0";
827
828 Displays = malloc(strlen(d) + 3);
829 sprintf(Displays, "{%s}", d);
830 if (strchr(d, ':') != NULL) {
831 FirstDisplay = malloc(strlen(d) + 1);
832 strcpy(FirstDisplay, d);
833 } else {
834 FirstDisplay = malloc(strlen(d) + 3);
835 sprintf(FirstDisplay, "%s:0", d);
836 }
837 }
838
839 if (!tkMustExit) {
840 env_init();
841 }
842
843 if (!tkMustExit) {
844 tk_main();
845 }
846
847 exit (ExitReturn);
848}
Impressum, Datenschutz