Annotation of micropolis/src/sim/sim.c, revision 1.1.1.1

1.1       root        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  [email protected].
                      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.