diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /games/canfield |
initial import of NetBSD tree
Diffstat (limited to 'games/canfield')
-rw-r--r-- | games/canfield/Makefile | 6 | ||||
-rw-r--r-- | games/canfield/canfield/Makefile | 12 | ||||
-rw-r--r-- | games/canfield/canfield/canfield.6 | 131 | ||||
-rw-r--r-- | games/canfield/canfield/canfield.c | 1716 | ||||
-rw-r--r-- | games/canfield/canfield/pathnames.h | 39 | ||||
-rw-r--r-- | games/canfield/cfscores/Makefile | 10 | ||||
-rw-r--r-- | games/canfield/cfscores/cfscores.c | 154 |
7 files changed, 2068 insertions, 0 deletions
diff --git a/games/canfield/Makefile b/games/canfield/Makefile new file mode 100644 index 00000000000..c656887f7ee --- /dev/null +++ b/games/canfield/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.3 1995/03/21 15:08:26 cgd Exp $ +# @(#)Makefile 8.1 (Berkeley) 5/31/93 + +SUBDIR= canfield cfscores + +.include <bsd.subdir.mk> diff --git a/games/canfield/canfield/Makefile b/games/canfield/canfield/Makefile new file mode 100644 index 00000000000..5877216910a --- /dev/null +++ b/games/canfield/canfield/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.5 1995/03/21 15:08:28 cgd Exp $ +# @(#)Makefile 8.1 (Berkeley) 5/31/93 + +PROG= canfield +MAN= canfield.6 +DPADD= ${LIBCURSES} ${LIBTERM} +LDADD= -lcurses -ltermcap +HIDEGAME=hidegame + + +.include "../../Makefile.inc" +.include <bsd.prog.mk> diff --git a/games/canfield/canfield/canfield.6 b/games/canfield/canfield/canfield.6 new file mode 100644 index 00000000000..17b34ae38dd --- /dev/null +++ b/games/canfield/canfield/canfield.6 @@ -0,0 +1,131 @@ +.\" $NetBSD: canfield.6,v 1.4 1995/03/21 15:08:30 cgd Exp $ +.\" +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)canfield.6 8.1 (Berkeley) 5/31/93 +.\" +.Dd May 31, 1993 +.Dt CANFIELD 6 +.Os +.Sh NAME +.Nm canfield , +.Nm cfscores +.Nd the solitaire card game canfield +.Sh SYNOPSIS +.Nm canfield +.Nm cfscores +.Op Fl a +.Op Ar user +.Sh DESCRIPTION +If you have never played solitaire before, it is recommended +that you consult a solitaire instruction book. In +Canfield, tableau cards may be built on each other downward +in alternate colors. An entire pile must be moved as a unit +in building. Top cards of the piles are available +to be played on foundations, but never into empty spaces. +.Pp +Spaces must be filled from the stock. The top card of +the stock also is available to be played on foundations or +built on tableau piles. After the stock is exhausted, +tableau spaces may be filled from the talon and the player may +keep them open until he wishes to use them. +.Pp +Cards are dealt from the hand to the talon by threes +and this repeats until there are no more cards in the hand +or the player quits. To have cards dealt onto the talon the +player types +.Sq Ic ht +for his move. Foundation base cards are +also automatically moved to the foundation when they become +available. +.Pp +The command +.Sq Ic c +causes +.Nm canfield +to maintain card counting statistics +on the bottom of the screen. +When properly used this can greatly increase one's chances of +winning. +.Pp +The rules for betting are somewhat less strict than +those used in the official version of the game. +The initial deal costs $13. +You may quit at this point or inspect the game. +Inspection costs $13 and allows you to make as many +moves as possible without moving any cards from your hand +to the talon. +(The initial deal places three cards on the talon; +if all these cards are used, +three more are made available.) +Finally, if the game seems interesting, +you must pay the final installment of $26. +At this point you are +credited at the rate of $5 for each card on the foundation; +as the game progresses you are credited with $5 for each +card that is moved to the foundation. +Each run through the hand after the first costs $5. +The card counting feature +costs $1 for each unknown card that is identified. +If the information is toggled on, +you are only charged for cards +that became visible since it was last turned on. +Thus the maximum cost of information is $34. +Playing time is charged at a rate of $1 per minute. +.Pp +With no arguments, the program +.Nm cfscores +prints out the current status of your canfield account. +If a +.Ar user +name is specified, +it prints out the status of their canfield account. +If the +.Fl a +flag is specified, +it prints out the canfield accounts for all users that have +played the game since the database was set up. +.Sh FILES +.Bl -tag -width /usr/games/canfield -compact +.It Pa /usr/games/canfield +the game itself +.It Pa /usr/games/cfscores +the database printer +.It Pa /var/games/cfscores +the database of scores +.Sh BUGS +It is impossible to cheat. +.Sh AUTHORS +Originally written: Steve Levine. +.Pp +Further random hacking by: Steve Feldman, Kirk McKusick, +Mikey Olson, and Eric Allman. diff --git a/games/canfield/canfield/canfield.c b/games/canfield/canfield/canfield.c new file mode 100644 index 00000000000..406b698dbc9 --- /dev/null +++ b/games/canfield/canfield/canfield.c @@ -0,0 +1,1716 @@ +/* $NetBSD: canfield.c,v 1.7 1995/05/13 07:28:35 jtc Exp $ */ + +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)canfield.c 8.1 (Berkeley) 5/31/93"; +#else +static char rcsid[] = "$NetBSD: canfield.c,v 1.7 1995/05/13 07:28:35 jtc Exp $"; +#endif +#endif /* not lint */ + +/* + * The canfield program + * + * Authors: + * Originally written: Steve Levine + * Converted to use curses and debugged: Steve Feldman + * Card counting: Kirk McKusick and Mikey Olson + * User interface cleanups: Eric Allman and Kirk McKusick + * Betting by Kirk McKusick + */ + +#include <sys/types.h> + +#include <curses.h> +#include <termios.h> +#include <ctype.h> +#include <signal.h> +#include <string.h> +#include <termios.h> + +#include "pathnames.h" + +#define decksize 52 +#define originrow 0 +#define origincol 0 +#define basecol 1 +#define boxcol 42 +#define tboxrow 2 +#define bboxrow 17 +#define movecol 43 +#define moverow 16 +#define msgcol 43 +#define msgrow 15 +#define titlecol 30 +#define titlerow 0 +#define sidecol 1 +#define ottlrow 6 +#define foundcol 11 +#define foundrow 3 +#define stockcol 2 +#define stockrow 8 +#define fttlcol 10 +#define fttlrow 1 +#define taloncol 2 +#define talonrow 13 +#define tabrow 8 +#define ctoprow 21 +#define cbotrow 23 +#define cinitcol 14 +#define cheightcol 1 +#define cwidthcol 4 +#define handstatrow 21 +#define handstatcol 7 +#define talonstatrow 22 +#define talonstatcol 7 +#define stockstatrow 23 +#define stockstatcol 7 +#define Ace 1 +#define Jack 11 +#define Queen 12 +#define King 13 +#define atabcol 11 +#define btabcol 18 +#define ctabcol 25 +#define dtabcol 32 + +#define spades 's' +#define clubs 'c' +#define hearts 'h' +#define diamonds 'd' +#define black 'b' +#define red 'r' + +#define stk 1 +#define tal 2 +#define tab 3 +#define INCRHAND(row, col) {\ + row -= cheightcol;\ + if (row < ctoprow) {\ + row = cbotrow;\ + col += cwidthcol;\ + }\ +} +#define DECRHAND(row, col) {\ + row += cheightcol;\ + if (row > cbotrow) {\ + row = ctoprow;\ + col -= cwidthcol;\ + }\ +} + + +struct cardtype { + char suit; + char color; + bool visible; + bool paid; + int rank; + struct cardtype *next; +}; + +#define NIL ((struct cardtype *) -1) + +struct cardtype *deck[decksize]; +struct cardtype cards[decksize]; +struct cardtype *bottom[4], *found[4], *tableau[4]; +struct cardtype *talon, *hand, *stock, *basecard; +int length[4]; +int cardsoff, base, cinhand, taloncnt, stockcnt, timesthru; +char suitmap[4] = {spades, clubs, hearts, diamonds}; +char colormap[4] = {black, black, red, red}; +char pilemap[4] = {atabcol, btabcol, ctabcol, dtabcol}; +char srcpile, destpile; +int mtforigin, tempbase; +int coldcol, cnewcol, coldrow, cnewrow; +bool errmsg, done; +bool mtfdone, Cflag = FALSE; +#define INSTRUCTIONBOX 1 +#define BETTINGBOX 2 +#define NOBOX 3 +int status = INSTRUCTIONBOX; +int uid; + +/* + * Basic betting costs + */ +#define costofhand 13 +#define costofinspection 13 +#define costofgame 26 +#define costofrunthroughhand 5 +#define costofinformation 1 +#define secondsperdollar 60 +#define maxtimecharge 3 +#define valuepercardup 5 +/* + * Variables associated with betting + */ +struct betinfo { + long hand; /* cost of dealing hand */ + long inspection; /* cost of inspecting hand */ + long game; /* cost of buying game */ + long runs; /* cost of running through hands */ + long information; /* cost of information */ + long thinktime; /* cost of thinking time */ + long wins; /* total winnings */ + long worth; /* net worth after costs */ +}; +struct betinfo this, game, total; +bool startedgame = FALSE, infullgame = FALSE; +time_t acctstart; +int dbfd = -1; + +/* + * The following procedures print the board onto the screen using the + * addressible cursor. The end of these procedures will also be + * separated from the rest of the program. + * + * procedure to set the move command box + */ +movebox() +{ + switch (status) { + case BETTINGBOX: + printtopbettingbox(); + break; + case NOBOX: + clearabovemovebox(); + break; + case INSTRUCTIONBOX: + printtopinstructions(); + break; + } + move(moverow, boxcol); + printw("| |"); + move(msgrow, boxcol); + printw("| |"); + switch (status) { + case BETTINGBOX: + printbottombettingbox(); + break; + case NOBOX: + clearbelowmovebox(); + break; + case INSTRUCTIONBOX: + printbottominstructions(); + break; + } + refresh(); +} + +/* + * print directions above move box + */ +printtopinstructions() +{ + move(tboxrow, boxcol); + printw("*----------------------------------*"); + move(tboxrow + 1, boxcol); + printw("| MOVES |"); + move(tboxrow + 2, boxcol); + printw("|s# = stock to tableau |"); + move(tboxrow + 3, boxcol); + printw("|sf = stock to foundation |"); + move(tboxrow + 4, boxcol); + printw("|t# = talon to tableau |"); + move(tboxrow + 5, boxcol); + printw("|tf = talon to foundation |"); + move(tboxrow + 6, boxcol); + printw("|## = tableau to tableau |"); + move(tboxrow + 7, boxcol); + printw("|#f = tableau to foundation |"); + move(tboxrow + 8, boxcol); + printw("|ht = hand to talon |"); + move(tboxrow + 9, boxcol); + printw("|c = toggle card counting |"); + move(tboxrow + 10, boxcol); + printw("|b = present betting information |"); + move(tboxrow + 11, boxcol); + printw("|q = quit to end the game |"); + move(tboxrow + 12, boxcol); + printw("|==================================|"); +} + +/* + * Print the betting box. + */ +printtopbettingbox() +{ + + move(tboxrow, boxcol); + printw("*----------------------------------*"); + move(tboxrow + 1, boxcol); + printw("|Costs Hand Game Total |"); + move(tboxrow + 2, boxcol); + printw("| Hands |"); + move(tboxrow + 3, boxcol); + printw("| Inspections |"); + move(tboxrow + 4, boxcol); + printw("| Games |"); + move(tboxrow + 5, boxcol); + printw("| Runs |"); + move(tboxrow + 6, boxcol); + printw("| Information |"); + move(tboxrow + 7, boxcol); + printw("| Think time |"); + move(tboxrow + 8, boxcol); + printw("|Total Costs |"); + move(tboxrow + 9, boxcol); + printw("|Winnings |"); + move(tboxrow + 10, boxcol); + printw("|Net Worth |"); + move(tboxrow + 11, boxcol); + printw("|Return |"); + move(tboxrow + 12, boxcol); + printw("|==================================|"); +} + +/* + * clear info above move box + */ +clearabovemovebox() +{ + int i; + + for (i = 0; i <= 11; i++) { + move(tboxrow + i, boxcol); + printw(" "); + } + move(tboxrow + 12, boxcol); + printw("*----------------------------------*"); +} + +/* + * print instructions below move box + */ +printbottominstructions() +{ + move(bboxrow, boxcol); + printw("|Replace # with the number of the |"); + move(bboxrow + 1, boxcol); + printw("|tableau you want. |"); + move(bboxrow + 2, boxcol); + printw("*----------------------------------*"); +} + +/* + * print betting information below move box + */ +printbottombettingbox() +{ + move(bboxrow, boxcol); + printw("|x = toggle information box |"); + move(bboxrow + 1, boxcol); + printw("|i = list playing instructions |"); + move(bboxrow + 2, boxcol); + printw("*----------------------------------*"); +} + +/* + * clear info below move box + */ +clearbelowmovebox() +{ + int i; + + move(bboxrow, boxcol); + printw("*----------------------------------*"); + for (i = 1; i <= 2; i++) { + move(bboxrow + i, boxcol); + printw(" "); + } +} + +/* + * procedure to put the board on the screen using addressable cursor + */ +makeboard() +{ + clear(); + refresh(); + move(titlerow, titlecol); + printw("=-> CANFIELD <-="); + move(fttlrow, fttlcol); + printw("foundation"); + move(foundrow - 1, fttlcol); + printw("=---= =---= =---= =---="); + move(foundrow, fttlcol); + printw("| | | | | | | |"); + move(foundrow + 1, fttlcol); + printw("=---= =---= =---= =---="); + move(ottlrow, sidecol); + printw("stock tableau"); + move(stockrow - 1, sidecol); + printw("=---="); + move(stockrow, sidecol); + printw("| |"); + move(stockrow + 1, sidecol); + printw("=---="); + move(talonrow - 2, sidecol); + printw("talon"); + move(talonrow - 1, sidecol); + printw("=---="); + move(talonrow, sidecol); + printw("| |"); + move(talonrow + 1, sidecol); + printw("=---="); + move(tabrow - 1, atabcol); + printw("-1- -2- -3- -4-"); + movebox(); +} + +/* + * clean up the board for another game + */ +cleanupboard() +{ + int cnt, row, col; + struct cardtype *ptr; + + if (Cflag) { + clearstat(); + for(ptr = stock, row = stockrow; + ptr != NIL; + ptr = ptr->next, row++) { + move(row, sidecol); + printw(" "); + } + move(row, sidecol); + printw(" "); + move(stockrow + 1, sidecol); + printw("=---="); + move(talonrow - 2, sidecol); + printw("talon"); + move(talonrow - 1, sidecol); + printw("=---="); + move(talonrow + 1, sidecol); + printw("=---="); + } + move(stockrow, sidecol); + printw("| |"); + move(talonrow, sidecol); + printw("| |"); + move(foundrow, fttlcol); + printw("| | | | | | | |"); + for (cnt = 0; cnt < 4; cnt++) { + switch(cnt) { + case 0: + col = atabcol; + break; + case 1: + col = btabcol; + break; + case 2: + col = ctabcol; + break; + case 3: + col = dtabcol; + break; + } + for(ptr = tableau[cnt], row = tabrow; + ptr != NIL; + ptr = ptr->next, row++) + removecard(col, row); + } +} + +/* + * procedure to create a deck of cards + */ +initdeck(deck) + struct cardtype *deck[]; +{ + int i; + int scnt; + char s; + int r; + + i = 0; + for (scnt=0; scnt<4; scnt++) { + s = suitmap[scnt]; + for (r=Ace; r<=King; r++) { + deck[i] = &cards[i]; + cards[i].rank = r; + cards[i].suit = s; + cards[i].color = colormap[scnt]; + cards[i].next = NIL; + i++; + } + } +} + +/* + * procedure to shuffle the deck + */ +shuffle(deck) + struct cardtype *deck[]; +{ + int i,j; + struct cardtype *temp; + + for (i=0; i<decksize; i++) { + deck[i]->visible = FALSE; + deck[i]->paid = FALSE; + } + for (i = decksize-1; i>=0; i--) { + j = random() % decksize; + if (i != j) { + temp = deck[i]; + deck[i] = deck[j]; + deck[j] = temp; + } + } +} + +/* + * procedure to remove the card from the board + */ +removecard(a, b) +{ + move(b, a); + printw(" "); +} + +/* + * procedure to print the cards on the board + */ +printrank(a, b, cp, inverse) + struct cardtype *cp; + bool inverse; +{ + move(b, a); + if (cp->rank != 10) + addch(' '); + if (inverse) + standout(); + switch (cp->rank) { + case 2: case 3: case 4: case 5: case 6: case 7: + case 8: case 9: case 10: + printw("%d", cp->rank); + break; + case Ace: + addch('A'); + break; + case Jack: + addch('J'); + break; + case Queen: + addch('Q'); + break; + case King: + addch('K'); + } + if (inverse) + standend(); +} + +/* + * procedure to print out a card + */ +printcard(a, b, cp) + int a,b; + struct cardtype *cp; +{ + if (cp == NIL) + removecard(a, b); + else if (cp->visible == FALSE) { + move(b, a); + printw(" ? "); + } else { + bool inverse = (cp->suit == 'd' || cp->suit == 'h'); + + printrank(a, b, cp, inverse); + if (inverse) + standout(); + addch(cp->suit); + if (inverse) + standend(); + } +} + +/* + * procedure to move the top card from one location to the top + * of another location. The pointers always point to the top + * of the piles. + */ +transit(source, dest) + struct cardtype **source, **dest; +{ + struct cardtype *temp; + + temp = *source; + *source = (*source)->next; + temp->next = *dest; + *dest = temp; +} + +/* + * Procedure to set the cards on the foundation base when available. + * Note that it is only called on a foundation pile at the beginning of + * the game, so the pile will have exactly one card in it. + */ +fndbase(cp, column, row) + struct cardtype **cp; +{ + bool nomore; + + if (*cp != NIL) + do { + if ((*cp)->rank == basecard->rank) { + base++; + printcard(pilemap[base], foundrow, *cp); + if (*cp == tableau[0]) + length[0] = length[0] - 1; + if (*cp == tableau[1]) + length[1] = length[1] - 1; + if (*cp == tableau[2]) + length[2] = length[2] - 1; + if (*cp == tableau[3]) + length[3] = length[3] - 1; + transit(cp, &found[base]); + if (cp == &talon) + usedtalon(); + if (cp == &stock) + usedstock(); + if (*cp != NIL) { + printcard(column, row, *cp); + nomore = FALSE; + } else { + removecard(column, row); + nomore = TRUE; + } + cardsoff++; + if (infullgame) { + this.wins += valuepercardup; + game.wins += valuepercardup; + total.wins += valuepercardup; + } + } else + nomore = TRUE; + } while (nomore == FALSE); +} + +/* + * procedure to initialize the things necessary for the game + */ +initgame() +{ + register i; + + for (i=0; i<18; i++) { + deck[i]->visible = TRUE; + deck[i]->paid = TRUE; + } + stockcnt = 13; + stock = deck[12]; + for (i=12; i>=1; i--) + deck[i]->next = deck[i - 1]; + deck[0]->next = NIL; + found[0] = deck[13]; + deck[13]->next = NIL; + for (i=1; i<4; i++) + found[i] = NIL; + basecard = found[0]; + for (i=14; i<18; i++) { + tableau[i - 14] = deck[i]; + deck[i]->next = NIL; + } + for (i=0; i<4; i++) { + bottom[i] = tableau[i]; + length[i] = tabrow; + } + hand = deck[18]; + for (i=18; i<decksize-1; i++) + deck[i]->next = deck[i + 1]; + deck[decksize-1]->next = NIL; + talon = NIL; + base = 0; + cinhand = 34; + taloncnt = 0; + timesthru = 0; + cardsoff = 1; + coldrow = ctoprow; + coldcol = cinitcol; + cnewrow = ctoprow; + cnewcol = cinitcol + cwidthcol; +} + +/* + * procedure to print the beginning cards and to start each game + */ +startgame() +{ + register int j; + + shuffle(deck); + initgame(); + this.hand = costofhand; + game.hand += costofhand; + total.hand += costofhand; + this.inspection = 0; + this.game = 0; + this.runs = 0; + this.information = 0; + this.wins = 0; + this.thinktime = 0; + infullgame = FALSE; + startedgame = FALSE; + printcard(foundcol, foundrow, found[0]); + printcard(stockcol, stockrow, stock); + printcard(atabcol, tabrow, tableau[0]); + printcard(btabcol, tabrow, tableau[1]); + printcard(ctabcol, tabrow, tableau[2]); + printcard(dtabcol, tabrow, tableau[3]); + printcard(taloncol, talonrow, talon); + move(foundrow - 2, basecol); + printw("Base"); + move(foundrow - 1, basecol); + printw("Rank"); + printrank(basecol, foundrow, found[0], 0); + for (j=0; j<=3; j++) + fndbase(&tableau[j], pilemap[j], tabrow); + fndbase(&stock, stockcol, stockrow); + showstat(); /* show card counting info to cheaters */ + movetotalon(); + updatebettinginfo(); +} + +/* + * procedure to clear the message printed from an error + */ +clearmsg() +{ + int i; + + if (errmsg == TRUE) { + errmsg = FALSE; + move(msgrow, msgcol); + for (i=0; i<25; i++) + addch(' '); + refresh(); + } +} + +/* + * procedure to print an error message if the move is not listed + */ +dumberror() +{ + errmsg = TRUE; + move(msgrow, msgcol); + printw("Not a proper move "); +} + +/* + * procedure to print an error message if the move is not possible + */ +destinerror() +{ + errmsg = TRUE; + move(msgrow, msgcol); + printw("Error: Can't move there"); +} + +/* + * function to see if the source has cards in it + */ +bool +notempty(cp) +struct cardtype *cp; +{ + if (cp == NIL) { + errmsg = TRUE; + move(msgrow, msgcol); + printw("Error: no cards to move"); + return (FALSE); + } else + return (TRUE); +} + +/* + * function to see if the rank of one card is less than another + */ +bool +ranklower(cp1, cp2) + struct cardtype *cp1, *cp2; +{ + if (cp2->rank == Ace) + if (cp1->rank == King) + return (TRUE); + else + return (FALSE); + else if (cp1->rank + 1 == cp2->rank) + return (TRUE); + else + return (FALSE); +} + +/* + * function to check the cardcolor for moving to a tableau + */ +bool +diffcolor(cp1, cp2) + struct cardtype *cp1, *cp2; +{ + if (cp1->color == cp2->color) + return (FALSE); + else + return (TRUE); +} + +/* + * function to see if the card can move to the tableau + */ +bool +tabok(cp, des) + struct cardtype *cp; +{ + if ((cp == stock) && (tableau[des] == NIL)) + return (TRUE); + else if (tableau[des] == NIL) + if (stock == NIL && + cp != bottom[0] && cp != bottom[1] && + cp != bottom[2] && cp != bottom[3]) + return (TRUE); + else + return (FALSE); + else if (ranklower(cp, tableau[des]) && diffcolor(cp, tableau[des])) + return (TRUE); + else + return (FALSE); +} + +/* + * procedure to turn the cards onto the talon from the deck + */ +movetotalon() +{ + int i, fin; + + if (cinhand <= 3 && cinhand > 0) { + move(msgrow, msgcol); + printw("Hand is now empty "); + } + if (cinhand >= 3) + fin = 3; + else if (cinhand > 0) + fin = cinhand; + else if (talon != NIL) { + timesthru++; + errmsg = TRUE; + move(msgrow, msgcol); + if (timesthru != 4) { + printw("Talon is now the new hand"); + this.runs += costofrunthroughhand; + game.runs += costofrunthroughhand; + total.runs += costofrunthroughhand; + while (talon != NIL) { + transit(&talon, &hand); + cinhand++; + } + if (cinhand >= 3) + fin = 3; + else + fin = cinhand; + taloncnt = 0; + coldrow = ctoprow; + coldcol = cinitcol; + cnewrow = ctoprow; + cnewcol = cinitcol + cwidthcol; + clearstat(); + showstat(); + } else { + fin = 0; + done = TRUE; + printw("I believe you have lost"); + refresh(); + sleep(5); + } + } else { + errmsg = TRUE; + move(msgrow, msgcol); + printw("Talon and hand are empty"); + fin = 0; + } + for (i=0; i<fin; i++) { + transit(&hand, &talon); + INCRHAND(cnewrow, cnewcol); + INCRHAND(coldrow, coldcol); + removecard(cnewcol, cnewrow); + if (i == fin - 1) + talon->visible = TRUE; + if (Cflag) { + if (talon->paid == FALSE && talon->visible == TRUE) { + this.information += costofinformation; + game.information += costofinformation; + total.information += costofinformation; + talon->paid = TRUE; + } + printcard(coldcol, coldrow, talon); + } + } + if (fin != 0) { + printcard(taloncol, talonrow, talon); + cinhand -= fin; + taloncnt += fin; + if (Cflag) { + move(handstatrow, handstatcol); + printw("%3d", cinhand); + move(talonstatrow, talonstatcol); + printw("%3d", taloncnt); + } + fndbase(&talon, taloncol, talonrow); + } +} + + +/* + * procedure to print card counting info on screen + */ +showstat() +{ + int row, col; + register struct cardtype *ptr; + + if (!Cflag) + return; + move(talonstatrow, talonstatcol - 7); + printw("Talon: %3d", taloncnt); + move(handstatrow, handstatcol - 7); + printw("Hand: %3d", cinhand); + move(stockstatrow, stockstatcol - 7); + printw("Stock: %3d", stockcnt); + for ( row = coldrow, col = coldcol, ptr = talon; + ptr != NIL; + ptr = ptr->next ) { + if (ptr->paid == FALSE && ptr->visible == TRUE) { + ptr->paid = TRUE; + this.information += costofinformation; + game.information += costofinformation; + total.information += costofinformation; + } + printcard(col, row, ptr); + DECRHAND(row, col); + } + for ( row = cnewrow, col = cnewcol, ptr = hand; + ptr != NIL; + ptr = ptr->next ) { + if (ptr->paid == FALSE && ptr->visible == TRUE) { + ptr->paid = TRUE; + this.information += costofinformation; + game.information += costofinformation; + total.information += costofinformation; + } + INCRHAND(row, col); + printcard(col, row, ptr); + } +} + +/* + * procedure to clear card counting info from screen + */ +clearstat() +{ + int row; + + move(talonstatrow, talonstatcol - 7); + printw(" "); + move(handstatrow, handstatcol - 7); + printw(" "); + move(stockstatrow, stockstatcol - 7); + printw(" "); + for ( row = ctoprow ; row <= cbotrow ; row++ ) { + move(row, cinitcol); + printw("%56s", " "); + } +} + +/* + * procedure to update card counting base + */ +usedtalon() +{ + removecard(coldcol, coldrow); + DECRHAND(coldrow, coldcol); + if (talon != NIL && (talon->visible == FALSE)) { + talon->visible = TRUE; + if (Cflag) { + this.information += costofinformation; + game.information += costofinformation; + total.information += costofinformation; + talon->paid = TRUE; + printcard(coldcol, coldrow, talon); + } + } + taloncnt--; + if (Cflag) { + move(talonstatrow, talonstatcol); + printw("%3d", taloncnt); + } +} + +/* + * procedure to update stock card counting base + */ +usedstock() +{ + stockcnt--; + if (Cflag) { + move(stockstatrow, stockstatcol); + printw("%3d", stockcnt); + } +} + +/* + * let 'em know how they lost! + */ +showcards() +{ + register struct cardtype *ptr; + int row; + + if (!Cflag || cardsoff == 52) + return; + for (ptr = talon; ptr != NIL; ptr = ptr->next) { + ptr->visible = TRUE; + ptr->paid = TRUE; + } + for (ptr = hand; ptr != NIL; ptr = ptr->next) { + ptr->visible = TRUE; + ptr->paid = TRUE; + } + showstat(); + move(stockrow + 1, sidecol); + printw(" "); + move(talonrow - 2, sidecol); + printw(" "); + move(talonrow - 1, sidecol); + printw(" "); + move(talonrow, sidecol); + printw(" "); + move(talonrow + 1, sidecol); + printw(" "); + for (ptr = stock, row = stockrow; ptr != NIL; ptr = ptr->next, row++) { + move(row, stockcol - 1); + printw("| |"); + printcard(stockcol, row, ptr); + } + if (stock == NIL) { + move(row, stockcol - 1); + printw("| |"); + row++; + } + move(handstatrow, handstatcol - 7); + printw(" "); + move(row, stockcol - 1); + printw("=---="); + if ( cardsoff == 52 ) + getcmd(moverow, movecol, "Hit return to exit"); +} + +/* + * procedure to update the betting values + */ +updatebettinginfo() +{ + long thiscosts, gamecosts, totalcosts; + double thisreturn, gamereturn, totalreturn; + time_t now; + register long dollars; + + time(&now); + dollars = (now - acctstart) / secondsperdollar; + if (dollars > 0) { + acctstart += dollars * secondsperdollar; + if (dollars > maxtimecharge) + dollars = maxtimecharge; + this.thinktime += dollars; + game.thinktime += dollars; + total.thinktime += dollars; + } + thiscosts = this.hand + this.inspection + this.game + + this.runs + this.information + this.thinktime; + gamecosts = game.hand + game.inspection + game.game + + game.runs + game.information + game.thinktime; + totalcosts = total.hand + total.inspection + total.game + + total.runs + total.information + total.thinktime; + this.worth = this.wins - thiscosts; + game.worth = game.wins - gamecosts; + total.worth = total.wins - totalcosts; + thisreturn = ((double)this.wins / (double)thiscosts - 1.0) * 100.0; + gamereturn = ((double)game.wins / (double)gamecosts - 1.0) * 100.0; + totalreturn = ((double)total.wins / (double)totalcosts - 1.0) * 100.0; + if (status != BETTINGBOX) + return; + move(tboxrow + 2, boxcol + 13); + printw("%4d%8d%9d", this.hand, game.hand, total.hand); + move(tboxrow + 3, boxcol + 13); + printw("%4d%8d%9d", this.inspection, game.inspection, total.inspection); + move(tboxrow + 4, boxcol + 13); + printw("%4d%8d%9d", this.game, game.game, total.game); + move(tboxrow + 5, boxcol + 13); + printw("%4d%8d%9d", this.runs, game.runs, total.runs); + move(tboxrow + 6, boxcol + 13); + printw("%4d%8d%9d", this.information, game.information, + total.information); + move(tboxrow + 7, boxcol + 13); + printw("%4d%8d%9d", this.thinktime, game.thinktime, total.thinktime); + move(tboxrow + 8, boxcol + 13); + printw("%4d%8d%9d", thiscosts, gamecosts, totalcosts); + move(tboxrow + 9, boxcol + 13); + printw("%4d%8d%9d", this.wins, game.wins, total.wins); + move(tboxrow + 10, boxcol + 13); + printw("%4d%8d%9d", this.worth, game.worth, total.worth); + move(tboxrow + 11, boxcol + 13); + printw("%4.0f%%%7.1f%%%8.1f%%", thisreturn, gamereturn, totalreturn); +} + +/* + * procedure to move a card from the stock or talon to the tableau + */ +simpletableau(cp, des) +struct cardtype **cp; +{ + int origin; + + if (notempty(*cp)) { + if (tabok(*cp, des)) { + if (*cp == stock) + origin = stk; + else + origin = tal; + if (tableau[des] == NIL) + bottom[des] = *cp; + transit(cp, &tableau[des]); + length[des]++; + printcard(pilemap[des], length[des], tableau[des]); + timesthru = 0; + if (origin == stk) { + usedstock(); + printcard(stockcol, stockrow, stock); + } else { + usedtalon(); + printcard(taloncol, talonrow, talon); + } + } else + destinerror(); + } +} + +/* + * print the tableau + */ +tabprint(sour, des) +{ + int dlength, slength, i; + struct cardtype *tempcard; + + for (i=tabrow; i<=length[sour]; i++) + removecard(pilemap[sour], i); + dlength = length[des] + 1; + slength = length[sour]; + if (slength == tabrow) + printcard(pilemap[des], dlength, tableau[sour]); + else + while (slength != tabrow - 1) { + tempcard = tableau[sour]; + for (i=1; i<=slength-tabrow; i++) + tempcard = tempcard->next; + printcard(pilemap[des], dlength, tempcard); + slength--; + dlength++; + } +} + +/* + * procedure to move from the tableau to the tableau + */ +tabtotab(sour, des) + register int sour, des; +{ + struct cardtype *temp; + + if (notempty(tableau[sour])) { + if (tabok(bottom[sour], des)) { + tabprint(sour, des); + temp = bottom[sour]; + bottom[sour] = NIL; + if (bottom[des] == NIL) + bottom[des] = temp; + temp->next = tableau[des]; + tableau[des] = tableau[sour]; + tableau[sour] = NIL; + length[des] = length[des] + (length[sour] - (tabrow - 1)); + length[sour] = tabrow - 1; + timesthru = 0; + } else + destinerror(); + } +} + +/* + * functions to see if the card can go onto the foundation + */ +bool +rankhigher(cp, let) + struct cardtype *cp; +{ + if (found[let]->rank == King) + if (cp->rank == Ace) + return(TRUE); + else + return(FALSE); + else if (cp->rank - 1 == found[let]->rank) + return(TRUE); + else + return(FALSE); +} + +/* + * function to determine if two cards are the same suit + */ +samesuit(cp, let) + struct cardtype *cp; +{ + if (cp->suit == found[let]->suit) + return (TRUE); + else + return (FALSE); +} + +/* + * procedure to move a card to the correct foundation pile + */ +movetofound(cp, source) + struct cardtype **cp; +{ + tempbase = 0; + mtfdone = FALSE; + if (notempty(*cp)) { + do { + if (found[tempbase] != NIL) + if (rankhigher(*cp, tempbase) + && samesuit(*cp, tempbase)) { + if (*cp == stock) + mtforigin = stk; + else if (*cp == talon) + mtforigin = tal; + else + mtforigin = tab; + transit(cp, &found[tempbase]); + printcard(pilemap[tempbase], + foundrow, found[tempbase]); + timesthru = 0; + if (mtforigin == stk) { + usedstock(); + printcard(stockcol, stockrow, stock); + } else if (mtforigin == tal) { + usedtalon(); + printcard(taloncol, talonrow, talon); + } else { + removecard(pilemap[source], length[source]); + length[source]--; + } + cardsoff++; + if (infullgame) { + this.wins += valuepercardup; + game.wins += valuepercardup; + total.wins += valuepercardup; + } + mtfdone = TRUE; + } else + tempbase++; + else + tempbase++; + } while ((tempbase != 4) && !mtfdone); + if (!mtfdone) + destinerror(); + } +} + +/* + * procedure to get a command + */ +getcmd(row, col, cp) + int row, col; + char *cp; +{ + char cmd[2] = { '\0', '\0'}, ch; + int i; + + i = 0; + move(row, col); + printw("%-24s", cp); + col += 1 + strlen(cp); + move(row, col); + refresh(); + do { + ch = getch() & 0177; + if (ch >= 'A' && ch <= 'Z') + ch += ('a' - 'A'); + if (ch == '\f') { + wrefresh(curscr); + refresh(); + } else if (i >= 2 && ch != erasechar() && ch != killchar()) { + if (ch != '\n' && ch != '\r' && ch != ' ') + write(1, "\007", 1); + } else if (ch == erasechar() && i > 0) { + printw("\b \b"); + refresh(); + cmd[--i] = '\0'; + } else if (ch == killchar() && i > 0) { + while (i > 0) { + printw("\b \b"); + cmd[--i] = '\0'; + } + refresh(); + } else if (ch == '\032') { /* Control-Z */ + suspend(); + move(row, col + i); + refresh(); + } else if (isprint(ch)) { + cmd[i++] = ch; + addch(ch); + refresh(); + } + } while (ch != '\n' && ch != '\r' && ch != ' '); + srcpile = cmd[0]; + destpile = cmd[1]; +} + +/* + * Suspend the game (shell escape if no process control on system) + */ +suspend() +{ +#ifndef SIGTSTP + char *sh; +#endif + + updatebettinginfo(); + move(21, 0); + refresh(); + if (dbfd != -1) { + lseek(dbfd, uid * sizeof(struct betinfo), 0); + write(dbfd, (char *)&total, sizeof(total)); + } + kill(getpid(), SIGTSTP); + raw(); + noecho(); +} + +/* + * procedure to evaluate and make the specific moves + */ +movecard() +{ + int source, dest; + char osrcpile, odestpile; + + done = FALSE; + errmsg = FALSE; + do { + if (talon == NIL && hand != NIL) + movetotalon(); + if (cardsoff == 52) { + refresh(); + srcpile = 'q'; + } else if (!startedgame) { + move(msgrow, msgcol); + errmsg = TRUE; + switch (34 - taloncnt - cinhand) { + default: + errmsg = FALSE; + break; + case 1: + printw("One card used from talon "); + break; + case 2: + printw("Two cards used from talon "); + break; + case 3: + printw(">3< cards used from talon "); + break; + } + getcmd(moverow, movecol, "Move:"); + } else + getcmd(moverow, movecol, "Move:"); + clearmsg(); + if (srcpile >= '1' && srcpile <= '4') + source = (int) (srcpile - '1'); + if (destpile >= '1' && destpile <= '4') + dest = (int) (destpile - '1'); + if (!startedgame && + (srcpile == 't' || srcpile == 's' || srcpile == 'h' || + srcpile == '1' || srcpile == '2' || srcpile == '3' || + srcpile == '4')) { + startedgame = TRUE; + osrcpile = srcpile; + odestpile = destpile; + if (status != BETTINGBOX) + srcpile = 'y'; + else do { + getcmd(moverow, movecol, "Inspect game?"); + } while (srcpile != 'y' && srcpile != 'n'); + if (srcpile == 'n') { + srcpile = 'q'; + } else { + this.inspection += costofinspection; + game.inspection += costofinspection; + total.inspection += costofinspection; + srcpile = osrcpile; + destpile = odestpile; + } + } + switch (srcpile) { + case 't': + if (destpile == 'f' || destpile == 'F') + movetofound(&talon, source); + else if (destpile >= '1' && destpile <= '4') + simpletableau(&talon, dest); + else + dumberror(); + break; + case 's': + if (destpile == 'f' || destpile == 'F') + movetofound(&stock, source); + else if (destpile >= '1' && destpile <= '4') + simpletableau(&stock, dest); + else dumberror(); + break; + case 'h': + if (destpile != 't' && destpile != 'T') { + dumberror(); + break; + } + if (infullgame) { + movetotalon(); + break; + } + if (status == BETTINGBOX) { + do { + getcmd(moverow, movecol, + "Buy game?"); + } while (srcpile != 'y' && + srcpile != 'n'); + if (srcpile == 'n') { + showcards(); + done = TRUE; + break; + } + } + infullgame = TRUE; + this.wins += valuepercardup * cardsoff; + game.wins += valuepercardup * cardsoff; + total.wins += valuepercardup * cardsoff; + this.game += costofgame; + game.game += costofgame; + total.game += costofgame; + movetotalon(); + break; + case 'q': + showcards(); + done = TRUE; + break; + case 'b': + printtopbettingbox(); + printbottombettingbox(); + status = BETTINGBOX; + break; + case 'x': + clearabovemovebox(); + clearbelowmovebox(); + status = NOBOX; + break; + case 'i': + printtopinstructions(); + printbottominstructions(); + status = INSTRUCTIONBOX; + break; + case 'c': + Cflag = !Cflag; + if (Cflag) + showstat(); + else + clearstat(); + break; + case '1': case '2': case '3': case '4': + if (destpile == 'f' || destpile == 'F') + movetofound(&tableau[source], source); + else if (destpile >= '1' && destpile <= '4') + tabtotab(source, dest); + else dumberror(); + break; + default: + dumberror(); + } + fndbase(&stock, stockcol, stockrow); + fndbase(&talon, taloncol, talonrow); + updatebettinginfo(); + } while (!done); +} + +char *basicinstructions[] = { + "Here are brief instuctions to the game of Canfield:\n\n", + " If you have never played solitaire before, it is recom-\n", + "mended that you consult a solitaire instruction book. In\n", + "Canfield, tableau cards may be built on each other downward\n", + "in alternate colors. An entire pile must be moved as a unit\n", + "in building. Top cards of the piles are available to be able\n", + "to be played on foundations, but never into empty spaces.\n\n", + " Spaces must be filled from the stock. The top card of\n", + "the stock also is available to be played on foundations or\n", + "built on tableau piles. After the stock is exhausted, ta-\n", + "bleau spaces may be filled from the talon and the player may\n", + "keep them open until he wishes to use them.\n\n", + " Cards are dealt from the hand to the talon by threes\n", + "and this repeats until there are no more cards in the hand\n", + "or the player quits. To have cards dealt onto the talon the\n", + "player types 'ht' for his move. Foundation base cards are\n", + "also automatically moved to the foundation when they become\n", + "available.\n\n", + "push any key when you are finished: ", + 0 }; + +char *bettinginstructions[] = { + " The rules for betting are somewhat less strict than\n", + "those used in the official version of the game. The initial\n", + "deal costs $13. You may quit at this point or inspect the\n", + "game. Inspection costs $13 and allows you to make as many\n", + "moves as is possible without moving any cards from your hand\n", + "to the talon. (the initial deal places three cards on the\n", + "talon; if all these cards are used, three more are made\n", + "available) Finally, if the game seems interesting, you must\n", + "pay the final installment of $26. At this point you are\n", + "credited at the rate of $5 for each card on the foundation;\n", + "as the game progresses you are credited with $5 for each\n", + "card that is moved to the foundation. Each run through the\n", + "hand after the first costs $5. The card counting feature\n", + "costs $1 for each unknown card that is identified. If the\n", + "information is toggled on, you are only charged for cards\n", + "that became visible since it was last turned on. Thus the\n", + "maximum cost of information is $34. Playing time is charged\n", + "at a rate of $1 per minute.\n\n", + "push any key when you are finished: ", + 0 }; + +/* + * procedure to printout instructions + */ +instruct() +{ + register char **cp; + + move(originrow, origincol); + printw("This is the game of solitaire called Canfield. Do\n"); + printw("you want instructions for the game?"); + do { + getcmd(originrow + 3, origincol, "y or n?"); + } while (srcpile != 'y' && srcpile != 'n'); + if (srcpile == 'n') + return; + clear(); + for (cp = basicinstructions; *cp != 0; cp++) + printw(*cp); + refresh(); + getch(); + clear(); + move(originrow, origincol); + printw("Do you want instructions for betting?"); + do { + getcmd(originrow + 2, origincol, "y or n?"); + } while (srcpile != 'y' && srcpile != 'n'); + if (srcpile == 'n') + return; + clear(); + for (cp = bettinginstructions; *cp != 0; cp++) + printw(*cp); + refresh(); + getch(); +} + +/* + * procedure to initialize the game + */ +initall() +{ + int i; + + srandom(getpid()); + time(&acctstart); + initdeck(deck); + uid = getuid(); + if (uid < 0) + uid = 0; + dbfd = open(_PATH_SCORE, 2); + if (dbfd < 0) + return; + i = lseek(dbfd, uid * sizeof(struct betinfo), 0); + if (i < 0) { + close(dbfd); + dbfd = -1; + return; + } + i = read(dbfd, (char *)&total, sizeof(total)); + if (i < 0) { + close(dbfd); + dbfd = -1; + return; + } +} + +/* + * procedure to end the game + */ +bool +finish() +{ + int row, col; + + if (cardsoff == 52) { + getcmd(moverow, movecol, "Hit return to exit"); + clear(); + refresh(); + move(originrow, origincol); + printw("CONGRATULATIONS!\n"); + printw("You won the game. That is a feat to be proud of.\n"); + row = originrow + 5; + col = origincol; + } else { + move(msgrow, msgcol); + printw("You got %d card", cardsoff); + if (cardsoff > 1) + printw("s"); + printw(" off "); + move(msgrow, msgcol); + row = moverow; + col = movecol; + } + do { + getcmd(row, col, "Play again (y or n)?"); + } while (srcpile != 'y' && srcpile != 'n'); + errmsg = TRUE; + clearmsg(); + if (srcpile == 'y') + return (FALSE); + else + return (TRUE); +} + +/* + * procedure to clean up and exit + */ +void +cleanup() +{ + + total.thinktime += 1; + status = NOBOX; + updatebettinginfo(); + if (dbfd != -1) { + lseek(dbfd, uid * sizeof(struct betinfo), 0); + write(dbfd, (char *)&total, sizeof(total)); + close(dbfd); + } + clear(); + move(22,0); + refresh(); + endwin(); + exit(0); + /* NOTREACHED */ +} + +/* + * Field an interrupt. + */ +void +askquit() +{ + move(msgrow, msgcol); + printw("Really wish to quit? "); + do { + getcmd(moverow, movecol, "y or n?"); + } while (srcpile != 'y' && srcpile != 'n'); + clearmsg(); + if (srcpile == 'y') + cleanup(); + signal(SIGINT, askquit); +} + +/* + * Can you tell that this used to be a Pascal program? + */ +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef MAXLOAD + double vec[3]; + + loadav(vec); + if (vec[2] >= MAXLOAD) { + puts("The system load is too high. Try again later."); + exit(0); + } +#endif + signal(SIGINT, askquit); + signal(SIGHUP, cleanup); + signal(SIGTERM, cleanup); + initscr(); + raw(); + noecho(); + initall(); + instruct(); + makeboard(); + for (;;) { + startgame(); + movecard(); + if (finish()) + break; + if (cardsoff == 52) + makeboard(); + else + cleanupboard(); + } + cleanup(); + /* NOTREACHED */ +} diff --git a/games/canfield/canfield/pathnames.h b/games/canfield/canfield/pathnames.h new file mode 100644 index 00000000000..4ecb7bb9a43 --- /dev/null +++ b/games/canfield/canfield/pathnames.h @@ -0,0 +1,39 @@ +/* $NetBSD: pathnames.h,v 1.3 1995/03/21 15:08:34 cgd Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 5/31/93 + */ + +#define _PATH_SCORE "/var/games/cfscores" + diff --git a/games/canfield/cfscores/Makefile b/games/canfield/cfscores/Makefile new file mode 100644 index 00000000000..bdc6269f8c3 --- /dev/null +++ b/games/canfield/cfscores/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.3 1995/03/21 15:08:36 cgd Exp $ +# @(#)Makefile 8.1 (Berkeley) 5/31/93 + +PROG= cfscores +CFLAGS+=-I${.CURDIR}/../canfield +NOMAN= noman +HIDEGAME=hidegame + +.include "../../Makefile.inc" +.include <bsd.prog.mk> diff --git a/games/canfield/cfscores/cfscores.c b/games/canfield/cfscores/cfscores.c new file mode 100644 index 00000000000..4a3a0e8f782 --- /dev/null +++ b/games/canfield/cfscores/cfscores.c @@ -0,0 +1,154 @@ +/* $NetBSD: cfscores.c,v 1.3 1995/03/21 15:08:37 cgd Exp $ */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cfscores.c 8.1 (Berkeley) 5/31/93"; +#else +static char rcsid[] = "$NetBSD: cfscores.c,v 1.3 1995/03/21 15:08:37 cgd Exp $"; +#endif +#endif /* not lint */ + +#include <sys/types.h> +#include <pwd.h> +#include "pathnames.h" + +struct betinfo { + long hand; /* cost of dealing hand */ + long inspection; /* cost of inspecting hand */ + long game; /* cost of buying game */ + long runs; /* cost of running through hands */ + long information; /* cost of information */ + long thinktime; /* cost of thinking time */ + long wins; /* total winnings */ + long worth; /* net worth after costs */ +}; + +int dbfd; + +main(argc, argv) + int argc; + char *argv[]; +{ + register struct passwd *pw; + int uid; + + if (argc > 2) { + printf("Usage: cfscores [user]\n"); + exit(1); + } + dbfd = open(_PATH_SCORE, 0); + if (dbfd < 0) { + perror(_PATH_SCORE); + exit(2); + } + setpwent(); + if (argc == 1) { + uid = getuid(); + pw = getpwuid(uid); + if (pw == 0) { + printf("You are not listed in the password file?!?\n"); + exit(2); + } + printuser(pw, 1); + exit(0); + } + if (strcmp(argv[1], "-a") == 0) { + while ((pw = getpwent()) != 0) + printuser(pw, 0); + exit(0); + } + pw = getpwnam(argv[1]); + if (pw == 0) { + printf("User %s unknown\n", argv[1]); + exit(3); + } + printuser(pw, 1); + exit(0); +} + +/* + * print out info for specified password entry + */ +printuser(pw, printfail) + register struct passwd *pw; + int printfail; +{ + struct betinfo total; + int i; + + if (pw->pw_uid < 0) { + printf("Bad uid %d\n", pw->pw_uid); + return; + } + i = lseek(dbfd, pw->pw_uid * sizeof(struct betinfo), 0); + if (i < 0) { + perror("lseek"); + return; + } + i = read(dbfd, (char *)&total, sizeof(total)); + if (i < 0) { + perror("read"); + return; + } + if (i == 0 || total.hand == 0) { + if (printfail) + printf("%s has never played canfield.\n", pw->pw_name); + return; + } + printf("*----------------------*\n"); + if (total.worth >= 0) + printf("* Winnings for %-8s*\n", pw->pw_name); + else + printf("* Losses for %-10s*\n", pw->pw_name); + printf("*======================*\n"); + printf("|Costs Total |\n"); + printf("| Hands %8d |\n", total.hand); + printf("| Inspections %8d |\n", total.inspection); + printf("| Games %8d |\n", total.game); + printf("| Runs %8d |\n", total.runs); + printf("| Information %8d |\n", total.information); + printf("| Think time %8d |\n", total.thinktime); + printf("|Total Costs %8d |\n", total.wins - total.worth); + printf("|Winnings %8d |\n", total.wins); + printf("|Net Worth %8d |\n", total.worth); + printf("*----------------------*\n\n"); +} |