BSD 4_1_snap development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Sep 1980 11:22:13 +0000 (03:22 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 15 Sep 1980 11:22:13 +0000 (03:22 -0800)
Work on file usr/src/games/mille/:ctfix
Work on file usr/src/games/mille/comp.c
Work on file usr/src/games/mille/end.c
Work on file usr/src/games/mille/init.c
Work on file usr/src/games/mille/extern.c
Work on file usr/src/games/mille/mille.c
Work on file usr/src/games/mille/move.c
Work on file usr/src/games/mille/print.c
Work on file usr/src/games/mille/save.c
Work on file usr/src/games/mille/roll.c
Work on file usr/src/games/mille/tags
Work on file usr/src/games/mille/table.c
Work on file usr/src/games/mille/types.c
Work on file usr/src/games/mille/varpush.c
Work on file usr/src/games/mille/unctrl.h

Synthesized-from: CSRG/cd1/4.1.snap

15 files changed:
usr/src/games/mille/:ctfix [new file with mode: 0644]
usr/src/games/mille/comp.c [new file with mode: 0644]
usr/src/games/mille/end.c [new file with mode: 0644]
usr/src/games/mille/extern.c [new file with mode: 0644]
usr/src/games/mille/init.c [new file with mode: 0644]
usr/src/games/mille/mille.c [new file with mode: 0644]
usr/src/games/mille/move.c [new file with mode: 0644]
usr/src/games/mille/print.c [new file with mode: 0644]
usr/src/games/mille/roll.c [new file with mode: 0644]
usr/src/games/mille/save.c [new file with mode: 0644]
usr/src/games/mille/table.c [new file with mode: 0644]
usr/src/games/mille/tags [new file with mode: 0644]
usr/src/games/mille/types.c [new file with mode: 0644]
usr/src/games/mille/unctrl.h [new file with mode: 0644]
usr/src/games/mille/varpush.c [new file with mode: 0644]

diff --git a/usr/src/games/mille/:ctfix b/usr/src/games/mille/:ctfix
new file mode 100644 (file)
index 0000000..30e5daf
--- /dev/null
@@ -0,0 +1,3 @@
+/^Mmille/s//main/
+w
+q
diff --git a/usr/src/games/mille/comp.c b/usr/src/games/mille/comp.c
new file mode 100644 (file)
index 0000000..2d8bbf8
--- /dev/null
@@ -0,0 +1,391 @@
+# include      "mille.h"
+
+# define       V_VALUABLE      40
+
+calcmove() {
+
+       reg CARD        card;
+       reg int         *value;
+       reg PLAY        *pp, *op;
+       reg bool        foundend, cango, canstop, foundlow;
+       reg unsgn int   i, count200, badcount, nummin, nummax, diff;
+       reg int         curmin, curmax;
+       reg CARD        safe, oppos;
+       int             valbuf[HAND_SZ], count[NUM_CARDS];
+       bool            playit[HAND_SZ];
+
+       wmove(Score, ERR_Y, ERR_X);     /* get rid of error messages    */
+       wclrtoeol(Score);
+       pp = &Player[COMP];
+       op = &Player[PLAYER];
+       safe = 0;
+       cango = 0;
+       canstop = FALSE;
+       foundend = FALSE;
+       for (i = 0; i < NUM_CARDS; i++)
+               count[i] = 0;
+       for (i = 0; i < HAND_SZ; i++) {
+               card = pp->hand[i];
+               switch (card) {
+                 case C_STOP:  case C_CRASH:
+                 case C_FLAT:  case C_EMPTY:
+                       if (playit[i] = canplay(pp, op, card))
+                               canstop = TRUE;
+                       goto norm;
+                 case C_LIMIT:
+                       if ((playit[i] = canplay(pp, op, card))
+                           && Numseen[C_25] == Numcards[C_25]
+                           && Numseen[C_50] == Numcards[C_50])
+                               canstop = TRUE;
+                       goto norm;
+                 case C_25:    case C_50:      case C_75:
+                 case C_100:   case C_200:
+                       if ((playit[i] = canplay(pp, op, card))
+                           && pp->mileage + Value[card] == End)
+                               foundend = TRUE;
+                       goto norm;
+                 default:
+                       playit[i] = canplay(pp, op, card);
+norm:
+                       if (playit[i])
+                               ++cango;
+                       break;
+                 case C_GAS_SAFE:      case C_DRIVE_SAFE:
+                 case C_SPARE_SAFE:    case C_RIGHT_WAY:
+                       if (pp->battle == opposite(card)
+                          || (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
+                               Movetype = M_PLAY;
+                               Card_no = i;
+                               return;
+                       }
+                       ++safe;
+                       playit[i] = TRUE;
+                       break;
+               }
+               ++count[card];
+       }
+       if (pp->hand[0] == C_INIT && Topcard > Deck) {
+               Movetype = M_DRAW;
+               return;
+       }
+       if (Debug)
+               fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n", cango, canstop, safe);
+       if (foundend)
+               foundend = !check_ext(TRUE);
+       for (i = 0; safe && i < HAND_SZ; i++) {
+               if (issafety(pp->hand[i])) {
+                       if (onecard(op) || (foundend && cango && !canstop)) {
+                               if (Debug)
+                                       fprintf(outf, "CALCMOVE: onecard(op) = %d, foundend = %d\n", onecard(op), foundend);
+playsafe:
+                               Movetype = M_PLAY;
+                               Card_no = i;
+                               return;
+                       }
+                       oppos = opposite(pp->hand[i]);
+                       if (Numseen[oppos] == Numcards[oppos])
+                               goto playsafe;
+                       else if (!cango
+                           && (op->can_go || !pp->can_go || Topcard < Deck)) {
+                               card = (Topcard - Deck) - roll(1, 10);
+                               if ((!pp->mileage) != (!op->mileage))
+                                       card -= 7;
+                               if (Debug)
+                                       fprintf(outf, "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n", card, DECK_SZ / 4);
+                               if (card < DECK_SZ / 4)
+                                       goto playsafe;
+                       }
+                       safe--;
+                       playit[i] = cango;
+               }
+       }
+       if (!pp->can_go && !isrepair(pp->battle))
+               Numneed[opposite(pp->battle)]++;
+redoit:
+       foundlow = (cango || count[C_END_LIMIT] != 0
+                         || Numseen[C_LIMIT] == Numcards[C_LIMIT]
+                         || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
+       foundend = FALSE;
+       count200 = pp->nummiles[C_200];
+       badcount = 0;
+       curmax = -1;
+       curmin = 101;
+       nummin = -1;
+       nummax = -1;
+       value = valbuf;
+       for (i = 0; i < HAND_SZ; i++) {
+               card = pp->hand[i];
+               if (issafety(card) || playit[i] == (cango != 0)) {
+                       if (Debug)
+                               fprintf(outf, "CALCMOVE: switch(\"%s\")\n", C_name[card]);
+                       switch (card) {
+                         case C_25:    case C_50:
+                               diff = End - pp->mileage;
+                               /* avoid getting too close */
+                               if (Topcard > Deck && cango && diff <= 100
+                                   && diff / Value[card] > count[card]
+                                   && (card == C_25 || diff % 50 == 0)) {
+                                       if (card == C_50 && diff - 50 == 25
+                                           && count[C_25] > 0)
+                                               goto okay;
+                                       *value = 0;
+                                       if (--cango <= 0)
+                                               goto redoit;
+                                       break;
+                               }
+okay:
+                               *value = (Value[card] >> 3);
+                               if (pp->speed == C_LIMIT)
+                                       ++*value;
+                               else
+                                       --*value;
+                               if (!foundlow
+                                  && (card == C_50 || count[C_50] == 0)) {
+                                       *value = (pp->mileage ? 10 : 20);
+                                       foundlow = TRUE;
+                               }
+                               goto miles;
+                         case C_200:
+                               if (++count200 > 2) {
+                                       *value = 0;
+                                       break;
+                               }
+                         case C_75:    case C_100:
+                               *value = (Value[card] >> 3);
+                               if (pp->speed == C_LIMIT)
+                                       --*value;
+                               else
+                                       ++*value;
+miles:
+                               if (pp->mileage + Value[card] > End)
+                                       *value = (End == 700 ? card : 0);
+                               else if (pp->mileage + Value[card] == End) {
+                                       *value = (foundend ? card : V_VALUABLE);
+                                       foundend = TRUE;
+                               }
+                               break;
+                         case C_END_LIMIT:
+                               if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
+                                       *value = (pp->safety[S_RIGHT_WAY] == S_PLAYED ? -1 : 1);
+                               else if (pp->speed == C_LIMIT && End - pp->mileage <= 50)
+                                       *value = 1;
+                               else if (pp->speed == C_LIMIT
+                                   || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
+                                       safe = S_RIGHT_WAY;
+                                       oppos = C_LIMIT;
+                                       goto repair;
+                               }
+                               else {
+                                       *value = 0;
+                                       --count[C_END_LIMIT];
+                               }
+                               break;
+                         case C_REPAIRS:       case C_SPARE:   case C_GAS:
+                               safe = safety(card) - S_CONV;
+                               oppos = opposite(card);
+                               if (pp->safety[safe] != S_UNKNOWN)
+                                       *value = (pp->safety[safe] == S_PLAYED ? -1 : 1);
+                               else if (pp->battle != oppos
+                                   && (Numseen[oppos] == Numcards[oppos] || Numseen[oppos] + count[card] > Numcards[oppos])) {
+                                       *value = 0;
+                                       --count[card];
+                               }
+                               else {
+repair:
+                                       *value = Numcards[oppos] * 6;
+                                       *value += (Numseen[card] - Numseen[oppos]);
+                                       if (!cango)
+                                           *value /= (count[card]*count[card]);
+                                       count[card]--;
+                               }
+                               break;
+                         case C_GO:
+                               if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
+                                       *value = (pp->safety[S_RIGHT_WAY] == S_PLAYED ? -1 : 2);
+                               else if (pp->can_go
+                                && Numgos + count[C_GO] == Numneed[C_GO]) {
+                                       *value = 0;
+                                       --count[C_GO];
+                               }
+                               else {
+                                       *value = Numneed[C_GO] * 3;
+                                       *value += (Numseen[C_GO] - Numgos);
+                                       *value /= (count[C_GO] * count[C_GO]);
+                                       count[C_GO]--;
+                               }
+                               break;
+                         case C_LIMIT:
+                               if (op->mileage + 50 >= End) {
+                                       *value = (End == 700 && !cango);
+                                       break;
+                               }
+                               if (canstop || (cango && !op->can_go))
+                                       *value = 1;
+                               else {
+                                       *value = (pp->safety[S_RIGHT_WAY] != S_UNKNOWN ? 2 : 3);
+                                       safe = S_RIGHT_WAY;
+                                       oppos = C_END_LIMIT;
+                                       goto normbad;
+                               }
+                               break;
+                         case C_CRASH: case C_EMPTY:   case C_FLAT:
+                               safe = safety(card) - S_CONV;
+                               oppos = opposite(card);
+                               *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
+normbad:
+                               if (op->safety[safe] == S_PLAYED)
+                                       *value = -1;
+                               else {
+                                   *value *= (Numneed[oppos] + Numseen[oppos] + 2);
+                                   if (!pp->mileage || foundend || onecard(op))
+                                       *value += 5;
+                                   if (op->mileage == 0 || onecard(op))
+                                       *value += 5;
+                                   if (op->speed == C_LIMIT)
+                                       *value -= 3;
+                                   if (cango && pp->safety[safe] != S_UNKNOWN)
+                                       *value += 3;
+                                   if (!cango)
+                                       *value /= ++badcount;
+                               }
+                               break;
+                         case C_STOP:
+                               if (op->safety[S_RIGHT_WAY] == S_PLAYED)
+                                       *value = -1;
+                               else {
+                                   *value = (pp->safety[S_RIGHT_WAY] != S_UNKNOWN ? 3 : 4);
+                                   *value *= (Numcards[C_STOP] + Numseen[C_GO]);
+                                   if (!pp->mileage || foundend || onecard(op))
+                                       *value += 5;
+                                   if (!cango)
+                                       *value /= ++badcount;
+                                   if (op->mileage == 0)
+                                       *value += 5;
+                                   if ((card == C_LIMIT
+                                     && op->speed == C_LIMIT) || (!op->can_go))
+                                       *value -= 5;
+                                   if (cango && pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
+                                       *value += 5;
+                               }
+                               break;
+                         case C_GAS_SAFE:      case C_DRIVE_SAFE:
+                         case C_SPARE_SAFE:    case C_RIGHT_WAY:
+                               *value = cango ? 0 : 101;
+                               break;
+                         case C_INIT:
+                               *value = 0;
+                       }
+               }
+               else
+                       *value = cango ? 0 : 101;
+               if (card != C_INIT) {
+                       if (*value >= curmax) {
+                               nummax = i;
+                               curmax = *value;
+                       }
+                       if (*value <= curmin) {
+                               nummin = i;
+                               curmin = *value;
+                       }
+               }
+               if (Debug)
+                       mvprintw(i+6,2,"%3d %-14s",*value,C_name[pp->hand[i]]);
+               value++;
+       }
+       if (!pp->can_go && !isrepair(pp->battle))
+               Numneed[opposite(pp->battle)]++;
+       if (cango) {
+               mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
+               if (Debug)
+                       getmove();
+               if (!Debug || Movetype == M_DRAW) {
+                       Movetype = M_PLAY;
+                       Card_no = nummax;
+               }
+       }
+       else {
+               mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
+               if (Debug)
+                       getmove();
+               if (!Debug || Movetype == M_DRAW) {
+                       Movetype = M_DISCARD;
+                       Card_no = nummin;
+               }
+       }
+       mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
+}
+
+onecard(pp)
+reg PLAY       *pp; {
+
+       reg CARD        bat, spd, card;
+
+       bat = pp->battle;
+       spd = pp->speed;
+       card = -1;
+       if (pp->can_go || ((isrepair(bat) || bat == C_STOP
+           || spd == C_LIMIT) && Numseen[S_RIGHT_WAY] != 0)
+           || Numseen[safety(bat)] != 0)
+               switch (End - pp->mileage) {
+                 case 200:
+                       if (pp->nummiles[C_200] == 2)
+                               return FALSE;
+                       card = C_200;
+                 case 100:
+                 case 75:
+                       if (card == -1)
+                               card = (End - pp->mileage == 75 ? C_75 : C_100);
+                       if (spd == C_LIMIT)
+                               return Numseen[S_RIGHT_WAY] == 0;
+                 case 50:
+                 case 25:
+                       if (card == -1)
+                               card = (End - pp->mileage == 25 ? C_25 : C_50);
+                       return Numseen[card] != Numcards[card];
+               }
+       return FALSE;
+}
+
+canplay(pp, op, card)
+reg PLAY       *pp, *op;
+reg CARD       card; {
+
+       switch (card) {
+         case C_200:
+               if (pp->nummiles[C_200] == 2)
+                       break;
+         case C_75:    case C_100:
+               if (pp->speed == C_LIMIT)
+                       break;
+         case C_50:
+               if (pp->mileage + Value[card] > End)
+                       break;
+         case C_25:
+               if (pp->can_go)
+                       return TRUE;
+               break;
+         case C_EMPTY: case C_FLAT:    case C_CRASH:
+         case C_STOP:
+               if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
+                       return TRUE;
+               break;
+         case C_LIMIT:
+               if (op->speed != C_LIMIT && op->safety[S_RIGHT_WAY] != S_PLAYED
+                   && op->mileage + 50 < End)
+                       return TRUE;
+               break;
+         case C_GAS:   case C_SPARE:   case C_REPAIRS:
+               if (pp->battle == opposite(card))
+                       return TRUE;
+               break;
+         case C_GO:
+               if (!pp->can_go
+                   && (isrepair(pp->battle) || pp->battle == C_STOP))
+                       return TRUE;
+               break;
+         case C_END_LIMIT:
+               if (pp->speed == C_LIMIT)
+                       return TRUE;
+       }
+       return FALSE;
+}
diff --git a/usr/src/games/mille/end.c b/usr/src/games/mille/end.c
new file mode 100644 (file)
index 0000000..eac01f2
--- /dev/null
@@ -0,0 +1,103 @@
+# include      "mille.h"
+
+/*
+ *     print out the score as if it was final, and add the totals for
+ * the end-of-games points to the user who deserves it (if any).
+ */
+finalscore(pp)
+reg PLAY       *pp; {
+
+       reg int         temp, tot, num;
+
+       num = pp - Player;
+       temp = num * 6 + 21 + 3;
+       for (tot = 5; tot <= 9; tot++)
+               mvaddch(tot, temp, '0');
+       if (pp->mileage == End) {
+               temp -= 2;
+               mvaddstr(5, temp, "40");
+               tot = SC_TRIP;
+               if (pp->nummiles[C_200] == 0) {
+                       mvaddstr(6, temp, "30");
+                       tot = SC_TRIP + SC_SAFE;
+               }
+               if (Topcard <= Deck) {
+                       mvaddstr(7, temp, "30");
+                       tot += SC_DELAY;
+               }
+               if (End == 1000) {
+                       mvaddstr(8, temp, "20");
+                       tot += SC_EXTENSION;
+               }
+               if (Player[other(num)].mileage == 0) {
+                       mvaddstr(9, temp, "50");
+                       tot += SC_SHUT_OUT;
+               }
+               pp->total += tot;
+               pp->hand_tot += tot;
+       }
+}
+
+# ifdef EXTRAP
+static int     Last_tot[2];    /* last tot used for extrapolate        */
+
+/*
+ *     print out the score as if it was final, and add the totals for
+ * the end-of-games points to the user who deserves it (if any).
+ */
+extrapolate(pp)
+reg PLAY       *pp; {
+
+       reg int         x, num, tot, count;
+
+       num = pp - Player;
+       tot += SC_TRIP + SC_DELAY + SC_EXT;
+       x = num * 6 + 21 + 3;
+       for (tot = 5; tot <= 9; tot++)
+               mvaddch(tot, x, '0');
+       x -= 2;
+       pp = &Player[other(num)];
+       for (count = 0, tot = 0; tot < NUM_SAFE; tot++)
+               if (pp->safety[tot] != S_PLAYED)
+                       count += SC_SAFE;
+       mvprintw(3, x, "%3d", count);
+       tot += count;
+       if (count == 400) {
+               mvaddstr(4, x, "30");
+               tot += SC_ALL_SAFE;
+       }
+       pp = &Player[num];
+       for (count = 0, tot = 0; tot < NUM_SAFE; tot++)
+               if (pp->safety[tot] != S_PLAYED)
+                       count += SC_COUP / 10;
+       mvprintw(4, x - 1, "%3d", count);
+       tot += count;
+       tot += 1000 - pp->mileage;
+       mvaddstr(5, x, "40");
+       mvaddstr(7, x, "30");
+       mvaddstr(8, x, "20");
+       if (pp->nummiles[C_200] == 0) {
+               mvaddstr(6, x, "30");
+               tot = SC_TRIP + SC_SAFE;
+       }
+       if (Player[other(num)].mileage == 0) {
+               mvaddstr(9, x, "50");
+               tot += SC_SHUT_OUT;
+       }
+       pp->total += tot;
+       pp->hand_tot += tot;
+       Last_tot[num] = tot;
+}
+
+undoex() {
+
+       reg PLAY        *pp;
+       reg int         i;
+
+       i = 0;
+       for (pp = Player; pp < &Player[2]; pp++) {
+               pp->total -= Last_tot[i];
+               pp->hand_tot -= Last_tot[i++];
+       }
+}
+# endif
diff --git a/usr/src/games/mille/extern.c b/usr/src/games/mille/extern.c
new file mode 100644 (file)
index 0000000..f0eeaed
--- /dev/null
@@ -0,0 +1,129 @@
+# include      "mille.h"
+
+bool   Debug,                  /* set if debugging code on             */
+       Finished,               /* set if current hand is finished      */
+       Next,                   /* set if changing players              */
+       On_exit,                /* set if game saved on exiting         */
+       Order,                  /* set if hand should be sorted         */
+       Saved;                  /* set if game just saved               */
+
+char   *C_fmt = "%-18.18s",    /* format for printing cards            */
+       *Fromfile = NULL,       /* startup file for game                */
+       Initstr[100],           /* initial string for error field       */
+       *_cn[NUM_CARDS] = {     /* Card name buffer                     */
+               "",
+               "25",
+               "50",
+               "75",
+               "100",
+               "200",
+               "Out of Gas",
+               "Flat Tire",
+               "Accident",
+               "Stop",
+               "Speed Limit", 
+               "Gasoline",
+               "Spare Tire",
+               "Repairs",
+               "Go",
+               "End of Limit",
+               "Extra Tank",
+               "Puncture Proof",
+               "Driving Ace",
+               "Right of Way"
+       },
+       **C_name = &_cn[1];     /* Card names                           */
+
+int    Card_no,                /* Card number for current move         */
+       End,                    /* End value for current hand           */
+       Handstart = COMP,       /* Player who starts hand               */
+       Movetype,               /* Current move type                    */
+       Play,                   /* Current player                       */
+       Numgos,                 /* Number of Go cards used by computer  */
+       Window = W_SMALL,       /* Current window wanted                */
+       Numseen[NUM_CARDS],     /* Number of cards seen in current hand */
+       Value[NUM_MILES] = {    /* Value of mileage cards               */
+               25, 50, 75, 100, 200
+       },
+       Numcards[NUM_CARDS] = { /* Number of cards in deck              */
+               10,     /* C_25 */
+               10,     /* C_50 */
+               10,     /* C_75 */
+               12,     /* C_100 */
+               4,      /* C_200 */
+               2,      /* C_EMPTY */
+               2,      /* C_FLAT */
+               2,      /* C_CRASH */
+               4,      /* C_STOP */
+               3,      /* C_LIMIT */
+               6,      /* C_GAS */
+               6,      /* C_SPARE */
+               6,      /* C_REPAIRS */
+               14,     /* C_GO */
+               6,      /* C_END_LIMIT */
+               1,      /* C_GAS_SAFE */
+               1,      /* C_SPARE_SAFE */
+               1,      /* C_DRIVE_SAFE */
+               1,      /* C_RIGHT_WAY */
+               0       /* C_INIT */
+       };
+       Numneed[NUM_CARDS] = {  /* number of cards needed per hand      */
+               0,      /* C_25 */
+               0,      /* C_50 */
+               0,      /* C_75 */
+               0,      /* C_100 */
+               0,      /* C_200 */
+               2,      /* C_EMPTY */
+               2,      /* C_FLAT */
+               2,      /* C_CRASH */
+               4,      /* C_STOP */
+               3,      /* C_LIMIT */
+               2,      /* C_GAS */
+               2,      /* C_SPARE */
+               2,      /* C_REPAIRS */
+               10,     /* C_GO */
+               3,      /* C_END_LIMIT */
+               1,      /* C_GAS_SAFE */
+               1,      /* C_SPARE_SAFE */
+               1,      /* C_DRIVE_SAFE */
+               1,      /* C_RIGHT_WAY */
+               0       /* C_INIT */
+       };
+
+CARD   Discard,                /* Top of discard pile                  */
+       *Topcard,               /* Pointer to next card to be picked    */
+       Opposite[NUM_CARDS] = { /* Opposites of each card               */
+               C_25, C_50, C_75, C_100, C_200, C_GAS, C_SPARE,
+               C_REPAIRS, C_GO, C_END_LIMIT, C_EMPTY, C_FLAT, C_CRASH,
+               C_STOP, C_LIMIT, C_EMPTY, C_FLAT, C_CRASH, C_STOP, C_INIT
+       },
+       Deck[DECK_SZ] = {       /* Current deck                         */
+               C_25, C_25, C_25, C_25, C_25, C_25, C_25, C_25, C_25, C_25,
+               C_50, C_50, C_50, C_50, C_50, C_50, C_50, C_50, C_50, C_50,
+               C_75, C_75, C_75, C_75, C_75, C_75, C_75, C_75, C_75, C_75,
+               C_100, C_100, C_100, C_100, C_100, C_100, C_100, C_100, C_100,
+               C_100, C_100, C_100,
+               C_200, C_200, C_200, C_200,
+               C_EMPTY, C_EMPTY,
+               C_FLAT, C_FLAT,
+               C_CRASH, C_CRASH,
+               C_STOP, C_STOP, C_STOP, C_STOP,
+               C_LIMIT, C_LIMIT, C_LIMIT,
+               C_GAS, C_GAS, C_GAS, C_GAS, C_GAS, C_GAS,
+               C_SPARE, C_SPARE, C_SPARE, C_SPARE, C_SPARE, C_SPARE,
+               C_REPAIRS, C_REPAIRS, C_REPAIRS, C_REPAIRS, C_REPAIRS,
+                       C_REPAIRS,
+               C_END_LIMIT, C_END_LIMIT, C_END_LIMIT, C_END_LIMIT, C_END_LIMIT,
+                       C_END_LIMIT,
+               C_GO, C_GO, C_GO, C_GO, C_GO, C_GO, C_GO, C_GO, C_GO, C_GO,
+                       C_GO, C_GO, C_GO, C_GO,
+               C_GAS_SAFE, C_SPARE_SAFE, C_DRIVE_SAFE, C_RIGHT_WAY
+       };
+
+FILE   *outf;
+
+PLAY   Player[2];              /* Player descriptions                  */
+
+WINDOW *Board,                 /* Playing field screen                 */
+       *Miles,                 /* Mileage screen                       */
+       *Score;                 /* Score screen                         */
diff --git a/usr/src/games/mille/init.c b/usr/src/games/mille/init.c
new file mode 100644 (file)
index 0000000..ac52d52
--- /dev/null
@@ -0,0 +1,156 @@
+# include      "mille.h"
+
+init() {
+
+       reg PLAY        *pp;
+       reg int         i, j;
+       reg CARD        card;
+
+       for (j = 0; j < C_RIGHT_WAY; j++)
+               Numseen[j] = 0;
+       Numgos = 0;
+
+       for (i = 0; i < 2; i++) {
+               pp = &Player[i];
+               pp->hand[0] = C_INIT;
+               for (j = 0; j < NUM_SAFE; j++) {
+                       pp->safety[j] = S_UNKNOWN;
+                       pp->coups[j] = FALSE;
+               }
+               for (j = 1; j < HAND_SZ; j++) {
+                       pp->hand[j] = *--Topcard;
+                       if (i == COMP) {
+                               account(card = *Topcard);
+                               if (issafety(card))
+                                       pp->safety[card - S_CONV] = S_IN_HAND;
+                       }
+               }
+               pp->mileage = 0;
+               pp->hand_tot = 0;
+               pp->safescore = 0;
+               pp->coupscore = 0;
+               pp->can_go = FALSE;
+               pp->speed = C_INIT;
+               pp->battle = C_INIT;
+               pp->new_speed = FALSE;
+               pp->new_battle = FALSE;
+               for (j = 0; j < NUM_MILES; j++)
+                       pp->nummiles[j] = 0;
+       }
+       if (Order)
+               sort(Player[PLAYER].hand);
+       Discard = C_INIT;
+       Finished = FALSE;
+       End = 700;
+}
+
+shuffle() {
+
+       reg int         i, r;
+       reg CARD        temp;
+
+       for (i = 0; i < DECK_SZ; i++) {
+               r = roll(1, DECK_SZ) - 1;
+               if (r < 0 || r > DECK_SZ - 1) {
+                       fprintf(stderr, "shuffle: card no. error: %d\n", r);
+                       die();
+               }
+               temp = Deck[r];
+               Deck[r] = Deck[i];
+               Deck[i] = temp;
+       }
+       Topcard = &Deck[DECK_SZ];
+}
+
+newboard() {
+
+       werase(Board);
+       werase(Score);
+       mvaddstr(5, 0, "--HAND--");
+       mvaddch(6, 0, 'P');
+       mvaddch(7, 0, '1');
+       mvaddch(8, 0, '2');
+       mvaddch(9, 0, '3');
+       mvaddch(10, 0, '4');
+       mvaddch(11, 0, '5');
+       mvaddch(12, 0, '6');
+       mvaddstr(13, 0, "--BATTLE--");
+       mvaddstr(15, 0, "--SPEED--");
+       mvaddstr(5, 20, "--DECK--");
+       mvaddstr(7, 20, "--DISCARD--");
+       mvaddstr(13, 20, "--BATTLE--");
+       mvaddstr(15, 20, "--SPEED--");
+       wmove(Miles, 0, 0);
+       if (winch(Miles) != '-') {
+               werase(Miles);
+               mvwaddstr(Miles, 0, 0, "--MILEAGE--");
+               mvwaddstr(Miles, 0, 41, "--MILEAGE--");
+       }
+       else {
+               wmove(Miles, 1, 0);
+               wclrtobot(Miles);
+       }
+       newscore();
+       stdscr = Board;
+}
+
+newscore() {
+
+       reg int i;
+
+       stdscr = Score;
+       move(0, 22);
+       if (inch() != 'Y') {
+               erase();
+               mvaddstr(0, 22,  "You   Comp   Value");
+               mvaddstr(1, 2, "Milestones Played");
+               mvaddstr(2, 8, "Each Safety");
+               mvaddstr(3, 5, "All 4 Safeties");
+               mvaddstr(4, 3, "Each Coup Fourre");
+               mvaddstr(2, 37, "100");
+               mvaddstr(3, 37, "300");
+               mvaddstr(4, 37, "300");
+       }
+       else {
+               move(5, 1);
+               clrtobot();
+       }
+       for (i = 0; i < SCORE_Y; i++)
+               mvaddch(i, 0, '|');
+       move(SCORE_Y - 1, 1);
+       while (addch('_') != ERR)
+               continue;
+       if (Window == W_FULL || Finished) {
+               mvaddstr(5, 5, "Trip Completed");
+               mvaddstr(6, 10, "Safe Trip");
+               mvaddstr(7, 5, "Delayed Action");
+               mvaddstr(8, 10, "Extension");
+               mvaddstr(9, 11, "Shut-Out");
+               mvaddstr(10, 21, "----   ----   -----");
+               mvaddstr(11, 9, "Hand Total");
+               mvaddstr(12, 20, "-----  -----");
+               mvaddstr(13, 6, "Overall Total");
+               mvaddstr(14, 15, "Games");
+               mvaddstr(5, 37, "400");
+               mvaddstr(6, 37, "300");
+               mvaddstr(7, 37, "300");
+               mvaddstr(8, 37, "200");
+               mvaddstr(9, 37, "500");
+       }
+       else {
+               mvaddstr(5, 21, "----   ----   -----");
+               mvaddstr(6, 9, "Hand Total");
+               mvaddstr(7, 20, "-----  -----");
+               mvaddstr(8, 6, "Overall Total");
+               mvaddstr(9, 15, "Games");
+               mvaddstr(11, 2, "p: pick");
+               mvaddstr(12, 2, "u: use #");
+               mvaddstr(13, 2, "d: discard #");
+               mvaddstr(14, 2, "w: toggle window");
+               mvaddstr(11, 21, "q: quit");
+               mvaddstr(12, 21, "o: order hand");
+               mvaddstr(13, 21, "s: save");
+               mvaddstr(14, 21, "r: reprint");
+       }
+       stdscr = Board;
+}
diff --git a/usr/src/games/mille/mille.c b/usr/src/games/mille/mille.c
new file mode 100644 (file)
index 0000000..a3e0d5d
--- /dev/null
@@ -0,0 +1,132 @@
+# include      "mille.h"
+# include      <signal.h>
+
+int    rub(), tstp();
+
+char   _sobuf[BUFSIZ];
+
+main(ac, av)
+reg int                ac;
+reg char       *av[]; {
+
+       reg bool        restore;
+
+# if 0
+       if (getuid() == GURP) {
+               printf("%s: Permission denied\n", av[0]);
+               exit(1);
+       }
+# endif
+       if (strcmp(av[0], "a.out") == 0) {
+               outf = fopen("q", "w");
+               setbuf(outf, 0);
+               Debug = TRUE;
+       }
+       restore = FALSE;
+# ifdef pdp11
+       if (geteuid() != ARNOLD)
+               maxusers(MAXUSERS, NULL);
+# endif
+       switch (ac) {
+         case 2:
+               rest_f(av[1]);
+               restore = TRUE;
+         case 1:
+               break;
+         default:
+               printf("usage: milles [ restore_file ]\n");
+               exit(-1);
+               /* NOTREACHED */
+       }
+       setbuf(stdout, _sobuf);
+       Play = PLAYER;
+       initscr();
+       if (!CA) {
+               printf("Sorry.  Need cursor addressing to play mille\n");
+               exit(-1);
+       }
+       delwin(stdscr);
+       stdscr = Board = newwin(BOARD_Y, BOARD_X, 0, 0);
+       Score = newwin(SCORE_Y, SCORE_X, 0, 40);
+       Miles = newwin(MILES_Y, MILES_X, 17, 0);
+       leaveok(Score, TRUE);
+       leaveok(Miles, TRUE);
+       clearok(curscr, TRUE);
+# ifndef PROF
+       srand(getpid());
+# else
+       srand(0);
+# endif
+       crmode();
+       noecho();
+       signal(SIGINT, rub);
+       signal(SIGTSTP, tstp);
+       for (;;) {
+               if (!restore || (Player[PLAYER].total >= 5000
+                   || Player[COMP].total >= 5000)) {
+                       if (Player[COMP].total < Player[PLAYER].total)
+                               Player[PLAYER].games++;
+                       else if (Player[COMP].total > Player[PLAYER].total)
+                               Player[COMP].games++;
+                       Player[COMP].total = 0;
+                       Player[PLAYER].total = 0;
+               }
+               do {
+                       if (!restore)
+                               Handstart = Play = other(Handstart);
+                       if (!restore || On_exit) {
+                               shuffle();
+                               init();
+                       }
+                       newboard();
+                       if (restore)
+                               mvwaddstr(Score, ERR_Y, ERR_X, Initstr);
+                       prboard();
+                       do {
+                               domove();
+                               if (Finished)
+                                       newscore();
+                               prboard();
+                       } while (!Finished);
+                       check_more();
+                       restore = On_exit = FALSE;
+               } while (Player[COMP].total < 5000
+                   && Player[PLAYER].total < 5000);
+       }
+}
+
+/*
+ *     Routine to trap rubouts, and make sure they really want to
+ * quit.
+ */
+rub() {
+
+       signal(SIGINT, 1);
+       if (getyn("Really? "))
+               die();
+       signal(SIGINT, rub);
+}
+
+/*
+ *     Time to go beddy-by
+ */
+die() {
+
+       signal(SIGINT, 1);
+       if (outf)
+               fflush(outf);
+       mvcur(0, COLS - 1, LINES - 1, 0);
+       endwin();
+       exit(1);
+}
+
+tstp() {
+
+       if (outf)
+               fflush(outf);
+       resetty();
+       kill(0, SIGTSTP);
+       signal(SIGTSTP, tstp);
+       noecho();
+       crmode();
+}
diff --git a/usr/src/games/mille/move.c b/usr/src/games/mille/move.c
new file mode 100644 (file)
index 0000000..46343fb
--- /dev/null
@@ -0,0 +1,465 @@
+#include       "mille.h"
+#include       "unctrl.h"
+
+#define        CTRL(c)         (c - 'A' + 1)
+
+char   *Movenames[] = {
+               "M_DISCARD", "M_DRAW", "M_PLAY", "M_ORDER"
+       };
+
+domove()
+{
+       reg PLAY        *pp;
+       reg int         i, j;
+       reg bool        goodplay;
+
+       pp = &Player[Play];
+       if (Play == PLAYER)
+               getmove();
+       else
+               calcmove();
+       Next = FALSE;
+       goodplay = TRUE;
+       switch (Movetype) {
+         case M_DISCARD:
+               if (haspicked(pp)) {
+                       if (pp->hand[Card_no] == C_INIT)
+                               if (Card_no == 6)
+                                       Finished = TRUE;
+                               else
+                                       error("no card there");
+                       else {
+                               Discard = pp->hand[Card_no];
+                               pp->hand[Card_no] = C_INIT;
+                               Next = TRUE;
+                               if (Play == PLAYER)
+                                       account(Discard);
+                       }
+               }
+               else
+                       error("must pick first");
+               break;
+         case M_PLAY:
+               goodplay = playcard(pp);
+               break;
+         case M_DRAW:
+               Card_no = 0;
+               if (Topcard <= Deck)
+                       error("no more cards");
+               else if (haspicked(pp))
+                       error("already picked");
+               else {
+                       pp->hand[0] = *--Topcard;
+                       if (Debug)
+                               fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
+acc:
+                       if (Play == COMP) {
+                               account(*Topcard);
+                               if (issafety(*Topcard))
+                                       pp->safety[*Topcard-S_CONV] = S_IN_HAND;
+                       }
+                       if (pp->hand[1] == C_INIT && Topcard > Deck) {
+                               Card_no = 1;
+                               pp->hand[1] = *--Topcard;
+                               if (Debug)
+                                       fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
+                               goto acc;
+                       }
+                       pp->new_battle = FALSE;
+                       pp->new_speed = FALSE;
+               }
+               break;
+
+         case M_ORDER:
+               break;
+       }
+       /*
+        * move blank card to top by one of two methods.  If the
+        * computer's hand was sorted, the randomness for picking
+        * between equally valued cards would be lost
+        */
+       if (Order && Movetype != M_DRAW && goodplay && pp == &Player[PLAYER])
+               sort(pp->hand);
+       else
+               for (i = 1; i < HAND_SZ; i++)
+                       if (pp->hand[i] == C_INIT) {
+                               for (j = 0; pp->hand[j] == C_INIT; j++)
+                                       if (j >= HAND_SZ) {
+                                               j = 0;
+                                               break;
+                                       }
+                               pp->hand[i] = pp->hand[j];
+                               pp->hand[j] = C_INIT;
+                       }
+       if (Topcard <= Deck)
+               check_go();
+       if (Next)
+               nextplay();
+}
+
+/*
+ *     Check and see if either side can go.  If they cannot,
+ * the game is over
+ */
+check_go() {
+
+       reg CARD        card;
+       reg PLAY        *pp, *op;
+       reg int         i;
+
+       for (pp = Player; pp < &Player[2]; pp++) {
+               op = (pp == &Player[COMP] ? &Player[PLAYER] : &Player[COMP]);
+               for (i = 0; i < HAND_SZ; i++) {
+                       card = pp->hand[i];
+                       if (issafety(card) || canplay(pp, op, card)) {
+                               if (Debug) {
+                                       fprintf(outf, "CHECK_GO: can play %s (%d), ", C_name[card], card);
+                                       fprintf(outf, "issafety(card) = %d, ", issafety(card));
+                                       fprintf(outf, "canplay(pp, op, card) = %d\n", canplay(pp, op, card));
+                               }
+                               return;
+                       }
+                       else if (Debug)
+                               fprintf(outf, "CHECK_GO: cannot play %s\n",
+                                   C_name[card]);
+               }
+       }
+       Finished = TRUE;
+}
+
+playcard(pp)
+reg PLAY       *pp;
+{
+       reg int         v;
+       reg CARD        card;
+
+       /*
+        * check and see if player has picked
+        */
+       switch (pp->hand[Card_no]) {
+         default:
+               if (!haspicked(pp))
+mustpick:
+                       return error("must pick first");
+         case C_GAS_SAFE:      case C_SPARE_SAFE:
+         case C_DRIVE_SAFE:    case C_RIGHT_WAY:
+               break;
+       }
+
+       card = pp->hand[Card_no];
+       if (Debug)
+               fprintf(outf, "PLAYCARD: Card = %s\n", C_name[card]);
+       Next = FALSE;
+       switch (card) {
+         case C_200:
+               if (pp->nummiles[C_200] == 2)
+                       return error("only two 200's per hand");
+         case C_100:   case C_75:
+               if (pp->speed == C_LIMIT)
+                       return error("limit of 50");
+         case C_50:
+               if (pp->mileage + Value[card] > End)
+                       return error("puts you over %d", End);
+         case C_25:
+               if (!pp->can_go)
+                       return error("cannot move now");
+               pp->nummiles[card]++;
+               v = Value[card];
+               pp->total += v;
+               pp->hand_tot += v;
+               if ((pp->mileage += v) == End)
+                       check_ext(FALSE);
+               break;
+
+         case C_GAS:   case C_SPARE:   case C_REPAIRS:
+               if (pp->battle != opposite(card))
+                       return error("can't play \"%s\"", C_name[card]);
+               pp->battle = card;
+               if (pp->safety[S_RIGHT_WAY] == S_PLAYED)
+                       pp->can_go = TRUE;
+               break;
+
+         case C_GO:
+               if (pp->battle != C_INIT && pp->battle != C_STOP
+                   && !isrepair(pp->battle))
+                       return error("cannot play \"Go\" on a \"%s\"",
+                           C_name[pp->battle]);
+               pp->battle = C_GO;
+               pp->can_go = TRUE;
+               break;
+
+         case C_END_LIMIT:
+               if (pp->speed != C_LIMIT)
+                       return error("not limited");
+               pp->speed = C_END_LIMIT;
+               break;
+
+         case C_EMPTY: case C_FLAT:    case C_CRASH:
+         case C_STOP:
+               pp = &Player[other(Play)];
+               if (!pp->can_go)
+                       return error("opponent cannot go");
+               else if (pp->safety[safety(card) - S_CONV] == S_PLAYED)
+protected:
+                       return error("opponent is protected");
+               pp->battle = card;
+               pp->new_battle = TRUE;
+               pp->can_go = FALSE;
+               pp = &Player[Play];
+               break;
+
+         case C_LIMIT:
+               pp = &Player[other(Play)];
+               if (pp->speed == C_LIMIT)
+                       return error("opponent has limit");
+               if (pp->safety[S_RIGHT_WAY] == S_PLAYED)
+                       goto protected;
+               pp->speed = C_LIMIT;
+               pp->new_speed = TRUE;
+               pp = &Player[Play];
+               break;
+
+         case C_GAS_SAFE:      case C_SPARE_SAFE:
+         case C_DRIVE_SAFE:    case C_RIGHT_WAY:
+               if (pp->battle == opposite(card)
+                   || (card == C_RIGHT_WAY && pp->speed == C_LIMIT)) {
+                       if (!(card == C_RIGHT_WAY && !isrepair(pp->battle))) {
+                               pp->battle = C_GO;
+                               pp->can_go = TRUE;
+                       }
+                       if (card == C_RIGHT_WAY && pp->speed == C_LIMIT)
+                               pp->speed = C_INIT;
+                       if (pp->new_battle
+                           || (pp->new_speed && card == C_RIGHT_WAY)) {
+                               pp->coups[card - S_CONV] = TRUE;
+                               pp->total += SC_COUP;
+                               pp->hand_tot += SC_COUP;
+                               pp->coupscore += SC_COUP;
+                       }
+               }
+               /*
+                * if not coup, must pick first
+                */
+               else if (pp->hand[0] == C_INIT && Topcard > Deck)
+                       goto mustpick;
+               pp->safety[card - S_CONV] = S_PLAYED;
+               pp->total += SC_SAFETY;
+               pp->hand_tot += SC_SAFETY;
+               if ((pp->safescore += SC_SAFETY) == NUM_SAFE * SC_SAFETY) {
+                       pp->total += SC_ALL_SAFE;
+                       pp->hand_tot += SC_ALL_SAFE;
+               }
+               if (card == C_RIGHT_WAY) {
+                       if (pp->speed == C_LIMIT)
+                               pp->speed = C_INIT;
+                       if (pp->battle == C_STOP || pp->battle == C_INIT) {
+                               pp->can_go = TRUE;
+                               pp->battle = C_INIT;
+                       }
+                       if (!pp->can_go && isrepair(pp->battle))
+                               pp->can_go = TRUE;
+               }
+               Next = -1;
+               break;
+
+         case C_INIT:
+               error("no card there");
+               Next = -1;
+               break;
+       }
+       if (pp == &Player[PLAYER])
+               account(card);
+       pp->hand[Card_no] = C_INIT;
+       Next = (Next == -1 ? FALSE : TRUE);
+       return TRUE;
+}
+
+getmove()
+{
+       reg char        c, *sp;
+       static char     moveprompt[] = ">>:Move:";
+#ifdef EXTRAP
+       static bool     last_ex = FALSE;        /* set if last command was E */
+
+       if (last_ex) {
+               undoex();
+               prboard();
+               last_ex = FALSE;
+       }
+#endif
+       for (;;) {
+               stand(MOVE_Y, MOVE_X, moveprompt);
+               clrtoeol();
+               move(MOVE_Y, MOVE_X + sizeof moveprompt);
+               leaveok(Board, FALSE);
+               refresh();
+               while ((c = getch()) == _tty.sg_kill || c == _tty.sg_erase)
+                       continue;
+               if (islower(c))
+                       c = toupper(c);
+               if (isprint(c) && !isspace(c)) {
+                       addch(c);
+                       refresh();
+               }
+               switch (c)
+               {
+                 case 'P':             /* Pick */
+                       Movetype = M_DRAW;
+                       goto ret;
+                 case 'U':             /* Use Card */
+                 case 'D':             /* Discard Card */
+                       if ((Card_no = getcard()) < 0)
+                               break;
+                       Movetype = (c == 'U' ? M_PLAY : M_DISCARD);
+                       goto ret;
+                 case 'O':             /* Order */
+                       Order = !Order;
+                       Movetype = M_ORDER;
+                       goto ret;
+                 case 'Q':             /* Quit */
+                       rub();          /* Same as a rubout */
+                       break;
+                 case 'W':             /* Window toggle */
+                       Window = nextwin(Window);
+                       newscore();
+                       prscore(TRUE);
+                       wrefresh(Score);
+                       break;
+                 case 'R':             /* Redraw screen */
+                 case CTRL('L'):
+                       clearok(curscr, TRUE);
+                       newboard();
+                       prboard();
+                       break;
+                 case 'S':             /* Save game */
+                       On_exit = FALSE;
+                       save();
+                       break;
+                 case 'E':             /* Extrapolate */
+#ifdef EXTRAP
+                       if (last_ex)
+                               break;
+                       Finished = TRUE;
+                       if (Window != W_FULL)
+                               newscore();
+                       prscore(FALSE);
+                       wrefresh(Score);
+                       last_ex = TRUE;
+                       Finished = FALSE;
+#else
+                       error("%c: command not implemented", c);
+#endif
+                       break;
+                 case '\r':            /* Ignore RETURNs and   */
+                 case '\n':            /* Line Feeds           */
+                 case ' ':             /* and Spaces           */
+                       break;
+                 case 'Z':             /* Debug code */
+                       if (geteuid() == ARNOLD) {
+                               if (!Debug && outf == NULL) {
+                                       char    buf[40];
+over:
+                                       mvaddstr(MOVE_Y, MOVE_X, "file: ");
+                                       clrtoeol();
+                                       leaveok(Board, FALSE);
+                                       refresh();
+                                       sp = buf;
+                                       while ((*sp = getch()) != '\n') {
+                                               if (*sp == _tty.sg_kill)
+                                                       goto over;
+                                               else if (*sp == _tty.sg_erase) {
+                                                       if (--sp < buf)
+                                                               sp = buf;
+                                                       else {
+                                                               addch('\b');
+                                                               if (*sp < ' ')
+                                                                   addch('\b');
+                                                               clrtoeol();
+                                                       }
+                                               }
+                                               else
+                                                       addstr(unctrl(*sp++));
+                                               refresh();
+                                       }
+                                       *sp = '\0';
+                                       leaveok(Board, TRUE);
+                                       if ((outf = fopen(buf, "w")) == NULL)
+                                               perror(buf);
+                                       setbuf(outf, 0);
+                               }
+                               Debug = !Debug;
+                               break;
+                       }
+                       /* FALLTHROUGH */
+                 default:
+                       error("unknown command: %s", unctrl(c));
+                       break;
+               }
+       }
+ret:
+       leaveok(Board, TRUE);
+}
+/*
+ * return whether or not the player has picked
+ */
+haspicked(pp)
+reg PLAY       *pp; {
+
+       reg int card;
+
+       if (Topcard <= Deck)
+               return TRUE;
+       switch (pp->hand[Card_no]) {
+         case C_GAS_SAFE:      case C_SPARE_SAFE:
+         case C_DRIVE_SAFE:    case C_RIGHT_WAY:
+               card = 1;
+               break;
+         default:
+               card = 0;
+               break;
+       }
+       return (pp->hand[card] != C_INIT);
+}
+
+account(card)
+reg CARD       card; {
+
+       reg CARD        oppos;
+
+       if (card == C_INIT)
+               return;
+       ++Numseen[card];
+       if (Play == COMP)
+               switch (card) {
+                 case C_GAS_SAFE:
+                 case C_SPARE_SAFE:
+                 case C_DRIVE_SAFE:
+                       oppos = opposite(card);
+                       Numgos += Numcards[oppos] - Numseen[oppos];
+                       break;
+                 case C_CRASH:
+                 case C_FLAT:
+                 case C_EMPTY:
+                 case C_STOP:
+                       Numgos++;
+                       break;
+               }
+}
+
+sort(hand)
+reg CARD       *hand;
+{
+       reg CARD        *cp, *tp;
+       reg int         j;
+       reg CARD        temp;
+
+       cp = hand;
+       hand += HAND_SZ;
+       for ( ; cp < &hand[-1]; cp++)
+               for (tp = cp + 1; tp < hand; tp++)
+                       if (*cp > *tp) {
+                               temp = *cp;
+                               *cp = *tp;
+                               *tp = temp;
+                       }
+}
diff --git a/usr/src/games/mille/print.c b/usr/src/games/mille/print.c
new file mode 100644 (file)
index 0000000..2d22054
--- /dev/null
@@ -0,0 +1,100 @@
+# include      "mille.h"
+
+# define       COMP_STRT       20
+# define       CARD_STRT       2
+
+prboard() {
+
+       reg PLAY        *pp;
+       reg int         i, j, k, temp;
+
+       for (k = 0; k < 2; k++) {
+               pp = &Player[k];
+               temp = k * COMP_STRT + CARD_STRT;
+               for (i = 0; i < NUM_SAFE; i++)
+                       if (pp->safety[i] == S_PLAYED) {
+                               mvaddstr(i, temp, C_name[i + S_CONV]);
+                               if (pp->coups[i])
+                                       mvaddch(i, temp - CARD_STRT, '*');
+                       }
+               mvprintw(14, temp, C_fmt, C_name[pp->battle]);
+               mvprintw(16, temp, C_fmt, C_name[pp->speed]);
+               for (i = C_25; i <= C_200; ) {
+                       reg char        *name;
+                       reg int         end;
+
+                       name = C_name[i];
+                       temp = k * 40;
+                       end = pp->nummiles[i++];
+                       for (j = 0; j < end; j++)
+                               mvwaddstr(Miles, i, (j << 2) + temp, name);
+               }
+       }
+       prscore(TRUE);
+       temp = CARD_STRT;
+       pp = &Player[PLAYER];
+       for (i = 0; i < HAND_SZ; i++)
+               mvprintw(i + 6, temp, C_fmt, C_name[pp->hand[i]]);
+       mvprintw(6, COMP_STRT + CARD_STRT, "%2d", Topcard - Deck);
+       mvprintw(8, COMP_STRT + CARD_STRT, C_fmt, C_name[Discard]);
+       if (End == 1000) {
+               static char     ext[] = "Extension";
+
+               stand(EXT_Y, EXT_X, ext);
+       }
+       wrefresh(Board);
+       wrefresh(Miles);
+       wrefresh(Score);
+}
+
+/*
+ *     Put str at (y,x) in standout mode
+ */
+stand(y, x, str)
+reg int                y, x;
+reg char       *str; {
+
+       standout();
+       mvaddstr(y, x, str);
+       standend();
+       return TRUE;
+}
+
+prscore(for_real)
+reg bool       for_real; {
+
+       reg PLAY        *pp;
+       reg int         x;
+       reg char        *Score_fmt = "%4d";
+
+       stdscr = Score;
+       for (pp = Player; pp < &Player[2]; pp++) {
+               x = (pp - Player) * 6 + 21;
+               mvprintw(1, x, Score_fmt, pp->mileage);
+               mvprintw(2, x, Score_fmt, pp->safescore);
+               if (pp->safescore == 400)
+                       mvaddstr(3, x + 1, "300");
+               else
+                       mvaddch(3, x + 3, '0');
+               mvprintw(4, x, Score_fmt, pp->coupscore);
+               if (Window == W_FULL || Finished) {
+#ifdef EXTRAP
+                       if (for_real)
+                               finalscore(pp);
+                       else
+                               extrapolate(pp);
+#else
+                       finalscore(pp);
+#endif
+                       mvprintw(11, x, Score_fmt, pp->hand_tot);
+                       mvprintw(13, x, Score_fmt, pp->total);
+                       mvprintw(14, x, Score_fmt, pp->games);
+               }
+               else {
+                       mvprintw(6, x, Score_fmt, pp->hand_tot);
+                       mvprintw(8, x, Score_fmt, pp->total);
+                       mvprintw(9, x, Score_fmt, pp->games);
+               }
+       }
+       stdscr = Board;
+}
diff --git a/usr/src/games/mille/roll.c b/usr/src/games/mille/roll.c
new file mode 100644 (file)
index 0000000..b1d72a2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *     This routine rolls ndie nside-sided dice.
+ */
+
+# define       reg     register
+
+# ifndef vax
+# define       MAXRAND 32767L
+
+roll(ndie, nsides)
+int    ndie, nsides; {
+
+       reg long        tot;
+       reg unsigned    n, r;
+
+       tot = 0;
+       n = ndie;
+       while (n--)
+               tot += rand();
+       return (int) ((tot * (long) nsides) / ((long) MAXRAND + 1)) + ndie;
+}
+
+# else
+
+roll(ndie, nsides)
+reg int        ndie, nsides; {
+
+       reg int         tot, r;
+       reg double      num_sides;
+
+       num_sides = nsides;
+       tot = 0;
+       while (ndie--)
+               tot += (r = rand()) * (num_sides / 017777777777) + 1;
+       return tot;
+}
+# endif
diff --git a/usr/src/games/mille/save.c b/usr/src/games/mille/save.c
new file mode 100644 (file)
index 0000000..6dea59a
--- /dev/null
@@ -0,0 +1,124 @@
+#include       "mille.h"
+#include       "unctrl.h"
+#include       <sys/types.h>
+#include       <sys/stat.h>
+#include       <time.h>
+
+typedef        struct stat     STAT;
+typedef        struct tm       TIME;
+
+char   *ctime();
+
+int    read(), write();
+
+/*
+ *     This routine saves the current game for use at a later date
+ */
+extern int     errno;
+extern char    *sys_errlist[];
+
+save() {
+
+       reg char        *sp;
+       reg int         outf;
+       reg TIME        *tp;
+       char            buf[80];
+       TIME            tme;
+       STAT            junk;
+
+       tp = &tme;
+       if (Fromfile && getyn("Same file? "))
+               strcpy(buf, Fromfile);
+       else {
+over:
+               mvaddstr(MOVE_Y, MOVE_X, "file: ");
+               clrtoeol();
+               leaveok(Board, FALSE);
+               refresh();
+               sp = buf;
+               while ((*sp = getch()) != '\n') {
+                       if (*sp == _tty.sg_kill)
+                               goto over;
+                       else if (*sp == _tty.sg_erase) {
+                               if (--sp < buf)
+                                       sp = buf;
+                               else {
+                                       addch('\b');
+                                       /*
+                                        * if the previous char was a control
+                                        * char, cover up two characters.
+                                        */
+                                       if (*sp < ' ')
+                                               addch('\b');
+                                       clrtoeol();
+                               }
+                       }
+                       else
+                               addstr(unctrl(*sp++));
+                       refresh();
+               }
+               *sp = '\0';
+               leaveok(Board, TRUE);
+       }
+
+       /*
+        * check for existing files, and confirm overwrite if needed
+        */
+
+       if (sp == buf || (!Fromfile && stat(buf, &junk) > -1
+           && getyn("Overwrite File? ") == FALSE))
+               return FALSE;
+
+       if ((outf = creat(buf, 0644)) < 0) {
+               error(sys_errlist[errno]);
+               return FALSE;
+       }
+       mvwaddstr(Score, ERR_Y, ERR_X, buf);
+       wrefresh(Score);
+       time(tp);                       /* get current time             */
+       strcpy(buf, ctime(tp));
+       for (sp = buf; *sp != '\n'; sp++)
+               continue;
+       *sp = '\0';
+       varpush(outf, write);
+       close(outf);
+       wprintw(Score, " [%s]", buf);
+       wclrtoeol(Score);
+       wrefresh(Score);
+       return TRUE;
+}
+
+/*
+ *     This does the actual restoring.  It returns TRUE if the
+ * backup was made on exiting, in which case certain things must
+ * be cleaned up before the game starts.
+ */
+rest_f(file)
+reg char       *file; {
+
+       reg char        *sp;
+       reg int         inf;
+       char            buf[80];
+       STAT            sbuf;
+
+       if ((inf = open(file, 0)) < 0) {
+               perror(file);
+               exit(1);
+       }
+       if (fstat(inf, &sbuf) < 0) {            /* get file stats       */
+               perror(file);
+               exit(1);
+       }
+       varpush(inf, read);
+       close(inf);
+       strcpy(buf, ctime(&sbuf.st_mtime));
+       for (sp = buf; *sp != '\n'; sp++)
+               continue;
+       *sp = '\0';
+       /*
+        * initialize some necessary values
+        */
+       sprintf(Initstr, "%s [%s]\n", file, buf);
+       Fromfile = file;
+       return !On_exit;
+}
diff --git a/usr/src/games/mille/table.c b/usr/src/games/mille/table.c
new file mode 100644 (file)
index 0000000..e206480
--- /dev/null
@@ -0,0 +1,15 @@
+# define       DEBUG
+# include      "mille.h"
+
+main() {
+
+       reg int i, j, count;
+
+       printf("   %16s -> %5s %5s %4s %s\n", "Card", "cards", "count", "need", "opposite");
+       for (i = 0; i < NUM_CARDS - 1; i++) {
+               for (j = 0, count = 0; j < DECK_SZ; j++)
+                       if (Deck[j] == i)
+                               count++;
+               printf("%2d %16s -> %5d %5d %4d %s\n", i, C_name[i], Numcards[i], count, Numneed[i], C_name[opposite(i)]);
+       }
+}
diff --git a/usr/src/games/mille/tags b/usr/src/games/mille/tags
new file mode 100644 (file)
index 0000000..0c7ed09
--- /dev/null
@@ -0,0 +1,135 @@
+CTRL   ../myex.h       ?^#define       CTRL(c) ('c' & 037)$?
+CTRL   move.c  ?^#define       CTRL(c)         (c - 'A' + 1)$?
+VOID   ../curses.h     ?^# define      VOID(x) (__void__ = (int) (x))$?
+_putchar       ../myput.c      ?^_putchar(c)$?
+_puts  ../curses.h     ?^# define      _puts(str)      if (str) { \$?
+_sprintw       ../printw.c     ?^_sprintw(win,fmt,args)$?
+_sscans        ../scanw.c      ?^_sscans(win,fmt,args)$?
+account        move.c  ?^account(card)$?
+addch  ../curses.h     ?^# define      addch(ch)       VOID(waddch(stdscr, ch))$?
+addstr ../curses.h     ?^# define      addstr(str)     VOID(waddstr(stdscr, str))$?
+box    ../box.c        ?^box(win,vert,hor)$?
+calcmove       comp.c  ?^calcmove() {$?
+canplay        comp.c  ?^canplay(pp, op, card)$?
+cgoto  ../cgoto.c      ?^cgoto()$?
+check_ext      misc.c  ?^check_ext(forcomp)$?
+check_go       move.c  ?^check_go() {$?
+check_more     misc.c  ?^check_more() {$?
+clear  ../curses.h     ?^# define      clear()         VOID(wclear(stdscr))$?
+clearok        ../curses.h     ?^#define       clearok(win,bf)  (win->_clear = bf)$?
+clrtobot       ../curses.h     ?^# define      clrtobot()      VOID(wclrtobot(stdscr))$?
+clrtoeol       ../curses.h     ?^# define      clrtoeol()      VOID(wclrtoeol(stdscr))$?
+crmode ../curses.h     ?^#define crmode() (_tty.sg_flags |= CBREAK, _rawmod?
+deleteln       ../curses.h     ?^# define      deleteln()      VOID(wdeleteln(stdscr))$?
+delwin ../delwin.c     ?^delwin(win)$?
+die    mille.c ?^die() {$?
+domove move.c  ?^domove()$?
+echo   ../curses.h     ?^#define echo()         (_tty.sg_flags |= ECHO, _echoit = ?
+endwin ../endwin.c     ?^endwin()$?
+erase  ../curses.h     ?^# define      erase()         VOID(werase(stdscr))$?
+error  misc.c  ?^error(str, arg)$?
+extrapolate    end.c   ?^extrapolate(pp)$?
+fgoto  ../myput.c      ?^fgoto()$?
+finalscore     end.c   ?^finalscore(pp)$?
+getcard        misc.c  ?^getcard()$?
+getch  ../curses.h     ?^# define      getch()         VOID(wgetch(stdscr))$?
+getmove        move.c  ?^getmove()$?
+getstr ../curses.h     ?^# define      getstr(str)     VOID(wgetstr(stdscr, str))$?
+gettmode       ../mytty.c      ?^gettmode() {$?
+getyn  misc.c  ?^getyn(prompt)$?
+getyx  ../curses.h     ?^#define       getyx(win,y,x)   y = win->_cury, x = win->_?
+haspicked      move.c  ?^haspicked(pp)$?
+inch   ../curses.h     ?^# define      inch()          VOID(winch(stdscr))$?
+init   init.c  ?^init() {$?
+initscr        ../initscr.c    ?^initscr() {$?
+insertln       ../curses.h     ?^# define      insertln()      VOID(winsertln(stdscr))$?
+isrepair       types.c ?^isrepair(card)$?
+issafety       mille.h ?^# define      issafety(x)     (x >= C_GAS_SAFE)$?
+leaveok        ../curses.h     ?^#define       leaveok(win,bf)  (win->_leave = bf)$?
+longname       ../longname.c   ?^longname(bp,def)$?
+main   mille.c ?^main(ac, av)$?
+makech ../refresh.c    ?^makech(win, wy)$?
+makenew        ../newwin.c     ?^makenew(num_lines, num_cols, by, bx)$?
+max    ../overlay.c    ?^# define      max(a,b)        (a < b ?
+min    ../overlay.c    ?^# define      min(a,b)        (a < b ?
+min    ../overwrite.c  ?^# define      min(a,b)        (a < b ?
+move   ../curses.h     ?^# define      move(y, x)      VOID(wmove(stdscr, y, x))$?
+mvaddch        ../curses.h     ?^#define       mvaddch(y,x,ch)         mvwaddch(stdscr,y,x,ch)$?
+mvaddstr       ../curses.h     ?^#define       mvaddstr(y,x,str)       mvwaddstr(stdscr,y,x,str?
+mvcur  ../myput.c      ?^mvcur(ly, lx, y, x)$?
+mvgetch        ../curses.h     ?^#define       mvgetch(y,x,ch)         mvwgetch(stdscr,y,x,ch)$?
+mvgetstr       ../curses.h     ?^#define       mvgetstr(y,x,str)       mvwgetstr(stdscr,y,x,str?
+mvinch ../curses.h     ?^#define       mvinch(y,x)             mvwinch(win,y,x)$?
+mvprintw       ../mvprintw.c   ?^mvprintw(y,x,fmt,args)$?
+mvscanw        ../mvscanw.c    ?^mvscanw(y,x,fmt,args)$?
+mvwaddch       ../curses.h     ?^#define       mvwaddch(win,y,x,ch)    VOID(wmove(win,y,x)==?
+mvwaddstr      ../curses.h     ?^#define       mvwaddstr(win,y,x,str)  VOID(wmove(win,y,x)?
+mvwgetch       ../curses.h     ?^#define       mvwgetch(win,y,x,ch)    VOID(wmove(win,y,x)==?
+mvwgetstr      ../curses.h     ?^#define       mvwgetstr(win,y,x,str)  VOID(wmove(win,y,x)?
+mvwinch        ../curses.h     ?^#define       mvwinch(win,y,x)        VOID(wmove(win,y,x) == ER?
+mvwprintw      ../mvprintw.c   ?^mvwprintw(win,y,x,fmt,args)$?
+mvwscanw       ../mvscanw.c    ?^mvwscanw(win,y,x,fmt,args)$?
+newboard       init.c  ?^newboard() {$?
+newscore       init.c  ?^newscore() {$?
+newwin ../newwin.c     ?^newwin(num_lines, num_cols, by, bx)$?
+nextplay       mille.h ?^# define      nextplay()      (Play = other(Play))$?
+nextwin        mille.h ?^# define      nextwin(x)      (1 - x)$?
+nl     ../curses.h     ?^#define nl()   (_tty.sg_flags |= CRMOD, NONL = TRUE?
+nocrmode       ../curses.h     ?^#define nocrmode() (_tty.sg_flags &= ~CBREAK,_rawm?
+noecho ../curses.h     ?^#define noecho() (_tty.sg_flags &= ~ECHO, _echoit ?
+nonl   ../curses.h     ?^#define nonl()         (_tty.sg_flags &= ~CRMOD, NONL = F?
+noraw  ../curses.h     ?^#define noraw()        (_tty.sg_flags &= ~RAW, _rawmode ?
+normal ../curses.h     ?^# define      normal()        VOID(wnormal(stdscr))$?
+onecard        comp.c  ?^onecard(pp)$?
+opposite       mille.h ?^# define      opposite(x)     (Opposite[x])$?
+other  mille.h ?^# define      other(x)        (1 - x)$?
+overlay        ../overlay.c    ?^overlay(win1, win2)$?
+overwrite      ../overwrite.c  ?^overwrite(win1, win2)$?
+playcard       move.c  ?^playcard(pp)$?
+plod   ../myput.c      ?^plod(cnt)$?
+plodput        ../myput.c      ?^plodput(c)$?
+prboard        print.c ?^prboard() {$?
+printw ../printw.c     ?^printw(fmt,args)$?
+prscore        print.c ?^prscore(for_real)$?
+putpad ../myput.c      ?^putpad(cp)$?
+raw    ../curses.h     ?^#define raw()  (_tty.sg_flags |= RAW, _rawmode = T?
+refresh        ../curses.h     ?^# define      refresh()       VOID(wrefresh(stdscr))$?
+resetty        ../curses.h     ?^#define       resetty()       (_tty.sg_flags = _res_flg, stty(?
+rest_f save.c  ?^rest_f(file)$?
+roll   roll.c  ?^roll(ndie, nsides)$?
+rub    mille.c ?^rub() {$?
+safety types.c ?^safety(card)$?
+save   save.c  ?^save() {$?
+savetty        ../curses.h     ?^#define       savetty()       (gtty(_tty_ch, &_tty), _res_flg ?
+scanw  ../scanw.c      ?^scanw(fmt,args)$?
+scroll ../scroll.c     ?^scroll(win)$?
+scrollok       ../curses.h     ?^#define       scrollok(win,bf) (win->_scroll = bf)$?
+setterm        ../mytty.c      ?^setterm(type)$?
+shuffle        init.c  ?^shuffle() {$?
+sort   move.c  ?^sort(hand)$?
+stand  print.c ?^stand(y, x, str)$?
+standout       ../curses.h     ?^# define      standout()      VOID(wstandout(stdscr))$?
+subwin ../newwin.c     ?^subwin(orig, num_lines, num_cols, by, bx)$?
+touchwin       ../touchwin.c   ?^touchwin(win)$?
+tstp   mille.c ?^tstp() {$?
+unctrl ../unctrl.h     ?^# define      unctrl(ch)      (_unctrl(ch, " ", "^ "))$?
+undoex end.c   ?^undoex() {$?
+varpush        varpush.c       ?^varpush(file, func)$?
+waddch ../addch.c      ?^waddch(win, c)$?
+waddstr        ../addstr.c     ?^waddstr(win,str)$?
+wclear ../clear.c      ?^wclear(win)$?
+wclrtobot      ../clrtobot.c   ?^wclrtobot(win)$?
+wclrtoeol      ../clrtoeol.c   ?^wclrtoeol(win)$?
+wdeleteln      ../deleteln.c   ?^wdeleteln(win)$?
+werase ../erase.c      ?^werase(win)$?
+wgetch ../getch.c      ?^wgetch(win)$?
+wgetstr        ../getstr.c     ?^wgetstr(win,str)$?
+winch  ../curses.h     ?^#define       winch(win)       (win->_y[win->_cury][win->_cur?
+winsertln      ../insertln.c   ?^winsertln(win)$?
+wmove  ../move.c       ?^wmove(win,y,x)$?
+wnormal        ../standout.c   ?^wnormal(win)$?
+wprintw        ../printw.c     ?^wprintw(win,fmt,args)$?
+wrefresh       ../refresh.c    ?^wrefresh(win)$?
+wscanw ../scanw.c      ?^wscanw(win,fmt,args)$?
+wstandout      ../standout.c   ?^wstandout(win)$?
+zap    ../mytty.c      ?^zap() {$?
diff --git a/usr/src/games/mille/types.c b/usr/src/games/mille/types.c
new file mode 100644 (file)
index 0000000..7df9589
--- /dev/null
@@ -0,0 +1,33 @@
+# include      "mille.h"
+
+isrepair(card)
+reg CARD       card; {
+
+       return card == C_GAS || card == C_SPARE || card == C_REPAIRS || card == C_INIT;
+}
+
+safety(card)
+reg CARD       card; {
+
+       switch (card) {
+         case C_EMPTY:
+         case C_GAS:
+         case C_GAS_SAFE:
+               return C_GAS_SAFE;
+         case C_FLAT:
+         case C_SPARE:
+         case C_SPARE_SAFE:
+               return C_SPARE_SAFE;
+         case C_CRASH:
+         case C_REPAIRS:
+         case C_DRIVE_SAFE:
+               return C_DRIVE_SAFE;
+         case C_GO:
+         case C_STOP:
+         case C_RIGHT_WAY:
+         case C_LIMIT:
+         case C_END_LIMIT:
+               return C_RIGHT_WAY;
+       }
+       /* NOTREACHED */
+}
diff --git a/usr/src/games/mille/unctrl.h b/usr/src/games/mille/unctrl.h
new file mode 100644 (file)
index 0000000..9abaf95
--- /dev/null
@@ -0,0 +1,4 @@
+# include      <stdio.h>
+# define       unctrl(ch)      (_unctrl[ch])
+
+extern char    *_unctrl[];
diff --git a/usr/src/games/mille/varpush.c b/usr/src/games/mille/varpush.c
new file mode 100644 (file)
index 0000000..238589b
--- /dev/null
@@ -0,0 +1,48 @@
+# include      "mille.h"
+
+int    read(), write();
+
+/*
+ *     push variables around via the routine func() on the file
+ * channel file.  func() is either read or write.
+ */
+varpush(file, func)
+reg int        file;
+reg int        (*func)(); {
+
+       int     temp;
+
+       (*func)(file, &Debug, sizeof Debug);
+       (*func)(file, &Finished, sizeof Finished);
+       (*func)(file, &Order, sizeof Order);
+       (*func)(file, &End, sizeof End);
+       (*func)(file, &On_exit, sizeof On_exit);
+       (*func)(file, &Handstart, sizeof Handstart);
+       (*func)(file, &Numgos, sizeof Numgos);
+       (*func)(file,  Numseen, sizeof Numseen);
+       (*func)(file, &Play, sizeof Play);
+       (*func)(file, &Window, sizeof Window);
+       (*func)(file,  Deck, sizeof Deck);
+       (*func)(file, &Discard, sizeof Discard);
+       (*func)(file,  Player, sizeof Player);
+       if (func == read) {
+               read(file, &temp, sizeof temp);
+               Topcard = &Deck[temp];
+               if (Debug) {
+                       char    buf[80];
+over:
+                       printf("Debug file:");
+                       gets(buf);
+                       if ((outf = fopen(buf, "w")) == NULL) {
+                               perror(buf);
+                               goto over;
+                       }
+                       if (strcmp(buf, "/dev/null") != 0)
+                               setbuf(outf, 0);
+               }
+       }
+       else {
+               temp = Topcard - Deck;
+               write(file, &temp, sizeof temp);
+       }
+}