Annotation of researchv10no/games/atc/atc.c, revision 1.1

1.1     ! root        1: /* atc: simulate an air traffic controller at work */
        !             2: 
        !             3: #define NRAND 1
        !             4: #define die nrand
        !             5: 
        !             6: #include <stdio.h>
        !             7: #include <sys/ttyio.h>
        !             8: #include <sys/param.h>
        !             9: #include <sys/timeb.h>
        !            10: #include <ctype.h>
        !            11: #include <signal.h>
        !            12: #include <pwd.h>
        !            13: #include "ahdr.h"
        !            14: 
        !            15: #define SYNTAX "Usage: atc [-s=<seed>] [-a=<airspace>] [-t=<time>]\n"
        !            16: 
        !            17: /* size of terminal capability buffer */
        !            18: #define TCSIZE 1024
        !            19: 
        !            20: int cmdx; /* command located using same cursor positioning as screen */
        !            21: int cmdy; /* usually will be at 24 lines down */
        !            22: 
        !            23: char screen[MAXWIDTH][MAXHEIGHT]; /* contents of screen when no planes */
        !            24: 
        !            25: char *flowfile = 0;             /* no default flow patterns */
        !            26: char *airfile = AIRFILE;
        !            27: char *airspace = {"Apple1"};    /* default airspace is as on Apple */
        !            28: char *protofile = 0;            /* no default protocol file */
        !            29: FILE *proto;                    /* stays open all the time if protocol */
        !            30: char *moviefile = 0;            /* if in movie mode, here's the file */
        !            31: FILE *movie;                    /* and the file descriptor */
        !            32: int nextmovie;                  /* next time for a moviefile command */
        !            33: char *mcommand;                 /* next movie command */
        !            34: int width,height; /* these values set in the airspace file */
        !            35: char *bigname = 0;              /* megastatistics file */
        !            36: FILE *bigstatsfile;             /* megastatistics stream */
        !            37: 
        !            38: struct flow fpath[MAXPATHS];
        !            39: int maxflow;
        !            40: int npaths;
        !            41: 
        !            42: int nentry = 0; /* number of entries into the board */
        !            43: struct pstruct entry[EMAX];
        !            44: 
        !            45: int nairport = 0;
        !            46: struct pstruct airport[AMAX];
        !            47: 
        !            48: int nnavaid = 0;
        !            49: struct pstruct navaid[NMAX];
        !            50: 
        !            51: int nplanes = PMAX;
        !            52: struct astruct plane[PMAX];
        !            53: 
        !            54: int initseed,seed,game_time,initgame_time,last_update;
        !            55: time_t start_time;      /* real time in seconds that game started */
        !            56: 
        !            57: time_t get_time();
        !            58: struct passwd *getpwuid();
        !            59: FILE *popen();
        !            60: 
        !            61: #define BUFSIZE 80      /* buffer for message */
        !            62: 
        !            63: int remain;
        !            64: 
        !            65: int bound = 0;          /* number of boundary errors */
        !            66: int system = 0;         /* system errors */
        !            67: int crash = 0;          /* crashed - out of fuel */
        !            68: int fuel = 0;           /* out of fuel on runway - tow truck */
        !            69: int goaround = 0;       /* missed an approach */
        !            70: int icmds = 0;          /* number of cmds issued (including deferred) */
        !            71: int cmds = 0;           /* number of cmds actually executed */
        !            72: 
        !            73: int fuelused = 0;
        !            74: 
        !            75: int inaptot=0,outaptot=0;   /* denominators for random entries/exits */
        !            76: int inawtot=0,outawtot=0;   /* for airports and airways */
        !            77: 
        !            78: char tcbuf[TCSIZE];
        !            79: char cmbuf[100];       /* buffer for cursor motion strings */
        !            80: char clbuf[100];       /* clear screen sequence */
        !            81: 
        !            82: int rubout = 0;
        !            83: 
        !            84: catchint(n)
        !            85:        int n;
        !            86: {
        !            87:        rubout = 1;
        !            88:        signal (n, catchint);
        !            89: }
        !            90: 
        !            91: struct sgttyb tty_setting;
        !            92: short tty_flags;
        !            93: 
        !            94: main(argc,argv)
        !            95: int argc;
        !            96: char **argv;
        !            97: {       register char *arg;
        !            98: 
        !            99:        char *ttype;
        !           100:        char *getenv();
        !           101: 
        !           102:        ttype = getenv("TERM");
        !           103:        if (ttype == NULL || *ttype == '\0' || tgetent (tcbuf, ttype) <= 0) {
        !           104:                fprintf (stderr, "cannot determine terminal type\n");
        !           105:                exit (1);
        !           106:        }
        !           107: 
        !           108:        /* get cursor motion and clear screen code into cmbuf and clbuf */
        !           109:        {
        !           110:                char *p;
        !           111:                p = cmbuf;
        !           112:                tgetstr ("cm", &p);
        !           113:                p = clbuf;
        !           114:                tgetstr ("cl", &p);
        !           115:        }
        !           116: 
        !           117:        ioctl(0, TIOCGETP, &tty_setting);
        !           118:        tty_flags = tty_setting.sg_flags;
        !           119:        seed = 0;
        !           120:        for (arg = *++argv; --argc; arg = *++argv) /* read args 1 at a time */
        !           121:        {   if (arg[0] == '-')
        !           122:                switch(arg[1])
        !           123:                {   case 's':
        !           124:                        if (arg[2] != '=') err(SYNTAX);
        !           125:                        seed = atoi(&arg[3]);
        !           126:                        break;
        !           127:                    case 'S':
        !           128:                        if (arg[2] != '=') err(SYNTAX);
        !           129:                        bigname = &arg[3];
        !           130:                        break;
        !           131:                    case 'a':
        !           132:                        if (arg[2] != '=') err(SYNTAX);
        !           133:                        airspace = &arg[3];
        !           134:                        break;
        !           135:                    case 'u':
        !           136:                        if (arg[2] != '=') err(SYNTAX);
        !           137:                        airfile = &arg[3];
        !           138:                        break;
        !           139:                    case 't':
        !           140:                        if (arg[2] != '=') err(SYNTAX);
        !           141:                        initgame_time = game_time = 59 + 60 * atoi(&arg[3]);
        !           142:                        break;
        !           143:                    case 'f':
        !           144:                        if (arg[2] != '=') err(SYNTAX);
        !           145:                        flowfile = &arg[3];
        !           146:                        break;
        !           147:                    case 'p':   /* run a protocol */
        !           148:                        if (arg[2] != '=') err(SYNTAX);
        !           149:                        protofile = &arg[3];
        !           150:                        break;
        !           151:                    case 'm':   /* movie mode */
        !           152:                        if (arg[2] != '=') err(SYNTAX);
        !           153:                        moviefile = &arg[3];
        !           154:                        break;
        !           155:                    default :
        !           156:                        err("Bad arg: %s\n",arg);
        !           157:                }
        !           158:        }
        !           159:        init(); /* set up flight plans, initialize screen */
        !           160:        while (command());      /* get commands from user */
        !           161:        done(1);
        !           162:        exit(0);
        !           163: }
        !           164: 
        !           165: #define CMDSIZE 40
        !           166: 
        !           167: int inter;      /* non-zero if an alarm went off */
        !           168: intp()  /* process interrupt from alarm */
        !           169: {       inter++;
        !           170: }
        !           171: 
        !           172: 
        !           173: command()
        !           174: {       time_t now;
        !           175:        char cmd[CMDSIZE];
        !           176:        char *c,utype,*d;
        !           177:        int i,j;
        !           178: 
        !           179:        for (utype = i = *(c=cmd) = 0; utype != RETURN; )
        !           180:        {
        !           181:                if (moviefile) game_time--;     /* 1 sec at a time? */
        !           182:                else
        !           183:                {       now = get_time();
        !           184:                        game_time = initgame_time - (now - start_time);
        !           185:                }
        !           186:                if (remain == 0) return(0);
        !           187:                if (game_time < 0)
        !           188:                {       report(OUTOFTIME,0,0);
        !           189:                        return(0);
        !           190:                }
        !           191:                if (i == 0)     /* preserve partial command */
        !           192:                {       cursor(cmdx,cmdy);
        !           193:                        printf("<%.2d> COMMAND:                  ",game_time/60);
        !           194:                }
        !           195:                if (last_update - game_time >= UPDATE)
        !           196:                {       update();
        !           197:                        if (c != cmd) {BEEP;} /* cmd may be obsolete */
        !           198:                }
        !           199:                while (moviefile && game_time <= nextmovie)
        !           200:                {       if (bigname) pcmd(bigstatsfile,mcommand);
        !           201:                        if (protofile) pcmd(proto,mcommand);
        !           202:                        i = parse(mcommand);
        !           203:                        if (!i) return i;
        !           204:                        getmcmd();
        !           205:                }
        !           206:                if (moviefile) continue;        /* no longer accept inputs */
        !           207:                cursor(cmdx+7,cmdy);
        !           208:                for (j=0; j<i; j++) putchar(cmd[j]);
        !           209:                signal(SIGALRM,intp);/* catch the alarm if it goes off */
        !           210:                inter = 0;      /* set to >0 if the alarm goes off */
        !           211:                if (rubout) return 0;   /* user really wants to quit */
        !           212:                alarm(TIMEOUT); /* read for TIMEOUT sec unless he types */
        !           213:                utype = getchar() & 0177;
        !           214:                alarm(0);
        !           215:                if (inter > 0) continue; /* didn't type anything */
        !           216:                delmsg(cmdx,cmdy-1);    /* erase previous echo if he types */
        !           217:                cursor(cmdx+7,cmdy);
        !           218:                if (i != 2 || (*(c-1) != '*' && *(c-1) != ':'))
        !           219:                 if (*cmd != '!' || i == 0) /* don't shift CDL filename */
        !           220:                  if (*cmd != '@'|| i == 0) /* don't shift location descrip */
        !           221:                      if (utype >= 'a' && utype <= 'z')
        !           222:                        utype = utype - 'a' + 'A';
        !           223:                if (utype == INSMODE) utype = RETURN;
        !           224:                if ((*c++ = utype) != RETURN)
        !           225:                {       if (++i >= CMDSIZE) c--;
        !           226:                        else
        !           227:                        switch(utype)   /* echo something reasonable */
        !           228:                        { 
        !           229: #ifdef ANNARBOR
        !           230:                            case MIPAGE:/* check cursor controls */
        !           231:                                putchar(*--c = 'N');
        !           232:                                putchar(*++c = 'W');
        !           233:                                c++; i++;
        !           234:                                break;
        !           235:                            case HOME:
        !           236:                                putchar(*--c = 'N');
        !           237:                                c++;
        !           238:                                break;
        !           239:                            case PLPAGE:
        !           240:                                putchar(*--c = 'N');
        !           241:                                putchar(*++c = 'E');
        !           242:                                c++; i++;
        !           243:                                break;
        !           244:                            case MISRCH:
        !           245:                                putchar(*--c = 'W');
        !           246:                                c++;
        !           247:                                break;
        !           248:                            case UPARROW:
        !           249:                                putchar(*--c = '0');
        !           250:                                c++;
        !           251:                                break;
        !           252:                            case PLSRCH:
        !           253:                                putchar(*--c = 'E');
        !           254:                                c++;
        !           255:                                break;
        !           256:                            case LEFTARROW:
        !           257:                                putchar(*--c = 'S');
        !           258:                                putchar(*++c = 'W');
        !           259:                                c++; i++;
        !           260:                                break;
        !           261:                            case DOWNARROW:
        !           262:                                putchar(*--c = 'S');
        !           263:                                c++;
        !           264:                                break;
        !           265:                            case RIGHTARROW:
        !           266:                                putchar(*--c = 'S');
        !           267:                                putchar(*++c = 'E');
        !           268:                                c++; i++;
        !           269:                                break;
        !           270:                            case ':':   /* like a * */
        !           271:                                putchar('*');
        !           272:                                break;
        !           273: #endif
        !           274:                            case BS:
        !           275:                                if (i<=0) break;
        !           276:                                if (i==1) { i = 0; break; }
        !           277:                                putchar(BS);
        !           278:                                c--; c--; i--; i--;
        !           279:                                break;
        !           280:                            default: putchar(utype); break;
        !           281:                        }
        !           282:                }
        !           283:        }
        !           284:        *c = 0;
        !           285:        if (bigname) pcmd(bigstatsfile,cmd);
        !           286:        if (protofile) pcmd(proto,cmd);
        !           287:        return(parse(cmd));
        !           288: }
        !           289: 
        !           290: pcmd(file,cmd)  /* protocol a command */
        !           291: FILE *file;
        !           292: char *cmd;
        !           293: {       register char *s;
        !           294: 
        !           295:        if (file == proto)
        !           296:             fprintf(file,"%5d: ",game_time);
        !           297:        else fprintf(file,"%5d: ",initgame_time - game_time);
        !           298:        for (s = cmd; *s && *s != RETURN; s++) fputc(*s,file);
        !           299:        fputc('\n',file);
        !           300: }
        !           301: 
        !           302: parse(cmd)      /* command is terminated by RETURN */
        !           303: register char *cmd;
        !           304: {       time_t now;
        !           305:        register int i;
        !           306:        register struct astruct *pl;
        !           307:        char dest;
        !           308:        char *fullcmd;
        !           309:        char ubuf[10];
        !           310: 
        !           311:        fullcmd = cmd;
        !           312:        switch(*cmd)        /* parse 1 letter at a time */
        !           313:        {   case ' ':  /* time advance */
        !           314:                sprintf (ubuf, "%d", UPDATE);
        !           315:                echo("%s\" - ROGER",ubuf);
        !           316:                now = get_time();
        !           317:                start_time = last_update - UPDATE - 1 - initgame_time + now;
        !           318:                break;
        !           319:            case '$':
        !           320:                return(0);
        !           321:            case '!':   /* read a file of clearance directive lists */
        !           322:                readcdl(++cmd);
        !           323:                break;
        !           324:            case '@':   /* get a monitoring command */
        !           325:                getmon(++cmd);
        !           326:                break;
        !           327:            default:    /* should be airplane id */
        !           328:                /* ASSUMPTION HERE: aircraft are A-Z */
        !           329:                if (*cmd < 'A' || *cmd > 'Z')
        !           330:                {       echo("%s - UNABLE",fullcmd);
        !           331:                        BEEP;
        !           332:                        break;
        !           333:                }
        !           334:                for (pl = &plane[i=0]; i < nplanes; i++,pl++)
        !           335:                        if (pl->a_id == *cmd) break;
        !           336:                if (i == nplanes)
        !           337:                {       echo("%s - NOT ACTIVE",fullcmd);
        !           338:                        BEEP;
        !           339:                        break;
        !           340:                }
        !           341: 
        !           342:                if (cmd[1] == '?')      /* o.k. to cancel plans */
        !           343:                {       if (pl->a_active != ACTIVE &&
        !           344:                            pl->a_active != WAITING)
        !           345:                        {       echo("%s - NOT ACTIVE",fullcmd);
        !           346:                                BEEP;
        !           347:                                break;
        !           348:                        }
        !           349:                }
        !           350:                else if (cmd[1] == RETURN)     /* info request only */
        !           351:                {       if (pl->a_active != ACTIVE &&
        !           352:                            pl->a_active != APPROACHING &&
        !           353:                            pl->a_active != WAITING)
        !           354:                        {       echo("%s - NOT ACTIVE",fullcmd);
        !           355:                                BEEP;
        !           356:                                break;
        !           357:                        }
        !           358:                }
        !           359:                else
        !           360:                {       if (pl->a_active != ACTIVE && pl->a_active != WAITING)
        !           361:                        {       echo("%s - NOT ACTIVE",fullcmd);
        !           362:                                BEEP;
        !           363:                                break;
        !           364:                        }
        !           365:                        if (pl->a_active==ACTIVE && pl->a_nextz == 0 && cmd[1]!=RETURN)
        !           366:                        {       echo("%s - LANDING",fullcmd);
        !           367:                                BEEP;
        !           368:                                break;
        !           369:                        }
        !           370:                }
        !           371:                switch(*++cmd)  /* parse second char */
        !           372:                {   case RETURN:  /* info request */
        !           373:                        strip(pl,cmdy+1,VERBOSE);
        !           374:                        break;
        !           375:                    case 'A':   /* change altitude */
        !           376:                        if (*++cmd < '0' || *cmd > '5')
        !           377:                        {       echo("%s - UNABLE",fullcmd);
        !           378:                                BEEP;
        !           379:                        }
        !           380:                        else
        !           381:                        {       pl->a_nextz = *cmd - '0';
        !           382:                                echo("%s - ROGER",fullcmd);
        !           383:                                cmds++;
        !           384:                                icmds++;
        !           385:                        }
        !           386:                        break;
        !           387:                    case 'H':   /* hold at beacon */
        !           388:                        pl->a_hold = 1;
        !           389:                        pl->a_clear = 0;
        !           390:                        echo("%s - ROGER",fullcmd);
        !           391:                        cmds++;
        !           392:                        icmds++;
        !           393:                        break;
        !           394:                    case 'L':   /* left turn */
        !           395:                        rdturn(pl,'L',++cmd,fullcmd);
        !           396:                        break;
        !           397:                    case 'R':   /* right turn */
        !           398:                        rdturn(pl,'R',++cmd,fullcmd);
        !           399:                        break;
        !           400:                    case 'T':   /* shortest turn */
        !           401:                        rdturn(pl,'T',++cmd,fullcmd);
        !           402:                        break;
        !           403:                    case '*':   /* clearance at navaid */
        !           404:                    case ':':
        !           405:                        dest = *++cmd;
        !           406:                        for (i=0; i<nentry; i++) /* vector to entry? */
        !           407:                                if (dest == entry[i].p_sym) break;
        !           408:                        if (pl->a_hold == 1) pl->a_hold = 0;
        !           409:                        if (i<nentry)
        !           410:                        {       echo("%s - ROGER",fullcmd);
        !           411:                                pl->a_clear = dest;
        !           412:                                cmds++;
        !           413:                                icmds++;
        !           414:                                break;
        !           415:                        }
        !           416:                        for (i=0; i<nairport; i++)
        !           417:                                if (dest == airport[i].p_sym) break;
        !           418:                        if (i<nairport)
        !           419:                        {       echo("%s - ROGER",fullcmd);
        !           420:                                pl->a_clear = dest;
        !           421:                                cmds++;
        !           422:                                icmds++;
        !           423:                                break;
        !           424:                        }
        !           425:                        echo("%s - UNABLE",fullcmd);
        !           426:                        BEEP;
        !           427:                        break;
        !           428:                    case '?':   /* delete delayed commands */
        !           429:                        ddelay(pl);
        !           430:                        echo("%s - ROGER",fullcmd);
        !           431:                        cmds++;
        !           432:                        icmds++;
        !           433:                        break;
        !           434:                    default:    /* airport id? - maybe cursor motions? */
        !           435:                        echo("%s - UNABLE",fullcmd);
        !           436:                        BEEP;
        !           437:                        break;
        !           438:                }
        !           439:        }
        !           440:        return(1);
        !           441: }
        !           442: 
        !           443: getmon(cmd)     /* get monitor command from command line */
        !           444: register char *cmd;
        !           445: {       int x,y;
        !           446:        register char *start;
        !           447: 
        !           448:        start = cmd;
        !           449:        if (getloc(cmd,&x,&y) == 0)     /* where did you say? */
        !           450:        {       echo("%s - BAD LOC SPEC",cmd);
        !           451:                BEEP;
        !           452:                return;
        !           453:        }
        !           454:        while (*cmd)    /* pick up each command that happens here */
        !           455:        {       while (*cmd && *cmd != ',') cmd++;
        !           456:                if (*cmd == 0) return; /* read last command */
        !           457:                putlist(start,x,y,++cmd); /* put the next command on a list */
        !           458:        }
        !           459: }
        !           460: 
        !           461: ddelay(pl)      /* delete any delayed commands from this plane's list */
        !           462: struct astruct *pl;
        !           463: {       struct list *l,*next;
        !           464: 
        !           465:        if (pl->a_plan == 0) return;
        !           466:        for (l = pl->a_plan; l; l = next)
        !           467:        {       next = l->l_next;
        !           468:                free(l);
        !           469:        }
        !           470:        pl->a_plan = 0;
        !           471: }
        !           472: 
        !           473: putlist(start,x,y,cmd) /* put some commands on the list for a plane */
        !           474: char *start;
        !           475: int x,y;
        !           476: char *cmd;
        !           477: {       register struct list *l;
        !           478:        register struct astruct *p;
        !           479:        register char *c,*d;
        !           480:        int i;
        !           481: 
        !           482:        d = cmd;
        !           483:        for (i = 0; cmd[i] != ',' && cmd[i] != 0 && cmd[i] != RETURN; i++)
        !           484:          if (i != 2 || (cmd[i-1] != '*' && cmd[i-1] != ':'))
        !           485:            if (cmd[i] >= 'a' && cmd[i] <= 'z') cmd[i] += 'A' - 'a';
        !           486:        for (p = &plane[i = 0]; i < nplanes; i++,p++)
        !           487:                if (p->a_id == *cmd) break;
        !           488:        if (i == nplanes)
        !           489:        {       echo("BAD PLANE SPEC: %s",cmd);
        !           490:                BEEP;
        !           491:                return;
        !           492:        }
        !           493:        l = p->a_plan;  /* go to the CDL for this plane */
        !           494:        if (p->a_plan == 0)
        !           495:                l = p->a_plan = (struct list *) malloc(sizeof (struct list));
        !           496:        else
        !           497:        {       for (l = p->a_plan; l->l_next != 0; l = l->l_next); /* eol */
        !           498:                l->l_next = (struct list *) malloc(sizeof (struct list));
        !           499:                l = l->l_next;
        !           500:        }
        !           501:        l->l_next = 0;
        !           502:        l->l_x = x;
        !           503:        l->l_y = y;
        !           504:        c = l->l_cmd;
        !           505:        while (*cmd != ',' && *cmd != 0 && *cmd != RETURN)
        !           506:                *c++ = *cmd++;
        !           507:        *c++ = RETURN;
        !           508:        *c = 0;
        !           509:        for (c = d; *c; c++) if (*c == RETURN) *c = 0; /* return damages dspla*/
        !           510:        echo("%s - WILCO",d);
        !           511:        icmds++;
        !           512:        /* copy the verbatim direction used by the guy */
        !           513:        for (c = start, d = l->l_loc; *c != ','; *d++ = *c++);
        !           514:        *d = 0;
        !           515: }
        !           516: 
        !           517: 
        !           518: getloc(cmd,px,py)       /* get location description from a monitor command */
        !           519: char *cmd;
        !           520: int *px,*py;
        !           521: {       register char l,*m;     /* location */
        !           522:        register int i;
        !           523:        register struct pstruct *p;
        !           524:        int dx,dy;
        !           525:        char buf[300];
        !           526: 
        !           527:        l = *(m = cmd);
        !           528:        p = 0;
        !           529:        for (i = 0; i < nentry; i++)
        !           530:                if (entry[i].p_sym == l) p = &entry[i];
        !           531:        for (i = 0; i < nairport; i++)
        !           532:                if (airport[i].p_sym == l) p = &airport[i];
        !           533:        for (i = 0; i < nnavaid; i++)
        !           534:                if (navaid[i].p_sym == l) p = &navaid[i];
        !           535:        if (p == 0) return 0;
        !           536:        *px = p->p_x;
        !           537:        *py = p->p_y;
        !           538:        m++;
        !           539:        while (*m != ',')     /* read through the other directions */
        !           540:        {       dx = dy = 0;
        !           541:                switch(*m)      /* NSEW */
        !           542:                {   case 'n': dy = -1; break;
        !           543:                    case 's': dy =  1; break;
        !           544:                    case 'e': dx =  1; break;
        !           545:                    case 'w': dx = -1; break;
        !           546:                    default:
        !           547:                        sprintf(buf,"Got %c instead of n,s,e,w",*m);
        !           548:                        msg(cmdx,cmdy+3,buf);
        !           549:                        return 0;
        !           550:                }
        !           551:                if      (*++m == 'w') { dx = -1; m++;}  /* NW or SW */
        !           552:                else if (*m   == 'e') { dx =  1; m++;}  /* NE or SE */
        !           553:                if (*m < '0' || *m > '9')
        !           554:                {       sprintf(buf,"Got %c instead of digit",*m);
        !           555:                        msg(cmdx,cmdy+3,buf);
        !           556:                        return 0;
        !           557:                }
        !           558:                for (i = 0; *m >= '0' && *m <= '9'; m++)
        !           559:                        i = 10 * i + *m - '0';
        !           560:                *px += i * dx;
        !           561:                *py += i * dy;
        !           562:        }
        !           563:        return 1;
        !           564: }
        !           565: 
        !           566: readcdl(fname)  /* fname points at CDL filename, \r-terminated */
        !           567: char *fname;
        !           568: {       FILE *cdlfile;
        !           569:        char *p;
        !           570: 
        !           571:        while (*fname == ' ') fname++;  /* skip initial blanks */
        !           572:        for (p = fname; *p && *p != RETURN; p++); /* remove newline */
        !           573:        *p = 0;
        !           574:        if ((cdlfile = fopen(fname,"r")) == NULL)
        !           575:        {       echo("Cannot open %s",fname);
        !           576:                return;
        !           577:        }
        !           578:        echo("Reading CDL file...",0);
        !           579:        fclose(cdlfile);
        !           580: }
        !           581: 
        !           582: 
        !           583: rdturn(pl,dir,cmd,fullcmd)
        !           584: struct astruct *pl;
        !           585: char dir;
        !           586: char *cmd,*fullcmd;
        !           587: {       int i,ok,newx,newy,turncount;
        !           588: 
        !           589:        if (pl->a_nextz == 0)
        !           590:        {       echo("%s - WRONG WAY",fullcmd);
        !           591:                BEEP;
        !           592:                return;
        !           593:        }
        !           594:        ok = 1; /* check whether this is a legal command */
        !           595:        newx = newy = 0;
        !           596:        for (i=0; i<2; i++)     /* look at next 2 chars */
        !           597:        switch(cmd[i])
        !           598:        {   case RETURN:
        !           599:                if (i == 0)
        !           600:                {       echo("%s - WHICH WAY?",fullcmd);
        !           601:                        BEEP;
        !           602:                        return;
        !           603:                }
        !           604:                break;
        !           605:            case '0':
        !           606:                if (i == 1)     /* can't be second char */
        !           607:                {       ok = 0;
        !           608:                        break;
        !           609:                }
        !           610:                pl->a_dxnew = 0;
        !           611:                pl->a_dynew = 0;
        !           612:                pl->a_turn = 0;
        !           613:                pl->a_clear = 0;
        !           614:                pl->a_hold = 0;
        !           615:                echo("%s - ROGER",fullcmd);
        !           616:                cmds++;
        !           617:                icmds++;
        !           618:                return;
        !           619:            case 'N':
        !           620:                newy = -1;
        !           621:                break;
        !           622:            case 'S':
        !           623:                newy = 1;
        !           624:                break;
        !           625:            case 'E':
        !           626:                newx = 1;
        !           627:                break;
        !           628:            case 'W':
        !           629:                newx = -1;
        !           630:                break;
        !           631:            default:    /* numbers (e.g.) no longer acceptable */
        !           632:                ok = 0;
        !           633:                break;
        !           634:        }
        !           635:        if (ok)
        !           636:        {       echo("%s - ROGER",fullcmd);
        !           637:                cmds++;
        !           638:                icmds++;
        !           639:                pl->a_turn = dir;       /* will replace 'T' with 'L' or 'R' */
        !           640:                pl->a_dxnew = newx; pl->a_dynew = newy;
        !           641:                pl->a_hold = pl->a_clear = 0;
        !           642:                if (dir == 'T')
        !           643:                {       newx = pl->a_dx; /* start with this direction */
        !           644:                        newy = pl->a_dy; /* and turn until done */
        !           645:                        for (turncount = 1; turncount < 9; turncount++)
        !           646:                            if (turn(&newx,&newy,'L',pl->a_dxnew,pl->a_dynew))
        !           647:                                break;
        !           648:                        if (turncount <= 4) pl->a_turn = 'L';
        !           649:                        else pl->a_turn = 'R';
        !           650:                }
        !           651:        }
        !           652:        else
        !           653:        {       echo("%s - UNABLE",fullcmd);
        !           654:                BEEP;
        !           655:        }
        !           656: }
        !           657: 
        !           658: echo(format,cmd)
        !           659: char *format,*cmd;
        !           660: {       char *c;
        !           661:        char mbuf[BUFSIZE];
        !           662: 
        !           663:        for (c=cmd; *c; c++) if (*c == RETURN) *c = 0;
        !           664:        sprintf(mbuf,format,cmd);
        !           665:        msg(cmdx,cmdy-1,mbuf);
        !           666: }
        !           667: 
        !           668: int parity = 0; /* props move every other update */
        !           669: 
        !           670: update()
        !           671: {       parity = 1 - parity;
        !           672:        last_update -= UPDATE;  /* must average out to every UPDATE secs */
        !           673:        moveplanes();
        !           674:        printplans();
        !           675:        if (bigname) activity();
        !           676: }
        !           677: 
        !           678: activity()      /* number of active planes to megastats file */
        !           679: {       register int i,active,waiting,approaching,planned;
        !           680:        struct astruct *p;
        !           681: 
        !           682:        for (i=active=waiting=approaching=planned=0; i < nplanes; i++)
        !           683:        {       p = &plane[i];
        !           684:                switch(p->a_active)
        !           685:                {   case ACTIVE:
        !           686:                        active++;
        !           687:                        break;
        !           688:                    case WAITING:
        !           689:                        waiting++;
        !           690:                        break;
        !           691:                    case APPROACHING:
        !           692:                        approaching++;
        !           693:                        break;
        !           694:                }
        !           695:                if (p->a_plan && p->a_active != DONE) planned++;
        !           696:        }
        !           697:        fprintf(bigstatsfile,"%5d: %d active, %d approaching, %d waiting.  ",
        !           698:                initgame_time - game_time, active,approaching,waiting);
        !           699:        fprintf(bigstatsfile,"%d planned.\n",planned);
        !           700:        for (i = 0; i < nplanes; i++)
        !           701:        {       int a;
        !           702: 
        !           703:                p = &plane[i];
        !           704:                a = p->a_active;
        !           705:                if (a == ACTIVE || a == APPROACHING || a == WAITING)
        !           706:                {       p->a_load += active;
        !           707:                        p->a_ticks++;
        !           708:                        p->a_planned += planned;
        !           709:                }
        !           710:                if (a == APPROACHING || a == WAITING)
        !           711:                {       p->a_aprev += active;
        !           712:                        p->a_prev++;
        !           713:                        p->a_pprev += planned;
        !           714:                        p->a_pplanned = (p->a_plan? YES : NO);
        !           715:                }
        !           716:        }
        !           717: }
        !           718: 
        !           719: moveplanes()
        !           720: {       register struct astruct *pl;
        !           721:        register int i,j;
        !           722:        register int nextx,nexty;
        !           723:        int ax,ay,oldx,oldy;
        !           724:        struct pstruct *dst;
        !           725: 
        !           726:        for (pl = &plane[i = 0]; i < PMAX; i++, pl++)
        !           727:        {       if (parity && pl->a_type == PROP)
        !           728:                {       pl->a_lastz = pl->a_z;
        !           729:                        if (pl->a_active == LANDING) pl->a_active = DONE;
        !           730:                        continue;
        !           731:                }
        !           732:                switch(pl->a_active)
        !           733:                {   case INACTIVE:
        !           734:                        if (initgame_time - game_time + FPTHRESH>= pl->a_stime
        !           735:                            && !pl->a_sair)
        !           736:                                pl->a_active = APPROACHING;
        !           737: 
        !           738:                    case APPROACHING:
        !           739:                        if (initgame_time - game_time>= pl->a_stime)
        !           740:                        {       pl->a_active = ACTIVE;
        !           741:                                if (pl->a_sair) pl->a_active = WAITING;
        !           742:                                nextx = pl->a_x;
        !           743:                                nexty = pl->a_y;
        !           744:                        }
        !           745:                        break;
        !           746: 
        !           747:                    case LANDING: /* to allow for conflicts */
        !           748:                        pl->a_active = DONE;
        !           749:                        break;
        !           750: 
        !           751:                    case ACTIVE:
        !           752:                        pl->a_dist++;   /* increment distance traveled */
        !           753:                        nextx = pl->a_x + pl->a_dx;
        !           754:                        nexty = pl->a_y + pl->a_dy;
        !           755:                        if (nextx < 0 || nexty < 0 ||
        !           756:                            nextx >= width || nexty >= height)
        !           757:                        {       leavescreen(pl);
        !           758:                                break;
        !           759:                        }
        !           760: 
        !           761:                        /* turning? */
        !           762:                        if (pl->a_turn)   /* turn 1 tick in right direction */
        !           763:                            if (turn(&pl->a_dx,&pl->a_dy,
        !           764:                                pl->a_turn,pl->a_dxnew,pl->a_dynew))
        !           765:                                  pl->a_turn = pl->a_dxnew = pl->a_dynew = 0;
        !           766: 
        !           767: 
        !           768:                        if (pl->a_dair) /* landing? */
        !           769:                        {       dst = &airport[pl->a_dest];
        !           770:                                ax = dst->p_x;
        !           771:                                ay = dst->p_y;
        !           772:                                if (ax == nextx && ay == nexty)
        !           773:                                    if (pl->a_z == 0 &&
        !           774:                                          pl->a_dx == dst->p_dx &&
        !           775:                                          pl->a_dy == dst->p_dy)
        !           776:                                    {   pl->a_active = LANDING;  /* landed */
        !           777:                                        erase(pl->a_x,pl->a_y);
        !           778:                                        pl->a_x = nextx;
        !           779:                                        pl->a_y = nexty;
        !           780:                                        remain--;
        !           781:                                    }
        !           782:                                    else if (pl->a_nextz == 0) /* flyby */
        !           783:                                    {   pl->a_nextz = 1; /* down too late*/
        !           784:                                        goaround++;
        !           785:                                        report(GOAROUND,pl);
        !           786:                                    }
        !           787:                        }
        !           788: 
        !           789:                        /* changing altitude? */
        !           790:                        if (pl->a_z > pl->a_nextz)
        !           791:                                pl->a_lastz = pl->a_z--;
        !           792:                        else if (pl->a_z < pl->a_nextz)
        !           793:                                pl->a_lastz = pl->a_z++;
        !           794:                        else pl->a_lastz = pl->a_z;
        !           795: 
        !           796:                        /* out of fuel? */
        !           797:                        if (--pl->a_fuel <= 0)
        !           798:                        {       crash++;
        !           799:                                report(CRASH,pl);
        !           800:                                pl->a_active = DONE;
        !           801:                                remain--;
        !           802:                                erase(pl->a_x,pl->a_y);
        !           803:                        }
        !           804:                        if (pl->a_type == JET) fuelused += 5;
        !           805:                        else fuelused += 1;
        !           806:                        break;
        !           807: 
        !           808:                    case WAITING:  /* waiting for takeoff */
        !           809:                        if (--pl->a_fuel <= 0)  /* out of fuel on ground? */
        !           810:                        {       fuel++;
        !           811:                                if (bigname) freport(pl);
        !           812:                                report(FUEL,pl);
        !           813:                                pl->a_active = DONE;
        !           814:                                remain--;
        !           815:                        }
        !           816:                        if (pl->a_nextz != 0)
        !           817:                        {       pl->a_z++;      /* take off */
        !           818:                                pl->a_active = ACTIVE;
        !           819:                                pl->a_dist++;
        !           820:                        }
        !           821:                        nextx = pl->a_x + pl->a_dx;
        !           822:                        nexty = pl->a_y + pl->a_dy;
        !           823: 
        !           824:                        /* turning? */
        !           825:                        if (pl->a_turn)   /* turn 1 tick in right direction */
        !           826:                            if (turn(&pl->a_dx,&pl->a_dy,
        !           827:                                pl->a_turn,pl->a_dxnew,pl->a_dynew))
        !           828:                                  pl->a_turn = pl->a_dxnew = pl->a_dynew = 0;
        !           829: 
        !           830:                        if (pl->a_type == JET) fuelused += 5;
        !           831:                        else fuelused += 1;
        !           832:                        break;
        !           833: 
        !           834:                    case DONE:  /* off the screen */
        !           835:                        break;
        !           836:                }
        !           837:                if (pl->a_active != ACTIVE) continue;
        !           838:                oldx = pl->a_x;
        !           839:                oldy = pl->a_y;
        !           840:                pl->a_x = nextx;
        !           841:                pl->a_y = nexty;
        !           842:                cursor(nextx,nexty);
        !           843:                printf("%c%c",pl->a_id,(pl->a_z>9? '^' : pl->a_z+'0'));
        !           844:                erase(oldx,oldy);
        !           845:                if (pl->a_hold || pl->a_clear)
        !           846:                        for (j = 0; j < nnavaid; j++)   /* at a navaid? */
        !           847:                                if (screen[nextx][nexty] == navaid[j].p_sym)
        !           848:                                {       donavaid(pl);   /* right navaid? */
        !           849:                                        break;
        !           850:                                }
        !           851:        }
        !           852:        conflict();
        !           853:        delays();       /* execute any applicable delayed commands */
        !           854: }
        !           855: 
        !           856: freport(pl)     /* report to big stats file about tow truck */
        !           857: struct astruct *pl;
        !           858: {
        !           859:        fprintf(bigstatsfile,"%5d: %c out of fuel on runway.\n",
        !           860:                initgame_time - game_time,pl->a_id);
        !           861: }
        !           862: 
        !           863: delays()        /* execute any applicable delayed actions */
        !           864: {       register struct astruct *p;
        !           865:        register int i;
        !           866:        register struct list *l,*last;
        !           867: 
        !           868:        /* for each plane, if it is active and if it has a command pending,
        !           869:         * and if it is at the right place for the command, then execute it.
        !           870:         */
        !           871:        for (i = 0; i < PMAX; i++)
        !           872:        {       p = &plane[i];
        !           873:                if (p->a_active != ACTIVE) continue;
        !           874:                if (p->a_plan == 0) continue;
        !           875:                last = 0;
        !           876:                for (l = p->a_plan; l; )
        !           877:                {       if (p->a_x != l->l_x || p->a_y != l->l_y)
        !           878:                        {
        !           879:                                last = l;
        !           880:                                l = l->l_next;
        !           881:                        }
        !           882:                        else    /* it matched */
        !           883:                        {
        !           884:                                parse(l->l_cmd); /* execute the command */
        !           885: 
        !           886:                                /* now delete the command from the list */
        !           887:                                if (last == 0)  /* it was the first one */
        !           888:                                {       p->a_plan = l->l_next;
        !           889:                                        free(l);
        !           890:                                        l = p->a_plan;
        !           891:                                        /* last stays at 0 */
        !           892:                                }
        !           893:                                else
        !           894:                                {       last->l_next = l->l_next;
        !           895:                                        free(l);
        !           896:                                        l = last->l_next;
        !           897:                                        /* last stays where it was */
        !           898:                                }
        !           899:                        }
        !           900:                }
        !           901:        }
        !           902: }
        !           903: 
        !           904: donavaid(pl)    /* take appropriate action at navaid */
        !           905: struct astruct *pl; /* the plane has either been vectored or told to hold */
        !           906: {       register struct pstruct *d;
        !           907:        register int i;
        !           908: 
        !           909:        if (pl->a_hold)
        !           910:        {       pl->a_hold = 2; /* will be holding now */
        !           911:                pl->a_turn = 'L'; /* and turning continuously to the left */
        !           912:                pl->a_dxnew = pl->a_dx; /* until it reaches this heading agn*/
        !           913:                pl->a_dynew = pl->a_dy;
        !           914:        }
        !           915:        if (pl->a_clear)
        !           916:        {       pl->a_turn = pl->a_dxnew = pl->a_dynew = pl->a_hold = 0;
        !           917:                /* see what we're vectoring to */
        !           918:                for (d = &entry[i=0]; i < nentry; i++,d++)
        !           919:                        if (d->p_sym == pl->a_clear) break;
        !           920:                if (i != nentry)        /* yes, it was a navaid */
        !           921:                {       pl->a_dx = -d->p_dx;    /* opposite of entry heading*/
        !           922:                        pl->a_dy = -d->p_dy;
        !           923:                        pl->a_clear = 0;
        !           924:                        return;
        !           925:                }
        !           926:                for (d = &airport[i=0]; i < nairport; i++,d++)
        !           927:                        if (d->p_sym == pl->a_clear) break;
        !           928:                if (i == nairport) return; /* program bug - cleared to ?? */
        !           929:                pl->a_dx = d->p_dx; /* assume landing heading for airport */
        !           930:                pl->a_dy = d->p_dy;
        !           931:                pl->a_clear = 0;
        !           932: 
        !           933:                if (pl->a_hold == 1)
        !           934:                        pl->a_hold = pl->a_dxnew = pl->a_dynew = 0;
        !           935:                else if (pl->a_hold == 0)
        !           936:                        pl->a_dxnew = pl->a_dynew = 0;
        !           937:                return;
        !           938:        }
        !           939: }
        !           940: 
        !           941: turn(newx,newy,direc,dx,dy)     /* messy - enumeration of all cases */
        !           942: int *newx,*newy;        /* returned values of new heading */
        !           943: char direc;
        !           944: int dx,dy;
        !           945: {       int x,y;
        !           946: 
        !           947:        x = *newx;
        !           948:        y = *newy;
        !           949:        switch(direc)
        !           950:        {   case 'L': /* cases would be more efficient, but this is clearer*/
        !           951:                if (x== -1 && y== -1) {*newx= -1; *newy=  0; break;}
        !           952:                if (x== -1 && y==  0) {*newx= -1; *newy=  1; break;}
        !           953:                if (x== -1 && y==  1) {*newx=  0; *newy=  1; break;}
        !           954:                if (x==  0 && y== -1) {*newx= -1; *newy= -1; break;}
        !           955:                if (x==  0 && y==  1) {*newx=  1; *newy=  1; break;}
        !           956:                if (x==  1 && y== -1) {*newx=  0; *newy= -1; break;}
        !           957:                if (x==  1 && y==  0) {*newx=  1; *newy= -1; break;}
        !           958:                if (x==  1 && y==  1) {*newx=  1; *newy=  0; break;}
        !           959:                break;
        !           960:            case 'R':
        !           961:                if (x== -1 && y== -1) {*newx=  0; *newy= -1; break;}
        !           962:                if (x== -1 && y==  0) {*newx= -1; *newy= -1; break;}
        !           963:                if (x== -1 && y==  1) {*newx= -1; *newy=  0; break;}
        !           964:                if (x==  0 && y== -1) {*newx=  1; *newy= -1; break;}
        !           965:                if (x==  0 && y==  1) {*newx= -1; *newy=  1; break;}
        !           966:                if (x==  1 && y== -1) {*newx=  1; *newy=  0; break;}
        !           967:                if (x==  1 && y==  0) {*newx=  1; *newy=  1; break;}
        !           968:                if (x==  1 && y==  1) {*newx=  0; *newy=  1; break;}
        !           969:                break;
        !           970:        }
        !           971:        if (*newx == dx && *newy == dy) return(1);      /* finished turn */
        !           972:        else return(0);
        !           973: }
        !           974: 
        !           975: 
        !           976: report(error,plane1,plane2)
        !           977: int error;
        !           978: struct astruct *plane1,*plane2;
        !           979: {       char mbuf[BUFSIZE];
        !           980:        int i;
        !           981: 
        !           982:        putchar(BELL);
        !           983:        switch(error)
        !           984:        {   case FUEL:
        !           985:                sprintf(mbuf,"Tow truck called for %c (%c)",
        !           986:                        plane1->a_id,airport[plane1->a_start].p_sym);
        !           987:                break;
        !           988:            case CRASH:
        !           989:                sprintf(mbuf,"PLANE %c OUT OF GAS",plane1->a_id);
        !           990:                break;
        !           991:            case BOUND:
        !           992:                sprintf(mbuf,"Boundary error - %c",plane1->a_id);
        !           993:                break;
        !           994:            case SYSTEM:
        !           995:                sprintf(mbuf,"%c AND %c: SYSTEM ERROR",
        !           996:                        plane1->a_id, plane2->a_id);
        !           997:                break;
        !           998:            case GOAROUND:
        !           999:                sprintf(mbuf,"%c missed approach",plane1->a_id);
        !          1000:                break;
        !          1001:            case OUTOFTIME:
        !          1002:                sprintf(mbuf,"Out of time: %d remain",remain);
        !          1003:                break;
        !          1004:        }
        !          1005:        msg(cmdx,cmdy+2,mbuf);
        !          1006: }
        !          1007: 
        !          1008: 
        !          1009: 
        !          1010: leavescreen(pl)
        !          1011: struct astruct *pl;
        !          1012: {       struct pstruct *e;
        !          1013: 
        !          1014:        pl->a_active = DONE;
        !          1015:        pl->a_dist++;
        !          1016:        erase(pl->a_x,pl->a_y);
        !          1017:        remain--;
        !          1018:        e = &entry[pl->a_dest];
        !          1019:        if (pl->a_z == 5 && !pl->a_dair && /* leaving at non-airport, 5K' */
        !          1020:            screen[pl->a_x][pl->a_y] == e->p_sym &&  /* right exit */
        !          1021:            pl->a_dx == -e->p_dx && pl->a_dy == -e->p_dy && /* right direc */
        !          1022:            pl->a_turn == 0)    /* and not turning */
        !          1023:                return(0);
        !          1024:        bound++;
        !          1025:        if (bigname)
        !          1026:        {       fprintf(bigstatsfile,"%5d: Boundary error - plane %c ",
        !          1027:                        initgame_time - game_time,pl->a_id);
        !          1028:                fprintf(bigstatsfile,"left at %d000' ",pl->a_z);
        !          1029:                if (pl->a_nextz > pl->a_z)
        !          1030:                   fprintf(bigstatsfile,"climbing to %d000'",pl->a_nextz);
        !          1031:                if (pl->a_nextz < pl->a_z)
        !          1032:                   fprintf(bigstatsfile,"descending to %d000'",pl->a_nextz);
        !          1033:                fprintf(bigstatsfile,
        !          1034:                        "\n\tPosition: (%d,%d)    Bearing: ",pl->a_x,pl->a_y);
        !          1035:                if (pl->a_dy < 0) fprintf(bigstatsfile,"N");
        !          1036:                else if (pl->a_dy > 0) fprintf(bigstatsfile,"S");
        !          1037:                if (pl->a_dx > 0) fprintf(bigstatsfile,"E");
        !          1038:                else if (pl->a_dx < 0) fprintf(bigstatsfile,"W");
        !          1039:                if (pl->a_turn)
        !          1040:                {       fprintf(bigstatsfile," turning %c to ",pl->a_turn);
        !          1041:                        if (pl->a_dynew < 0) fprintf(bigstatsfile,"N");
        !          1042:                        else if (pl->a_dynew > 0) fprintf(bigstatsfile,"S");
        !          1043:                        if (pl->a_dxnew > 0) fprintf(bigstatsfile,"E");
        !          1044:                        else if (pl->a_dxnew < 0) fprintf(bigstatsfile,"W");
        !          1045:                }
        !          1046:                fprintf(bigstatsfile,".\n");
        !          1047:        }
        !          1048:        report(BOUND,pl);
        !          1049:        return(0);
        !          1050: }
        !          1051: 
        !          1052: conflict()      /* check each pair of planes for problems */
        !          1053: {       register struct astruct *q,*p;
        !          1054:        register int i,j,k;
        !          1055:        register int miss;
        !          1056: 
        !          1057:        for (p = &plane[k=1]; k < nplanes; k++,p++)
        !          1058:        {       if (p->a_active != ACTIVE && p->a_active != LANDING) continue;
        !          1059:                for (q = &plane[i=0]; i < k; i++,q++)
        !          1060:                {       if (q->a_active != ACTIVE) continue;
        !          1061:                        if (q->a_z != p->a_z && q->a_z != p->a_lastz &&
        !          1062:                            q->a_lastz != p->a_z && q->a_lastz != p->a_lastz)
        !          1063:                                continue;
        !          1064:                        miss = abs(q->a_x - p->a_x);
        !          1065:                        j = abs(q->a_y - p->a_y);
        !          1066:                        if (j>miss) miss=j;
        !          1067:                        if (miss < 3)   /* too close - system error */
        !          1068:                        {       system++;
        !          1069:                                if (bigname) bigsyserr(p,q);
        !          1070:                                report(SYSTEM,p,q);
        !          1071:                                break;
        !          1072:                        }
        !          1073:                }
        !          1074:        }
        !          1075: }
        !          1076: 
        !          1077: bigsyserr(p,q)  /* spew sys err info into the big stats file */
        !          1078: struct astruct *p,*q;
        !          1079: {
        !          1080:        fprintf(bigstatsfile,
        !          1081:                "%5d: System error between %c (%d,%d,%d000) and %c (%d,%d,%d000)\n",
        !          1082:                initgame_time - game_time,p->a_id,p->a_x,p->a_y,p->a_z,
        !          1083:                q->a_id,q->a_x,q->a_y,q->a_z);
        !          1084: }
        !          1085: 
        !          1086: erase(x,y)
        !          1087: int x,y;
        !          1088: {       register struct astruct *p;
        !          1089:        register int i;
        !          1090: 
        !          1091:        if (x<0 || y < 0) return;
        !          1092:        if (x>=width || y>=height) return;
        !          1093:        cursor(x,y);
        !          1094:        printf("%c ",screen[x][y]);
        !          1095:        for (p = &plane[i=0]; i < nplanes; i++,p++)
        !          1096:                if (p->a_active == ACTIVE && x == p->a_x && y == p->a_y)
        !          1097:                {       cursor(x,y);
        !          1098:                        printf("%c%c",p->a_id,(p->a_z>9?'^':p->a_z+'0'));
        !          1099:                }
        !          1100: }
        !          1101: 
        !          1102: 
        !          1103: int msglen[MAXHEIGHT];  /* length of message string on this row */
        !          1104: 
        !          1105: init()
        !          1106: {       int i,j;
        !          1107:        char c,mbuf[BUFSIZE];
        !          1108:        int pcompare();
        !          1109:        FILE *statfile;
        !          1110:        struct passwd *pw;
        !          1111:        time_t now;
        !          1112:        char *p,*ct;
        !          1113:        extern char *ctime();
        !          1114:        int nearlies;
        !          1115: 
        !          1116:        if ((statfile = fopen(STATSFILE,"a")) != NULL)
        !          1117:        {       pw = getpwuid(getuid());
        !          1118:                now = get_time();
        !          1119:                ct = ctime(&now);
        !          1120:                for (p= &ct[4]; p <= &ct[16]; p++) fputc(*p,statfile);
        !          1121:                fprintf(statfile,"%8s\n",pw->pw_name);
        !          1122:                fclose(statfile);
        !          1123:        }
        !          1124: 
        !          1125:        /* go into raw mode, no echo */
        !          1126:        if (!moviefile)
        !          1127:        {       ioctl(0, TIOCGETP, &tty_setting);
        !          1128:                tty_flags = tty_setting.sg_flags;
        !          1129: #ifdef CBREAK
        !          1130:                tty_setting.sg_flags |= CBREAK;
        !          1131:                tty_setting.sg_flags &= ~CRMOD;
        !          1132: #else
        !          1133:                tty_setting.sg_flags |= RAW;
        !          1134: #endif
        !          1135:                tty_setting.sg_flags &= ~ECHO;
        !          1136:                ioctl(0, TIOCSETP, &tty_setting);
        !          1137:                if (signal (SIGINT, SIG_IGN) != SIG_IGN)
        !          1138:                        signal (SIGINT, catchint);
        !          1139:                if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
        !          1140:                        signal (SIGQUIT, catchint);
        !          1141:        }
        !          1142: 
        !          1143:        for (i = 0; i < MAXHEIGHT; i++)
        !          1144:                msglen[i] = 0;
        !          1145: 
        !          1146:        for (i=0; i<MAXWIDTH; i++) for (j=0; j<MAXHEIGHT; j++)
        !          1147:                screen[i][j] = '.';
        !          1148: 
        !          1149:        if (moviefile)
        !          1150:        {       if ((movie = fopen(moviefile,"r")) == NULL)
        !          1151:                        err("Cannot open %s for reading.\n",moviefile);
        !          1152:                minit();        /* initialize from movie file */
        !          1153:        }
        !          1154: 
        !          1155:        if (seed == 0) seed = get_time();
        !          1156:        initseed = seed;
        !          1157: #ifdef vax
        !          1158:        srand(seed);
        !          1159: #else
        !          1160:        srandom(seed);    /* initialize random number generator */
        !          1161: #endif
        !          1162: 
        !          1163:        clearscreen();
        !          1164:        readspace();
        !          1165: 
        !          1166: 
        !          1167:        cmdx = width;  /* start command just to right of display */
        !          1168:        cmdy = height-4; /* and a ways from the bottom */
        !          1169:        display();      /* initial display */
        !          1170:        for (i=0; i<nairport; i++)
        !          1171:        {       sprintf(mbuf,"%c : %c%c",
        !          1172:                     screen[airport[i].p_x][airport[i].p_y],
        !          1173:                     (j = airport[i].p_dy) == 1 ? 'S' : j == -1 ? 'N' : ' ',
        !          1174:                     (j = airport[i].p_dx) == 1 ? 'E' : j == -1 ? 'W' : ' ');
        !          1175:                msg(cmdx,cmdy-2-i,mbuf);
        !          1176:        }
        !          1177: 
        !          1178:        cdltop.c_next = 0;      /* initially no clearance directive lists */
        !          1179:        cdltop.c_list = 0;
        !          1180: 
        !          1181:        while (game_time < 16*60 || game_time > 99*60+59) /*get time from user */
        !          1182:        {       char buf[100];
        !          1183:                char *p;
        !          1184:                cursor(cmdx,cmdy);
        !          1185:                printf("<  >");
        !          1186:                cursor(cmdx,cmdy);
        !          1187: 
        !          1188:                /* move the cursor one space to the right */
        !          1189:                p = buf;
        !          1190:                tgetstr ("nd", &p);
        !          1191:                fwrite (buf, sizeof (*buf), p-buf, stdout);
        !          1192: 
        !          1193:                game_time = getdigit()*10;   /* get the time as 2 digits */
        !          1194:                game_time += getdigit();
        !          1195:                initgame_time = game_time = game_time*60+59;
        !          1196:        }
        !          1197: 
        !          1198:        if (protofile)  /* keeping a protocol of the whole game */
        !          1199:        {       if ((proto = fopen(protofile,"w")) == NULL)
        !          1200:                        err("Cannot open %s for writing.\n",protofile);
        !          1201:                protostats(proto);
        !          1202:        }
        !          1203: 
        !          1204:        if (bigname)    /* megastatistics requested */
        !          1205:        {       if ((bigstatsfile = fopen(bigname,"w")) == NULL)
        !          1206:                        err("Cannot open %s for writing.\n",bigname);
        !          1207:                protostats(bigstatsfile);
        !          1208:                if (protofile)
        !          1209:                        fprintf(bigstatsfile,"Protocol from %s\n",protofile);
        !          1210:        }
        !          1211: 
        !          1212:        last_update = initgame_time+UPDATE; /* force early update */
        !          1213:        if (moviefile) last_update += OFFSET;
        !          1214: 
        !          1215:        for (i=nearlies=0; i<nplanes; i++)   /* construct 26 flight plans */
        !          1216:        {       plane[i].a_id = 'A'+i;
        !          1217:                flightplan(&plane[i],0);
        !          1218:                if (plane[i].a_stime < FPTHRESH) nearlies++;
        !          1219:        }
        !          1220:        for (i=nearlies; i < NEARLY; i++) /* ensure 2 or so planes in 1st minute */
        !          1221:                flightplan(&plane[die(nplanes)],1);
        !          1222:        qsort(plane,nplanes,sizeof (struct astruct),pcompare);
        !          1223:        remain = nplanes;
        !          1224:        if (bigname)
        !          1225:                for (i = 0; i < nplanes; i++)
        !          1226:                        strip(&plane[i],-1,TERSE);
        !          1227: 
        !          1228:        for (i=0; i<nairport; i++)      /* erase the approaches */
        !          1229:                delmsg(cmdx,cmdy-2-i);
        !          1230:        start_time = get_time();
        !          1231: }
        !          1232: 
        !          1233: protostats(proto)    /* bunch of statistics for protocols and stuff */
        !          1234: FILE *proto;
        !          1235: {       char wd[100];   /* result of a "pwd" command */
        !          1236:        FILE *pwd;
        !          1237:        char *s,*t,*u;
        !          1238:        int c;
        !          1239: 
        !          1240:        if ((pwd = popen("pwd","r")) == NULL)
        !          1241:                err("Cannot open a pipe to pwd.\n");
        !          1242:        for (s = wd; (c = getc(pwd)) != EOF;)
        !          1243:                if (c != '\n') *s++ = c;
        !          1244:        t = s;  /* here's where to put the filename */
        !          1245:        *s = 0;
        !          1246:        fclose(pwd);
        !          1247:        if (*airfile != '/') /* relative airspace file */
        !          1248:        {       s = t;
        !          1249:                *s++ = '/';
        !          1250:                for (u = airfile; *s++ = *u++; );
        !          1251:                fprintf(proto,"Airspace file: %s\n",wd);
        !          1252:        }
        !          1253:        else    fprintf(proto,"Airspace file: %s\n",airfile);
        !          1254:        fprintf(proto,"Airspace: %s\n",airspace);
        !          1255:        if (flowfile)
        !          1256:        {       if (*flowfile != '/') /* relative flowfile */
        !          1257:                {       s = t;
        !          1258:                        *s++ = '/';
        !          1259:                        for (u = flowfile; *s++ = *u++; );
        !          1260:                        fprintf(proto,"Flow file: %s\n",wd);
        !          1261:                }
        !          1262:                else    fprintf(proto,"Flow file: %s\n",flowfile);
        !          1263:        }
        !          1264:        else    fprintf(proto,"Flow file: \n");
        !          1265:        fprintf(proto,"Seed: %d\n",seed);
        !          1266:        fprintf(proto,"Time: %d seconds\n",game_time);
        !          1267: }
        !          1268: 
        !          1269: minit() /* initialize the game from a protocol file */
        !          1270: {       /* the file is open on stream "movie" */
        !          1271:        char buffer[80];
        !          1272:        static char airfilebuf[80];
        !          1273:        static char airbuf[80];
        !          1274:        static char flowbuf[80];
        !          1275:        char *s,*t;
        !          1276: 
        !          1277:        if (fgets(buffer,80,movie) == 0)      /* airspace file line */
        !          1278:                err("Unexpected EOF on movie file.\n");
        !          1279:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
        !          1280:        if (*s == 0) err("Bad airspace file line.\n");
        !          1281:        s++; s++;       /* skip colon and space */
        !          1282:        for (t = airfilebuf; (*t++ = *s++) != '\n';); /* copy airspace file */
        !          1283:        *--t = 0;
        !          1284:        airfile = airfilebuf;   /* and dummy the pointer */
        !          1285:        if (fgets(buffer,80,movie) == 0)      /* airspace line */
        !          1286:                err("Unexpected EOF on movie file.\n");
        !          1287:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
        !          1288:        if (*s == 0) err("Bad airspace line.\n");
        !          1289:        s++; s++;       /* skip colon and space */
        !          1290:        for (t = airbuf; (*t++ = *s++) != '\n';); /* copy airspace name */
        !          1291:        *--t = 0;
        !          1292:        airspace = airbuf; /* and dummy the pointer */
        !          1293:        if (fgets(buffer,80,movie) == 0)      /* flowfile line */
        !          1294:                err("Unexpected EOF on movie file.\n");
        !          1295:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
        !          1296:        if (*s == 0) err("Bad flowfile line.\n");
        !          1297:        s++; s++;       /* skip colon and space */
        !          1298:        if (*s == '\n') flowfile = 0;
        !          1299:        else
        !          1300:        {       for (t = flowbuf; (*t++ = *s++) != '\n';); /* copy flowfile */
        !          1301:                *--t = 0;
        !          1302:                flowfile = flowbuf; /* and dummy the pointer */
        !          1303:        }
        !          1304:        if (fgets(buffer,80,movie) == 0)      /* seed */
        !          1305:                err("Unexpected EOF on movie file.\n");
        !          1306:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
        !          1307:        if (*s == 0) err("Bad seed line.\n");
        !          1308:        s++; s++;       /* skip colon and space */
        !          1309:        seed = atoi(s);
        !          1310:        if (fgets(buffer,80,movie) == 0)      /* time line */
        !          1311:                err("Unexpected EOF on movie file.\n");
        !          1312:        for (s = buffer; *s != ':' && *s; s++); /* scan to colon */
        !          1313:        if (*s == 0) err("Bad time line.\n");
        !          1314:        s++; s++;       /* skip colon and space */
        !          1315:        initgame_time = game_time = atoi(s);
        !          1316:        getmcmd();      /* get the first command from movie mode */
        !          1317: }
        !          1318: 
        !          1319: getmcmd()       /* read a command and store time and command */
        !          1320: {       static char buff[80];
        !          1321:        char *s;
        !          1322: 
        !          1323:        if (fgets(buff,80,movie) == 0)
        !          1324:        {       mcommand = "";
        !          1325:                nextmovie = -20;
        !          1326:                fclose(movie);
        !          1327:                return;
        !          1328:        }
        !          1329:        for (s = buff; *s == ' '; s++);       /* skip initial blanks */
        !          1330:        nextmovie = atoi(s);
        !          1331:        while (*s++ != ' ');  /* skip to the command */
        !          1332:        mcommand = s;           /* and save it in a global */
        !          1333:        for (; *s; s++) if (*s == '\n') *s = RETURN;
        !          1334: }
        !          1335: 
        !          1336: pcompare(p1,p2) /* compare start times for sorting the plane list */
        !          1337: struct astruct *p1,*p2;
        !          1338: {       if ((p1)->a_stime < (p2)->a_stime) return(-1);
        !          1339:        else if ((p1)->a_stime == (p2)->a_stime) return(0);
        !          1340:        else return(1);
        !          1341: }
        !          1342: 
        !          1343: 
        !          1344: printplans()    /* flight plans for active and near-active planes */
        !          1345: {       register int ctr;      /* can only keep cmdy-2 planes on the screen */
        !          1346:        register struct astruct *p;
        !          1347:        register int i;
        !          1348: 
        !          1349:        for (i = ctr = 0, p = &plane[0]; i < nplanes && ctr < cmdy - 2; i++,p++)
        !          1350:                if (p->a_active == APPROACHING || p->a_active == WAITING)
        !          1351:                        strip(p,ctr++,TERSE);
        !          1352:        delmsg(cmdx,ctr++);     /* blank line between approaching and active*/
        !          1353:        for (p = &plane[i=0]; i < nplanes && ctr < cmdy - 2; i++,p++)
        !          1354:                if (p->a_active == ACTIVE)
        !          1355:                        strip(p,ctr++,TERSE);
        !          1356:        while (ctr < cmdy - 2) delmsg(cmdx,ctr++); /* delete any msg on line*/
        !          1357: }
        !          1358: 
        !          1359: strip(p,y,outstyle)     /* display flight strip for this plane on cmd row y */
        !          1360: register struct astruct *p;
        !          1361: int y,outstyle;
        !          1362: {       char mbuf[80];  /* plan message to appear */
        !          1363:        int pfuel;
        !          1364:        struct list *l;
        !          1365:        char *s;
        !          1366: 
        !          1367:        if (p->a_active == WAITING) sprintf(mbuf,"  ");
        !          1368:        else if (p->a_active == APPROACHING)
        !          1369:                sprintf(mbuf,"%d ",
        !          1370:                        (p->a_stime - initgame_time + game_time + 14) / 15);
        !          1371:        else mbuf[0] = 0;
        !          1372:        sprintf(&mbuf[strlen(mbuf)],"%c%c %c->%c ",
        !          1373:                p->a_id,
        !          1374:                (p->a_type? 'j': 'p'),
        !          1375:                screen[p->a_x][p->a_y],
        !          1376:                (p->a_dair? airport[p->a_dest].p_sym :
        !          1377:                            entry[p->a_dest].p_sym));
        !          1378:        sprintf(&mbuf[strlen(mbuf)],"%d%c%c ",
        !          1379:                p->a_z,
        !          1380:                (p->a_nextz > p->a_z ? '^' :
        !          1381:                 p->a_nextz < p->a_z ? 'v' : ' '),
        !          1382:                (p->a_nextz != p->a_z ? p->a_nextz + '0' : ' '));
        !          1383:        if (p->a_dy>0) sprintf(&mbuf[strlen(mbuf)],"S");
        !          1384:        else if (p->a_dy<0) sprintf(&mbuf[strlen(mbuf)],"N");
        !          1385:        if (p->a_dx>0) sprintf(&mbuf[strlen(mbuf)],"E");
        !          1386:        else if (p->a_dx<0) sprintf(&mbuf[strlen(mbuf)],"W");
        !          1387:        if (p->a_dy == 0) sprintf(&mbuf[strlen(mbuf)]," ");
        !          1388:        switch(p->a_hold)
        !          1389:        {   case 2: sprintf(&mbuf[strlen(mbuf)]," h "); break;
        !          1390:            case 1: sprintf(&mbuf[strlen(mbuf)]," * "); break;
        !          1391:            case 0: sprintf(&mbuf[strlen(mbuf)]," %c ",p->a_turn-'A'+'a');
        !          1392:                    break;
        !          1393:        }
        !          1394:        if (p->a_clear)
        !          1395:                sprintf(&mbuf[strlen(mbuf)],"* %c",p->a_clear);
        !          1396:        if (p->a_dynew>0) sprintf(&mbuf[strlen(mbuf)],"S");
        !          1397:        else if (p->a_dynew<0) sprintf(&mbuf[strlen(mbuf)],"N");
        !          1398:        if (p->a_dxnew>0) sprintf(&mbuf[strlen(mbuf)],"E");
        !          1399:        else if (p->a_dxnew<0) sprintf(&mbuf[strlen(mbuf)],"W");
        !          1400:        if (p->a_dynew == 0) sprintf(&mbuf[strlen(mbuf)]," ");
        !          1401:        pfuel = (p->a_type == JET? p->a_fuel/4 : p->a_fuel/2);
        !          1402:        sprintf(&mbuf[strlen(mbuf)]," %c",pfuel>=10?'+':pfuel+'0');
        !          1403:        if (p->a_plan)
        !          1404:                sprintf(&mbuf[strlen(mbuf)]," P");
        !          1405:        if (y < 0)      /* flight strip to file, not screen */
        !          1406:        {       if (bigname)
        !          1407:                {       int st;
        !          1408: 
        !          1409:                        st = p->a_stime;
        !          1410:                        if (p->a_type == JET)
        !          1411:                        {       st = st / 15;
        !          1412:                                st = st * 15;
        !          1413:                        }
        !          1414:                        else
        !          1415:                        {       st = (st + 45) / 30;
        !          1416:                                st = (st * 30) - 15;
        !          1417:                        }
        !          1418:                        if (st < FIRST_TIME) st = FIRST_TIME;
        !          1419:                        fprintf(bigstatsfile,"%5d: ",st);
        !          1420:                        fprintf(bigstatsfile,"%s\n",mbuf);
        !          1421:                }
        !          1422:        }
        !          1423:        else
        !          1424:        {       msg(cmdx,y,mbuf);   /* display the string */
        !          1425:                if (outstyle == VERBOSE && p->a_plan)
        !          1426:                {       for (l = p->a_plan; l; l = l->l_next)
        !          1427:                        {       sprintf(mbuf,"%s %s",l->l_loc,l->l_cmd);
        !          1428:                                for (s = mbuf; *s; s++) if (*s == RETURN) *s = 0;
        !          1429:                                msg(cmdx,++y,mbuf);
        !          1430:                        }
        !          1431:                }
        !          1432:                while (++y < MAXHEIGHT && msglen[y]) msg(cmdx,y,"");/* clr old plans*/
        !          1433:        }
        !          1434: }
        !          1435: 
        !          1436: msg(x,y,string) /* put up a message at cursor position x,y */
        !          1437: int x,y;
        !          1438: char *string;
        !          1439: {       int i,l;
        !          1440: 
        !          1441:        cursor(x,y);
        !          1442:        printf("%s",string);
        !          1443:        l = strlen(string);
        !          1444:        for (i=l; i<msglen[y]; i++) putchar(' ');
        !          1445:        msglen[y] = l;
        !          1446: }
        !          1447: 
        !          1448: delmsg(x,y)     /* delete any message starting at cursor posn x,y */
        !          1449: int x,y;
        !          1450: {       int i;
        !          1451: 
        !          1452:        if (msglen[y] <= 0) return;
        !          1453:        cursor(x,y);
        !          1454:        for (i=0; i<msglen[y]; i++) putchar(' ');
        !          1455:        msglen[y] = 0;
        !          1456: }
        !          1457: 
        !          1458: 
        !          1459: flightplan(p,early)
        !          1460: struct astruct *p;
        !          1461: int early;      /* 1 if this plane should be rescheduled for early arrival */
        !          1462: {       int i,r,cum;
        !          1463:        struct astruct *q;
        !          1464:        struct pstruct *loc;
        !          1465: 
        !          1466:        p->a_type = die(2);
        !          1467:        /* starting time: no planes in last 15 minutes; pretend interval
        !          1468:         * extends negatively from 0 by FUDGE seconds to make it more likely
        !          1469:         * that there will be planes available soon.  On the other hand, no
        !          1470:         * plane can come on for the first FIRST_TIME seconds.
        !          1471:         */
        !          1472:        p->a_stime = die(FUDGE + game_time - 15*60) - FUDGE;
        !          1473:        if (early) p->a_stime = die(FPTHRESH);
        !          1474:        if (p->a_stime <FIRST_TIME) p->a_stime = FIRST_TIME;
        !          1475:        if (flowfile)   /* flows have been specified */
        !          1476:        {       r = die(maxflow);
        !          1477:                for (i = cum = 0; i < npaths; i++)
        !          1478:                {       cum += fpath[i].f_freq;
        !          1479:                        if (cum >= r) break;
        !          1480:                }
        !          1481:                if (i >= npaths) i = 0; /* shouldn't ever do this */
        !          1482:                p->a_sair = fpath[i].f_fair;
        !          1483:                p->a_dair = fpath[i].f_tair;
        !          1484:                p->a_hold = (p->a_dair && !p->a_sair? 1 : 0);
        !          1485:                p->a_start = fpath[i].f_from;
        !          1486:                p->a_dest = fpath[i].f_to;
        !          1487: 
        !          1488:                if (p->a_sair) loc = &airport[p->a_start];
        !          1489:                else           loc = &entry[p->a_start];
        !          1490:        }
        !          1491:        else
        !          1492:        {       p->a_sair = (die(inaptot+inawtot) <= inaptot? 1 : 0);
        !          1493:                p->a_dair = (die(outaptot+outawtot) <= outaptot? 1 : 0);
        !          1494: 
        !          1495:                p->a_hold = (p->a_dair? 1 : 0);
        !          1496:                if (p->a_sair)
        !          1497:                {       p->a_start =pick(die(inaptot),&airport[0],nairport,1);
        !          1498:                        loc = &airport[p->a_start];
        !          1499:                        p->a_hold = 0;
        !          1500:                        if (p->a_dair) p->a_dest = pick(die(inaptot),
        !          1501:                                                        &airport[0],nairport,0);
        !          1502:                        else           p->a_dest = pick(die(inawtot),
        !          1503:                                                        &entry[0],nentry,0);
        !          1504:                }
        !          1505:                else
        !          1506:                {       p->a_start = pick(die(inawtot),&entry[0],nentry,0);
        !          1507:                        loc = &entry[p->a_start];
        !          1508:                        if (p->a_dair) p->a_dest = pick(die(inaptot),
        !          1509:                                                        &airport[0],nairport,0);
        !          1510:                        else do p->a_dest = pick(die(inawtot),
        !          1511:                                                 &entry[0],nentry,0);
        !          1512:                             while (p->a_dest == p->a_start);
        !          1513:                }
        !          1514:        }
        !          1515:        p->a_active = INACTIVE;
        !          1516:        p->a_z = (p->a_sair? 0 : 6);
        !          1517:        if (!p->a_sair) /* separate planes by 1000' altitude */
        !          1518:            for (q = &plane[0]; q != &plane[PMAX]; q++)
        !          1519:            {   if (q == p && !early) break;
        !          1520:                if (q == p) continue;
        !          1521:                if (p->a_start == q->a_start)
        !          1522:                    if (abs(q->a_stime - p->a_stime) < SAFETY)
        !          1523:                        if (q->a_z >= p->a_z)
        !          1524:                            p->a_z = q->a_z + 1;
        !          1525:            }
        !          1526:        if (flowfile && p->a_z < NALT)
        !          1527:        {       p->a_opt = fpath[i].f_dist[p->a_z];
        !          1528:                p->a_cmds = fpath[i].f_cmds;
        !          1529:        }
        !          1530:        p->a_prev = p->a_pprev = p->a_aprev = 0;
        !          1531:        p->a_x = loc->p_x;
        !          1532:        p->a_y = loc->p_y;
        !          1533:        p->a_dx = loc->p_dx;
        !          1534:        p->a_dy = loc->p_dy;
        !          1535:        p->a_dxnew = p->a_dynew = 0;
        !          1536:        p->a_lastz = p->a_nextz = p->a_z;
        !          1537:        p->a_turn = 0;
        !          1538:        p->a_fuel = (p->a_type == JET ? JETFUEL : PROPFUEL);
        !          1539:        p->a_clear = 0; /* not cleared for any approach */
        !          1540:        p->a_plan = 0;  /* no monitor points on the flight plan */
        !          1541:        p->a_load = p->a_ticks = p->a_planned = p->a_dist = 0;
        !          1542: }
        !          1543: 
        !          1544: pick(draw,point,num,in)
        !          1545: int draw;
        !          1546: struct pstruct *point;
        !          1547: int num,in;
        !          1548: {       register int i,cum;
        !          1549: 
        !          1550:        for (i = cum = 0; i<num; i++,point++)
        !          1551:        {       if (in) cum += point->p_inprop;
        !          1552:                else    cum += point->p_outprop;
        !          1553:                if (cum >= draw) return(i);
        !          1554:        }
        !          1555:        return(0); /* should never get here */
        !          1556: }
        !          1557: 
        !          1558: #if !NRAND
        !          1559: die(n) /* throw an n-sided die (sides 0 thru n-1) */
        !          1560: int n;
        !          1561: {       int r;
        !          1562: 
        !          1563: #ifdef vax
        !          1564:        r = rand() >> 10;        /* rightmost bits are not very random */
        !          1565: #else
        !          1566:        r = random();   /* rightmost bits are not very random */
        !          1567: #endif
        !          1568:        return(r % n);  /* enough resolution to make this o.k. */
        !          1569: }
        !          1570: #endif
        !          1571: 
        !          1572: getdigit()      /* keep reading chars from terminal until get a digit */
        !          1573: {       int c;  /* returns digit - '0' */
        !          1574: 
        !          1575:        do {
        !          1576:                if (rubout) return 9;
        !          1577:                c = getchar() & 0177;
        !          1578:        } while (c < '0' || c > '9');
        !          1579:        putchar(c);
        !          1580:        return(c-'0');
        !          1581: }
        !          1582: 
        !          1583: time_t
        !          1584: get_time()      /* returns time in seconds since 1970 */
        !          1585: {
        !          1586:        time_t t;
        !          1587: 
        !          1588:        time(&t);
        !          1589:        return(t);     /* seconds since 1970 */
        !          1590: }
        !          1591: 
        !          1592: 
        !          1593: display()      /* put up initial screen */
        !          1594: {      int i,j;
        !          1595: 
        !          1596:        for (j=0; j<height; j++)
        !          1597:        {       cursor(0,j);    /* general enough to extend to graphics */
        !          1598:                for (i=0; i<width; i++)
        !          1599:                {       putchar(screen[i][j]);
        !          1600:                        putchar(' ');
        !          1601:                }
        !          1602:        }
        !          1603: }
        !          1604: 
        !          1605: 
        !          1606: cursor(x,y)    /* move to location x,y on WIDTHxHEIGHT screen */
        !          1607: char x,y;       /* this is in terms of screen, i.e. with x's 2 chars wide */
        !          1608: { 
        !          1609:        poscur(2*x,y);
        !          1610: } 
        !          1611: 
        !          1612: 
        !          1613: poscur(x,y)     /* position cursor at this absolute location on screen */
        !          1614: char x,y;
        !          1615: {       
        !          1616:        char *tgoto();
        !          1617:        printf ("%s", tgoto (cmbuf, x, y));
        !          1618: }
        !          1619: 
        !          1620: 
        !          1621: clearscreen()
        !          1622: {       
        !          1623:        printf ("%s", clbuf);
        !          1624: }
        !          1625: 
        !          1626: char *
        !          1627: plural(n)       /* returns "s" unless n=1 */
        !          1628: int n;
        !          1629: {       static char s[2] = "s";
        !          1630: 
        !          1631:        if (n != 1) return(s);
        !          1632:        else return("");
        !          1633: }
        !          1634: 
        !          1635: done(flag)  /* clean up */
        !          1636: int flag;
        !          1637: {       FILE *statfile;
        !          1638:        struct passwd *pw;
        !          1639:        time_t now;
        !          1640:        char *c,*ct;
        !          1641:        extern char *ctime();
        !          1642: 
        !          1643:        if (!moviefile)
        !          1644:        {       tty_setting.sg_flags = tty_flags;/* put terminal back the way it was*/
        !          1645:                ioctl(0, TIOCSETP, &tty_setting);
        !          1646:        }
        !          1647:        if (flag) cursor(LEFT,height+1);
        !          1648: 
        !          1649:        if ((statfile = fopen(STATSFILE,"a")) != NULL)
        !          1650:        {       pw = getpwuid(getuid());
        !          1651:                now = get_time();
        !          1652:                ct = ctime(&now);
        !          1653:                for (c= &ct[4]; c <= &ct[16]; c++) fputc(*c,statfile);
        !          1654:                if (!flag) fprintf(statfile,"%8s: aborted\n",pw->pw_name);
        !          1655:                else
        !          1656:                {  fprintf(statfile,"%8s: %2d %3d %2d %2d %3d %5d   %3d %2d",
        !          1657:                           pw->pw_name,crash,system,fuel,bound,goaround,
        !          1658:                           fuelused,cmds,remain);
        !          1659:                   fprintf(statfile,". %d  %2d %s\n",
        !          1660:                           initseed,initgame_time/60,airspace);
        !          1661:                   fclose(statfile);
        !          1662:                }
        !          1663:        }
        !          1664:        if (!flag) return;
        !          1665:        ttystats(stdout);
        !          1666:        if (bigname)
        !          1667:        {       int i;
        !          1668:                float load,ticks,plans,route,d,stripped;
        !          1669: 
        !          1670:                for (i = 0; i < nplanes; i++)
        !          1671:                {       load = plane[i].a_load;
        !          1672:                        ticks = plane[i].a_ticks;
        !          1673:                        plans = plane[i].a_planned;
        !          1674:                        route = plane[i].a_opt;
        !          1675:                        stripped = plane[i].a_prev;
        !          1676:                        d = plane[i].a_dist;
        !          1677:                        fprintf(bigstatsfile,
        !          1678: "%c: %2d tks, %2d/%2d=%1.2f, %d, %.2f a/tk, %.2f p/tk, %.2f a/ptk, %.2f p/ptk, %c, %s\n",
        !          1679:                                plane[i].a_id,plane[i].a_ticks,
        !          1680:                                plane[i].a_dist,
        !          1681:                                plane[i].a_opt,
        !          1682:                                d/route,
        !          1683:                                plane[i].a_cmds,
        !          1684:                                load/ticks,
        !          1685:                                plans/ticks,
        !          1686:                                plane[i].a_aprev/stripped,
        !          1687:                                plane[i].a_pprev/stripped,
        !          1688:                                plane[i].a_sair? 'W' : 'A',
        !          1689:                                plane[i].a_pplanned? "+P" : "-P"
        !          1690:                        );
        !          1691:                }
        !          1692:        }
        !          1693:        if (bigname) ttystats(bigstatsfile);
        !          1694:        if (protofile) fclose(proto);
        !          1695:        if (bigname) fclose(bigstatsfile);
        !          1696: }
        !          1697: 
        !          1698: ttystats(file)
        !          1699: FILE *file;
        !          1700: {       char *eol;
        !          1701: 
        !          1702:        if (file == bigstatsfile) eol = "\n";
        !          1703:        else {
        !          1704:                clearscreen();
        !          1705:                eol = "\n\r";
        !          1706:        }
        !          1707:        if (crash)  fprintf(file,"%d plane%s out of fuel, crashed%s",
        !          1708:                crash,plural(crash),eol);
        !          1709:        if (system) fprintf(file,"%d system error%s%s",
        !          1710:                system,plural(system),eol);
        !          1711:        if (fuel)   fprintf(file,"%d tow truck%s called%s",
        !          1712:                fuel,plural(fuel),eol);
        !          1713:        if (bound)  fprintf(file,"%d boundary error%s%s",
        !          1714:                bound,plural(bound),eol);
        !          1715:        if (goaround) fprintf(file,"%d go-around%s%s",
        !          1716:                goaround,plural(goaround),eol);
        !          1717:        if (crash+system+fuel+bound+remain == 0)
        !          1718:        { fprintf(file,"GREAT JOB!!  Have you considered a career in ATC?\n");
        !          1719:          fprintf(file,"Now try %d minutes...\n",initgame_time/60-5);
        !          1720:        }
        !          1721:        fprintf(file,"Fuel used: %d\n",fuelused);
        !          1722:        fprintf(file,"Commands issued (including deferred): %d\n",icmds);
        !          1723:        fprintf(file,"Commands executed: %d\n",cmds);
        !          1724:        fprintf(file,"Airspace: %s; seed: %d; time=%d; %d remaining.%s",
        !          1725:                airspace,initseed,initgame_time/60,remain,eol);
        !          1726:        if (file == bigstatsfile) fprintf(file,"\f");
        !          1727: }
        !          1728: 
        !          1729: err(msg,arg1,arg2)
        !          1730: char *msg; 
        !          1731: {       fprintf(stderr,msg,arg1,arg2);
        !          1732:        done(0);
        !          1733:        exit(1);
        !          1734: } 
        !          1735: 

unix.superglobalmegacorp.com

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