: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH echo 'Making directory "=test"' mkdir =test echo 'Making directory "=test/=mille"' mkdir =test/=mille echo 'x - =test/=mille/Makefile' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/Makefile HEADERS=mille.h CFILES= comp.c end.c extern.c init.c mille.c misc.c move.c print.c \ roll.c save.c types.c varpush.c OBJS= comp.o end.o extern.o init.o mille.o misc.o move.o print.o \ roll.o save.o types.o varpush.o POBJS= comp.po end.po extern.po init.po mille.po misc.po move.po \ roll.po print.po save.po types.po varpush.po LIBS= ../../=src/libpcurses.a CFLAGS= -O -DSTANDOUT -I../../=src X.SUFFIXES: .po .i X.c.po: rm -f x.c ; ln $*.c x.c ${CC} ${CFLAGS} -pg -c x.c mv x.o $*.po X.c.i: ${CC} ${CFLAGS} -P $*.c mille: ${OBJS} ${CC} ${CFLAGS} -n -o mille ${OBJS} ${LIBS} install: mille cp mille /usr/games pmb: ${POBJS} ${CC} ${CFLAGS} -n -pg -o pmb ${POBJS} $(LIBS) mille.po: mille.c rm -f x.c ; ln mille.c x.c ${CC} ${CFLAGS} -DPROF -p -c x.c mv x.o mille.po table: table.o extern.o ${CC} ${CFLAGS} -i -o table table.o extern.o readdump: readdump.o extern.o varpush.o ${CC} ${CFLAGS} -i -o readdump readdump.o extern.o varpush.o ctags: ctags ${HEADERS} ${CFILES} ed - tags < :ctfix sort tags -o tags lint: lint -hxb ${CFILES} > lint.out mille.ar: ar ruv mille.ar Makefile tags ${HEADERS} ${CFILES} tar: tar crvf mille.tar Makefile tags :ctfix ${HEADERS} ${CFILES} lpr: pr Makefile ${HEADERS} ${CFILES} tags | lpr ; lpq //go.sysin dd * echo 'x - =test/=mille/comp.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/comp.c # 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; } //go.sysin dd * echo 'x - =test/=mille/end.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/end.c # include "mille.h" X/* * 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 */ X/* * 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 //go.sysin dd * echo 'x - =test/=mille/extern.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/extern.c # 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 }; XFILE *outf; PLAY Player[2]; /* Player descriptions */ WINDOW *Board, /* Playing field screen */ *Miles, /* Mileage screen */ *Score; /* Score screen */ //go.sysin dd * echo 'x - =test/=mille/init.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/init.c # 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; } //go.sysin dd * echo 'x - =test/=mille/mille.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/mille.c # include "mille.h" # include # include int rub(); 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 (! cursor_address) { 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(); nonl(); signal(SIGINT, rub); 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); } } X/* * Routine to trap rubouts, and make sure they really want to * quit. */ rub() { signal(SIGINT, 1); if (getyn("Really? ")) die(); signal(SIGINT, rub); } X/* * Time to go beddy-by */ die() { signal(SIGINT, 1); if (outf) fflush(outf); mvcur(0, COLS - 1, LINES - 1, 0); endwin(); exit(1); } //go.sysin dd * echo 'x - =test/=mille/mille.h' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/mille.h # include # include X/* * Miscellaneous constants */ # define unsgn unsigned # define reg register # define CARD short # ifdef vax # define ARNOLD 78 /* my uid */ # else # define ARNOLD 24601 /* my uid */ # endif # define GURP 28672 /* bad uid */ # define MAXUSERS 35 /* max # of users for startup */ # define HAND_SZ 7 /* number of cards in a hand */ # define DECK_SZ 101 /* number of cards in decks */ # define NUM_SAFE 4 /* number of saftey cards */ # define NUM_MILES 5 /* number of milestones types */ # define NUM_CARDS 20 /* number of types of cards */ # define BOARD_Y 17 /* size of board screen */ # define BOARD_X 40 # define MILES_Y 7 /* size of mileage screen */ # define MILES_X 80 # define SCORE_Y 17 /* size of score screen */ # define SCORE_X 40 # define MOVE_Y 10 /* Where to print move prompt */ # define MOVE_X 20 # define ERR_Y 15 /* Where to print errors */ # define ERR_X 5 # define EXT_Y 4 /* Where to put Extension */ # define EXT_X 9 # define PLAYER 0 # define COMP 1 # define W_SMALL 0 /* Small (initial) window */ # define W_FULL 1 /* Full (final) window */ X/* * Move types */ # define M_DISCARD 0 # define M_DRAW 1 # define M_PLAY 2 # define M_ORDER 3 X/* * Scores */ # define SC_SAFETY 100 # define SC_ALL_SAFE 300 # define SC_COUP 300 # define SC_TRIP 400 # define SC_SAFE 300 # define SC_DELAY 300 # define SC_EXTENSION 200 # define SC_SHUT_OUT 500 X/* * safety descriptions */ # define S_UNKNOWN 0 /* location of safety unknown */ # define S_IN_HAND 1 /* safety in player's hand */ # define S_PLAYED 2 /* safety has been played */ # define S_GAS_SAFE 0 /* Gas safety card index */ # define S_SPARE_SAFE 1 /* Tire safety card index */ # define S_DRIVE_SAFE 2 /* Driveing safety card index */ # define S_RIGHT_WAY 3 /* Right-of-Way card index */ # define S_CONV 15 /* conversion from C_ to S_ */ X/* * card numbers */ # define C_INIT -1 # define C_25 0 # define C_50 1 # define C_75 2 # define C_100 3 # define C_200 4 # define C_EMPTY 5 # define C_FLAT 6 # define C_CRASH 7 # define C_STOP 8 # define C_LIMIT 9 # define C_GAS 10 # define C_SPARE 11 # define C_REPAIRS 12 # define C_GO 13 # define C_END_LIMIT 14 # define C_GAS_SAFE 15 # define C_SPARE_SAFE 16 # define C_DRIVE_SAFE 17 # define C_RIGHT_WAY 18 typedef struct { bool coups[NUM_SAFE]; bool can_go; bool new_battle; bool new_speed; short safety[NUM_SAFE]; short nummiles[NUM_MILES]; CARD hand[HAND_SZ]; CARD battle; CARD speed; int mileage; int hand_tot; int safescore; int coupscore; int total; int games; } PLAY; X/* * macros */ # define other(x) (1 - x) # define nextplay() (Play = other(Play)) # define nextwin(x) (1 - x) # define opposite(x) (Opposite[x]) # define issafety(x) (x >= C_GAS_SAFE) X/* * externals */ extern bool Debug, Finished, Next, On_exit, Order, Saved; extern char *C_fmt, **C_name, *Fromfile, Initstr[]; extern int Card_no, End, Handstart, Movetype, Numcards[], Numgos, Numneed[], Numseen[NUM_CARDS], Play, Value[], Window; extern CARD Deck[DECK_SZ], Discard, Opposite[NUM_CARDS], *Topcard; extern FILE *outf; extern PLAY Player[2]; extern WINDOW *Board, *Miles, *Score; X/* * functions */ CARD getcard(); //go.sysin dd * echo 'x - =test/=mille/misc.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/misc.c #include "mille.h" #include "unctrl.h" #define NUMSAFE 4 X/* VARARGS1 */ error(str, arg) char *str; { stdscr = Score; mvprintw(ERR_Y, ERR_X, str, arg); clrtoeol(); putchar(''); refresh(); stdscr = Board; return FALSE; } CARD getcard() { reg char c, c1; for (;;) { while ((c = getch()) == '\n' || c == '\r' || c == ' ') continue; if (islower(c)) c = toupper(c); if (c == killchar() || c == erasechar()) return -1; addstr(unctrl(c)); clrtoeol(); switch (c) { case '1': case '2': case '3': case '4': case '5': case '6': c -= '0'; break; case '0': case 'P': case 'p': c = 0; break; default: putchar(''); addch('\b'); if (!isprint(c)) addch('\b'); c = -1; break; } refresh(); if (c >= 0) { while ((c1=getch()) != '\r' && c1 != '\n' && c1 != ' ') if (c1 == killchar()) return -1; else if (c1 == erasechar()) { addch('\b'); clrtoeol(); refresh(); goto cont; } else write(0, "", 1); return c; } cont: ; } } check_ext(forcomp) reg bool forcomp; { if (End == 700) if (Play == PLAYER) { if (getyn("Extension? ")) { extend: if (!forcomp) End = 1000; return TRUE; } else { done: if (!forcomp) Finished = TRUE; return FALSE; } } else { reg PLAY *pp, *op; reg int i, safe, miles; pp = &Player[COMP]; op = &Player[PLAYER]; for (safe = 0, i = 0; i < NUMSAFE; i++) if (pp->safety[i] != S_UNKNOWN) safe++; if (safe < 2) goto done; if (op->mileage == 0 || onecard(op) || (op->can_go && op->mileage >= 500)) goto done; for (miles = 0, i = 0; i < NUMSAFE; i++) if (op->safety[i] != S_PLAYED && pp->safety[i] == S_UNKNOWN) miles++; if (miles + safe == NUMSAFE) goto extend; for (miles = 0, i = 0; i < HAND_SZ; i++) if ((safe = pp->hand[i]) <= C_200) miles += Value[safe]; if (miles + (Topcard - Deck) * 3 > 1000) goto extend; goto done; } else goto done; } X/* * Get a yes or no answer to the given question. Saves are * also allowed. Return TRUE if the answer was yes, FALSE if no. */ getyn(prompt) reg char *prompt; { reg char c; Saved = FALSE; for (;;) { leaveok(Board, FALSE); mvaddstr(MOVE_Y, MOVE_X, prompt); clrtoeol(); refresh(); switch (c = getch()) { case 'n': case 'N': addch('N'); refresh(); leaveok(Board, TRUE); return FALSE; case 'y': case 'Y': addch('Y'); refresh(); leaveok(Board, TRUE); return TRUE; case 's': case 'S': addch('S'); refresh(); Saved = save(); continue; default: addstr(unctrl(c)); refresh(); putchar(''); break; } } } X/* * Check to see if more games are desired. If not, and game * came from a saved file, make sure that they don't want to restore * it. Exit appropriately. */ check_more() { raw(); /* Flush input */ noraw(); On_exit = TRUE; if (Player[PLAYER].total >= 5000 || Player[COMP].total >= 5000) if (getyn("Another game? ")) return; else { /* * must do accounting normally done in main() */ if (Player[PLAYER].total > Player[COMP].total) Player[PLAYER].games++; else if (Player[PLAYER].total < Player[COMP].total) Player[COMP].games++; Player[COMP].total = 0; Player[PLAYER].total = 0; } else if (getyn("Another hand? ")) return; if (!Saved && getyn("Save game? ")) if (!save()) return; die(); } //go.sysin dd * echo 'x - =test/=mille/move.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/move.c #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(); } X/* * 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()) == killchar() || c == erasechar()) 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 == killchar()) goto over; else if (*sp == erasechar()) { 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); } X/* * 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; } } //go.sysin dd * echo 'x - =test/=mille/print.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/print.c # 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); } X/* * 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; } //go.sysin dd * echo 'x - =test/=mille/roll.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/roll.c X/* * 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 //go.sysin dd * echo 'x - =test/=mille/save.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/save.c #include "mille.h" #include "unctrl.h" #include #include #include typedef struct stat STAT; typedef struct tm TIME; char *ctime(); int read(), write(); X/* * 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(); #ifdef UNDEFINED sp = buf; while ((*sp = getch()) != '\n') { if (*sp == killchar()) goto over; else if (*sp == erasechar()) { 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'; #else getstr(buf); #endif 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; } X/* * 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; } //go.sysin dd * echo 'x - =test/=mille/table.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/table.c # 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)]); } } //go.sysin dd * echo 'x - =test/=mille/types.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/types.c # 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 */ } //go.sysin dd * echo 'x - =test/=mille/unctrl.h' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/unctrl.h # include # define unctrl(ch) (_unctrl[ch]) extern char *_unctrl[]; //go.sysin dd * echo 'x - =test/=mille/varpush.c' sed 's/^X//' <<'//go.sysin dd *' >=test/=mille/varpush.c # include "mille.h" int read(), write(); X/* * 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); } } //go.sysin dd * exit