home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG048.ARK / RALLY.C < prev    next >
C/C++ Source or Header  |  1984-04-29  |  10KB  |  411 lines

  1. /*
  2.     H19 RALLY Game,        5/80    Steve Ward
  3.  
  4.     Works ONLY on Heathkit/Zenith H19/Z19 terminal
  5.                  (or H89 computer)
  6.  
  7.     Command format:
  8.  
  9.     A>rally [-rn] [-b] [mapname] <cr>
  10.  
  11.     where:    "n"  is an optional seed for the random number generator
  12.              (results in exactly the same minor track deviations each
  13.              time it is given with a particular track);
  14.              If "n" is omitted, then track deviations are totally
  15.              random for each session (but same for each run in any
  16.              single session.)
  17.  
  18.         "-b" is a debugging option doing Steve-knows-what.
  19.  
  20.         "mapname" specifies the map file to use for the track
  21.             (defaults to "rally.map").
  22. */
  23.  
  24.  
  25. #include "bdscio.h"        /* Get std console parameters    */
  26.  
  27. #define    CARY    16        /* Y position of car.        */
  28. #define    IBAD    0
  29. #define    LSPEED    7        /* Line 25 label posns        */
  30. #define    LMILES    20
  31. #define    MAXSPD    9
  32. #define    SPDSCL    128
  33. #define    TENTHS    10        /* Number of lines per mile.    */
  34. #define    TICMIN    1920        /* Number of tics per minute.    */
  35.  
  36. char    Free[10000], *Freep;
  37.  
  38. char    CRTFrz, CRTChr;
  39. int    Miles;
  40. char    Pavement, Freeze, BFlag;
  41. char    CurX, CurY, SignY;
  42. int    CarX, CarDX;
  43. char    RevFlg, AltFlg;
  44. int    Speed, Tenths;
  45. char    Image[CARY*80+80];
  46. char    *ImPtr, *ImEnd;
  47. int    Seed;
  48. int    Ranno;
  49. char    InBuf[BUFSIZ], SavChr;
  50. int    SpTime[MAXSPD+1];
  51.  
  52. struct Road {
  53.     struct Node *Next;
  54.     char    active;
  55.     char    Token;
  56.     int    Windy;
  57.     int    Curvy;
  58.     int    Age;
  59.     int    ToGo;
  60.     char    Holes;
  61.     char    X;
  62.     char    dx;
  63.     char    width; } Road1, Road2;
  64.  
  65. struct Sign {
  66.     struct Node *Next;
  67.     char key;
  68.     char text[0]; };
  69.  
  70. struct Fork {
  71.     struct Node *Next;
  72.     char key;
  73.     char *Branch; };
  74.  
  75. struct Dist {
  76.     struct Node *Next;
  77.     char key;
  78.     char wid, curve, wind;
  79.     int miles; };
  80.  
  81. union Node {
  82.     struct Dist;
  83.     struct Fork;
  84.     struct Sign; } *Tag[128];
  85.  
  86.  
  87. /*
  88.     Write a character to the terminal, handling X-ON/X-OFF
  89.     protocol and not going into a busy loop if the terminal
  90.     isn't ready to send a character, but rather just returning
  91.     in that case to let the caller do more crunching and try
  92.     again later.
  93. */
  94.  
  95. putchar(c)
  96.  {    char stat, ch;
  97.     for(;;)
  98.      { if ((CIMASK & (stat = inp(CSTAT))) == (CAHI ? CIMASK : 0))
  99.         switch(ch = (0177 & inp(CDATA))) {
  100.         case 'S'-64:    CRTFrz=1; break;
  101.         case 'Q'-64:    CRTFrz=0; break;
  102.         case 'C'-64:    puts("\033z"); exit();
  103.         default:    CRTChr=ch; }
  104.        if (CRTFrz) continue;
  105.        if ((stat & COMASK) == (CAHI ? COMASK : 0))
  106.          { if (c) outp(CDATA,c); return; }
  107.      }
  108. }
  109.  
  110.  
  111. char *new(size)
  112.  {    char *rr;
  113.     rr = Freep; Freep += size; return rr; }
  114.  
  115. struct Dist *NRoad(widx, curv, windx, dist)
  116.  {    struct Dist *rr;
  117.     rr = new(sizeof *rr);
  118.     rr->key = 'D';        rr->Next = 0;
  119.     rr->miles = dist;    rr->wid = widx;
  120.     rr->curve = curv;    rr->wind = windx;
  121.     return rr; }
  122.  
  123. struct Sign *NSign(txt)
  124.  char *txt;
  125.  {    int leng; char *cc, *dd;
  126.     struct Sign *ss;
  127.     leng = sizeof *ss; leng++;
  128.     for (cc=txt; *cc++; leng++);
  129.     ss = new(leng);        ss->key = 'S';        ss->Next = 0;
  130.     dd = &(ss->text); for (cc=txt; *dd++ = *cc++;);
  131.     return ss; }
  132.  
  133. struct Fork *NFork(kk)
  134.  {    struct Fork *ff;
  135.     ff = new(sizeof *ff); ff->key = kk;
  136.     ff->Next = 0;    ff->Branch = 0;
  137.     return ff; }
  138.  
  139. PrNode(nn)
  140.  struct Node *nn;
  141.  {    printf("Node %x: %c -> %x \r\n", nn, nn->key, nn->Next); }
  142.  
  143. char rdc()
  144.  {    char ch;
  145.     if (ch = SavChr) { SavChr=0; return ch; };
  146.     return (getc(InBuf)); }
  147.  
  148. char pkc()
  149.  {    return (SavChr = rdc()); }
  150.  
  151. int rdn()
  152.  {    int ans, ch;
  153.     ans = 0;
  154.     while (isdigit(pkc()))    ans = ans*10 + (rdc() - '0');
  155.     return ans; }
  156.  
  157. struct Dist *LRoad()
  158.  {    int w, c, iwid, dd;
  159.     char ch;
  160.     dd = rdn();
  161.     w = -1; c = -1; iwid = 20;
  162.     while (pkc() != '\n') switch(rdc())
  163.      {    case '~':    c++; continue;
  164.         case 'W':    iwid = rdn(); continue;
  165.         case '!':    w++; continue;
  166.         default:    continue; }
  167.     return NRoad(iwid, c, w, dd);
  168.  }
  169.  
  170. struct Dist *Load(name)
  171.  char *name;
  172.  {    char ch, buf[100], *cc;
  173.     struct Sign First, Ignore;
  174.     struct Node *it, *last;
  175.     puts("\033z");
  176.     SavChr = 0;
  177.     it = &First; First.key = '?';
  178.     if (fopen(name, InBuf) == -1)
  179.      { printf("Can't read %s\r\n", name); exit(); }
  180.  
  181.     while ((ch = rdc()) != 014) putchar(ch);
  182.     while ((ch = rdc()) != ('Z'-64))
  183.      { last = it;
  184.        switch(ch)
  185.         {    case '=':    Tag[rdc(InBuf)] = Freep; break;
  186.         case '|':    while (rdc() != '\n'); break;
  187.         case '"':    cc = buf;
  188.                 while (((ch = rdc()) != '"') &&
  189.                     (ch != '\n')) *cc++ = ch;
  190.                 *cc = 0;
  191.                 it->Next = NSign(buf); it = it->Next;
  192.                 break;
  193.         case '#':    it->Next = LRoad(); it = it->Next;
  194.                 break;
  195.  
  196.         case ':':    it->Next = rdc();
  197.         case '.':    it = &Ignore; break;
  198.  
  199.         case '>':    it->Next = NFork('R'); it = it->Next;
  200.                 it->Branch = rdc();
  201.                 break;
  202.         case '<':    it->Next = NFork('L'); it = it->Next;
  203.                 it->Branch = rdc();
  204.                 break;
  205.  
  206.         case ' ':    case '\n':    case '\r':    case '\t':
  207.         case '\f':    break;
  208.  
  209.         default:    puts("Illegal syntax: "); putchar(ch);
  210.                 while ((ch = rdc(InBuf)) != '\n') putchar(ch);
  211.                 puts("\n\r"); break; }}
  212.     NSign("Unbound label");
  213.     srand1("\033x1\033x5\033Y8   (type a character to start)");
  214.     if (!Seed) Seed = rand();    /* Do this only if "-r" option given
  215.                        without any argument.    */
  216.     bdos(1);
  217.     return First.Next; }
  218.  
  219. Exec(rr)
  220. struct Road *rr;
  221.  {    int x, dir, tt, right, left;
  222.     union Node *nn;
  223.     nn = rr->Next;    rr->Next = nn->Next;
  224.     x = rr->X; dir = -1;
  225.  
  226.     switch (nn->key) {
  227.      case 'S':    right = x+(rr->width); left = 78-right;
  228.             x = x>left? 0:right+2;
  229.             printf("\033Y%c%c\033G %s \033F",
  230.                 SignY++, x+32, &(nn->text));
  231.             return;
  232.      case 'D':    rr->Age = 0;
  233.             if (nn->wind != 255) rr->Windy = ~(-1 << nn->wind);
  234.             if (nn->curve != 255) rr->Curvy = nn->curve;
  235.             rr->ToGo = nn->miles;
  236.             if (nn->wid != 255) rr->width = nn->wid; return;
  237.      case 'L':    dir = 1;
  238.      case 'R':    if (!Freeze) fork(nn->Branch, dir); return;
  239.              }
  240.  }
  241.  
  242. MoveTo(x, y) { puts("\033Y"); putchar(y+32); putchar(x+32); }
  243. SpeedL() { MoveTo(LSPEED, 24); putchar(Speed + '0'); }
  244. label(val, posn)
  245.  {    printf("\033Y8%c%d ", posn+32, val); }
  246.  
  247.  
  248. getchar()
  249.  {    char ch;
  250.     while (!(ch = CRTChr)) putchar(0);
  251.     CRTChr = 0; return ch; }
  252.  
  253. car(x)
  254.  {    puts("\033Y"); putchar(CARY+31); putchar(x+32);
  255.     puts(" "); }
  256.  
  257. roll()
  258.  {    puts("\033H\033L");
  259.     CurX=0; CurY=0;
  260.     if ((ImPtr += 80) == ImEnd) ImPtr = Image;
  261.     Pavement = ImPtr[CarX];
  262.     setmem(ImPtr, 80, IBAD); }
  263.  
  264. road(x, width, rdno)
  265.  {    char i, *cc;
  266.     puts("\033Y ");
  267.     putchar(32+x);
  268.     if (!RevFlg) { puts("\033p"); RevFlg=1; }
  269.     if (!AltFlg) { puts("\033F"); AltFlg=1; }
  270.     cc = &(ImPtr[x]);
  271.     for (i=width; i--;) { putchar('i'); *cc++ |= rdno; }}
  272.  
  273. /* Update a Road; returns 1 if finish line.    */
  274.  
  275. UpRd(rr)
  276.  struct Road *rr;
  277.  {    int ddx, left, right, curve, act, rough; unsigned i;
  278.     if (!(act = rr->active)) return 0;
  279.     (rr->ToGo)--;
  280.     while ((rr->ToGo) <= 0)
  281.      { if (i = (rr->Next))
  282.         {    if (i == '.') return 1;
  283.         if (i == '*') { rr->active = 0; return 0; }
  284.         if (i < 128)
  285.          { rr->Next = Tag[i];
  286.            if (BFlag) { puts("\033H\033G");
  287.                 putchar(i);
  288.                 puts("\033F"); }}
  289.         Exec(rr); }
  290.        else { rr->active = 0; return 0; }}
  291.     if (Freeze) rough=0;
  292.     else rough=1;
  293.     if (++(rr->Age) > 24)
  294.         if (!(Pavement & (rr->Token)))
  295.             { rr->active = 0; Freeze = 0; return 0; }
  296.     ddx = rr->dx;
  297.     left = rr->X; right = left+(rr->width);
  298.     if (left < 1) ddx = rough;
  299.     else if (right > 79) ddx = -rough;
  300.     else if ((!Freeze) && (!((rr->Windy) & Ranno)))
  301.      { curve = rr->Curvy;
  302.        if (Ranno & 64) ddx += 1;
  303.        if (Ranno & 1024) ddx -= 1;
  304.        if ((ddx > curve) || (ddx < (-curve))) ddx = rr->dx; }
  305.     rr->dx = ddx;
  306.     rr->X += ddx;
  307.     road(rr->X, rr->width, rr->Token);
  308.     return 0; }
  309.  
  310. /* returns 2 iff end, 0 iff crash, 1 else.    */
  311.  
  312. int Update()
  313.  {    int Eor;
  314.     SignY=32;
  315.     roll();
  316.     Eor = UpRd(&Road1) | UpRd(&Road2);
  317.     if (Eor) return 2;
  318.     Delay(SpTime[Speed]);
  319.     if ((CarX += CarDX) < 0) { CarX=0; CarDX=0; }
  320.     else if (CarX > 79) { CarX=79; CarDX=0; }
  321.     car(CarX);
  322.     if (Pavement == IBAD) return 0;
  323.     return 1; }
  324.  
  325. Delay(n)
  326.  {    char ch;
  327.     n |= 1;
  328.     while (n--)
  329.      {    putchar(0);
  330.         if (CRTChr)
  331.          { ch = getchar();
  332.            switch(ch) {
  333.             case '4':    CarDX--; break;
  334.             case '6':    CarDX++; break;
  335.             case '5':
  336.             case '2':    if (Speed>1) Speed--; Speed--;
  337.             case '8':    if (++Speed > MAXSPD) Speed=MAXSPD;
  338.                     SpeedL();
  339.                      }}}}
  340.  
  341. fork(where, dir)
  342.  struct Node *where;
  343.  {    struct Road *r1, *r2, newx;
  344.     r1 = &Road1; r2 = &Road2;
  345.     if (!(r1->active)) { r1 = &Road2; r2 = &Road1; }
  346.     r1->dx = dir; r2->dx = -dir;
  347.     r2->X = r1->X;
  348.     r2->active = 1; r2->Age = 0;
  349.     r2->Windy = r1->Windy;
  350.     r2->Curvy = r1->Curvy;
  351.     r2->width = r1->width;
  352.     r2->Next = where; r2->ToGo = -1;
  353.     Freeze = 1; }
  354.  
  355. main(argc, argv)
  356.  char **argv;
  357.  {    int i, j, Mins, Hours, Tics;
  358.     char *arg, *MapNam;
  359.     struct Node *First;
  360.     Seed = 12345;
  361.     j = SPDSCL*MAXSPD;
  362.     for (i=1; i<= MAXSPD; i++) SpTime[i] = j/i - SPDSCL;
  363.     SpTime[MAXSPD] = 0;
  364.     BFlag = 0; MapNam = "RALLY.MAP";
  365.     for (i=1; i<argc; i++)
  366.      { if (*(arg = argv[i]) == '-') switch(*++arg) {
  367.         case 'R':    Seed = atoi(++arg);
  368.                 continue;
  369.         case 'B':    BFlag++; continue; }
  370.        else MapNam = arg; }
  371.     CRTFrz = CRTChr = 0;
  372.     Freep = Free;
  373.     for (i=0; i<128; i++) Tag[i] = 0;
  374.     First = Load(MapNam);
  375. top:    srand(Seed); Ranno = rand();
  376.     Freeze=0;
  377.     puts("\033H\033J\033G\033x5\033x1\033Y8 \033K\033p");
  378.     puts(" Speed 00     Miles 0      ");
  379.     puts("\033Y8X Rally 1.2   Steve Ward ");
  380.     setmem(Image,CARY*80,255);
  381.     ImPtr = Image; ImEnd = &(Image[CARY*80]);
  382.     Road1.Token=1; Road2.Token=2;
  383.     Road1.active = 1; Road1.Age = 0; Road1.ToGo = 0;
  384.     Road1.X = 20; Road1.dx = 0;
  385.     Road2.active = 0;
  386.     CarDX = 0;
  387.     RevFlg = 0; AltFlg = 0;
  388.     Road1.ToGo = 0; Road1.Next= First;
  389.     CarX = Road1.X + (Road1.width >> 1);
  390.     Speed=3;
  391.     Update();
  392.     for (i=0; i<CARY; i++) { Update(); SpeedL(); }
  393.     Miles=0; Tenths=0;
  394.     label(Miles, LMILES); Mins=0; Hours=0; Tics=0;
  395. loop:    Ranno = rand();
  396.     Tics += SpTime[Speed]+SPDSCL;
  397.     while (Tics >= TICMIN) { Tics -= TICMIN; Mins++; };
  398.     while (Mins >= 60) { Mins -= 60; Hours++; };
  399.     if (!(i = Update()))
  400.      { puts("\033H CRASHED AFTER ");
  401. done:       printf("\033G %d Hours, %d Minutes\007!!! !!! !!!  ", Hours, Mins);
  402.        delay(10000);
  403.        goto top; }
  404.     else if (i == 2)
  405.      { puts("\033H YOU MADE IT IN ");
  406.        goto done; }
  407.     if (++Tenths >= 10)
  408.      { label(++Miles, LMILES); Tenths=0; }
  409.     goto loop;
  410.  }
  411.