From: Alexandre Beletti Date: Thu, 25 Sep 2014 00:03:28 +0000 (+0200) Subject: Import NetBSD games/fish command. X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/Bv9ARM.ch05.html?a=commitdiff_plain;h=6a76678e59667bb2f015855384331fc706fc2d18;p=minix.git Import NetBSD games/fish command. Change-Id: Ie3009121c768fa5e0c50c681b87cde344ae7cfe2 --- diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index 9b7a8310b..bdd4debec 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -593,6 +593,7 @@ ./usr/games/bcd minix-sys ./usr/games/colorbars minix-sys ./usr/games/factor minix-sys +./usr/games/fish minix-sys ./usr/games/fortune minix-sys ./usr/games/hide minix-sys ./usr/games/monop minix-sys @@ -5027,6 +5028,7 @@ ./usr/man/man6/bcd.6 minix-sys ./usr/man/man6/colorbars.6 minix-sys ./usr/man/man6/factor.6 minix-sys +./usr/man/man6/fish.6 minix-sys ./usr/man/man6/fortune.6 minix-sys ./usr/man/man6/monop.6 minix-sys ./usr/man/man6/morse.6 minix-sys @@ -5281,6 +5283,7 @@ ./usr/share/examples/lutok/interpreter.cpp minix-sys kyua ./usr/share/examples/lutok/raii.cpp minix-sys kyua ./usr/share/games minix-sys +./usr/share/games/fish.instr minix-sys ./usr/share/games/fortune minix-sys ./usr/share/games/fortune/farber minix-sys ./usr/share/games/fortune/farber.dat minix-sys diff --git a/games/Makefile b/games/Makefile index e03e53130..085caaf40 100644 --- a/games/Makefile +++ b/games/Makefile @@ -10,7 +10,7 @@ SUBDIR= adventure arithmetic \ bcd \ colorbars \ - factor fortune \ + factor fish fortune \ monop morse number \ pig ppt primes \ random snake tetris \ diff --git a/games/fish/Makefile b/games/fish/Makefile new file mode 100644 index 000000000..854bd568b --- /dev/null +++ b/games/fish/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.10 1999/02/13 02:54:21 lukem Exp $ +# @(#)Makefile 8.1 (Berkeley) 5/31/93 + +.include + +PROG= fish +MAN= fish.6 +HIDEGAME=hidegame +.if ${MKSHARE} != "no" +FILES=fish.instr +FILESDIR=/usr/share/games +.endif + +.include diff --git a/games/fish/fish.6 b/games/fish/fish.6 new file mode 100644 index 000000000..398c55f7e --- /dev/null +++ b/games/fish/fish.6 @@ -0,0 +1,87 @@ +.\" $NetBSD: fish.6,v 1.8 2003/08/07 09:37:13 agc 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. 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. +.\" +.\" @(#)fish.6 8.1 (Berkeley) 5/31/93 +.\" +.Dd May 31, 1993 +.Dt FISH 6 +.Os +.Sh NAME +.Nm fish +.Nd play +.Dq Go Fish +.Sh SYNOPSIS +.Nm +.Op Fl p +.Sh DESCRIPTION +.Nm +is the game +.Dq Go Fish , +a traditional children's card game. +.Pp +The computer deals the player and itself seven cards, and places +the rest of the deck face-down (figuratively). +The object of the game is to collect +.Dq books , +or all of the members of a single rank. +For example, collecting four 2's would give the player a +.Dq book of 2's . +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl p +Professional mode. +.El +.Pp +The computer makes a random decision as to who gets to start the +game, and then the computer and player take turns asking each other +for cards of a specified rank. +If the asked player has any cards of the requested rank, they give +them up to the asking player. +A player must have at least one of the cards of the rank they request +in their hand. +When a player asks for a rank of which the other player has no +cards, the asker is told to +.Dq Go Fish! . +Then, the asker draws a card from the non-dealt cards. +If they draw the card they asked for, they continue their turn, asking +for more ranks from the other player. +Otherwise, the other player gets a turn. +.Pp +When a player completes a book, either by getting cards from the +other player or drawing from the deck, they set those cards aside and +the rank is no longer in play. +.Pp +The game ends when either player no longer has any cards in their hand. +The player with the most books wins. +.Pp +.Nm +provides instructions as to what input it accepts. +.Sh BUGS +The computer cheats only rarely. diff --git a/games/fish/fish.c b/games/fish/fish.c new file mode 100644 index 000000000..c7c342abd --- /dev/null +++ b/games/fish/fish.c @@ -0,0 +1,478 @@ +/* $NetBSD: fish.c,v 1.22 2011/09/01 07:18:50 plunky Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Muffy Barkocy. + * + * 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. 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. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1990, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)fish.c 8.1 (Berkeley) 5/31/93"; +#else +__RCSID("$NetBSD: fish.c,v 1.22 2011/09/01 07:18:50 plunky Exp $"); +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +#define RANKS 13 +#define HANDSIZE 7 +#define CARDS 4 +#define TOTCARDS RANKS * CARDS + +#define USER 1 +#define COMPUTER 0 +#define OTHER(a) (1 - (a)) + +static const char *const cards[] = { + "A", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "J", "Q", "K", NULL, +}; +#define PRC(card) (void)printf(" %s", cards[card]) + +static int promode; +static int asked[RANKS], comphand[RANKS], deck[TOTCARDS]; +static int userasked[RANKS], userhand[RANKS]; +static int curcard = TOTCARDS; + +static void chkwinner(int, const int *); +static int compmove(void); +static int countbooks(const int *); +static int countcards(const int *); +static int drawcard(int, int *); +static int gofish(int, int, int *); +static void goodmove(int, int, int *, int *); +static void init(void); +static void instructions(void); +static int nrandom(int); +static void printhand(const int *); +static void printplayer(int); +static int promove(void); +static void usage(void) __dead; +static int usermove(void); + +int +main(int argc, char **argv) +{ + int ch, move; + + /* Revoke setgid privileges */ + setgid(getgid()); + + while ((ch = getopt(argc, argv, "p")) != -1) + switch(ch) { + case 'p': + promode = 1; + break; + case '?': + default: + usage(); + } + + srandom(time(NULL)); + instructions(); + init(); + + if (nrandom(2) == 1) { + printplayer(COMPUTER); + (void)printf("get to start.\n"); + goto istart; + } + printplayer(USER); + (void)printf("get to start.\n"); + + for (;;) { + move = usermove(); + if (!comphand[move]) { + if (gofish(move, USER, userhand)) + continue; + } else { + goodmove(USER, move, userhand, comphand); + continue; + } + +istart: for (;;) { + move = compmove(); + if (!userhand[move]) { + if (!gofish(move, COMPUTER, comphand)) + break; + } else + goodmove(COMPUTER, move, comphand, userhand); + } + } + /* NOTREACHED */ +} + +static int +usermove(void) +{ + int n; + const char *const *p; + char buf[256]; + + (void)printf("\nYour hand is:"); + printhand(userhand); + + for (;;) { + (void)printf("You ask me for: "); + (void)fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) == NULL) + exit(0); + if (buf[0] == '\0') + continue; + if (buf[0] == '\n') { + (void)printf("%d cards in my hand, %d in the pool.\n", + countcards(comphand), curcard); + (void)printf("My books:"); + (void)countbooks(comphand); + continue; + } + buf[strlen(buf) - 1] = '\0'; + if (!strcasecmp(buf, "p") && !promode) { + promode = 1; + (void)printf("Entering pro mode.\n"); + continue; + } + if (!strcasecmp(buf, "quit")) + exit(0); + for (p = cards; *p; ++p) + if (!strcasecmp(*p, buf)) + break; + if (!*p) { + (void)printf("I don't understand!\n"); + continue; + } + n = p - cards; + if (userhand[n]) { + userasked[n] = 1; + return(n); + } + if (nrandom(3) == 1) + (void)printf("You don't have any of those!\n"); + else + (void)printf("You don't have any %s's!\n", cards[n]); + if (nrandom(4) == 1) + (void)printf("No cheating!\n"); + (void)printf("Guess again.\n"); + } + /* NOTREACHED */ +} + +static int +compmove(void) +{ + static int lmove; + + if (promode) + lmove = promove(); + else { + do { + lmove = (lmove + 1) % RANKS; + } while (!comphand[lmove] || comphand[lmove] == CARDS); + } + asked[lmove] = 1; + + (void)printf("I ask you for: %s.\n", cards[lmove]); + return(lmove); +} + +static int +promove(void) +{ + int i, max; + + for (i = 0; i < RANKS; ++i) + if (userasked[i] && + comphand[i] > 0 && comphand[i] < CARDS) { + userasked[i] = 0; + return(i); + } + if (nrandom(3) == 1) { + for (i = 0;; ++i) + if (comphand[i] && comphand[i] != CARDS) { + max = i; + break; + } + while (++i < RANKS) + if (comphand[i] != CARDS && + comphand[i] > comphand[max]) + max = i; + return(max); + } + if (nrandom(1024) == 0723) { + for (i = 0; i < RANKS; ++i) + if (userhand[i] && comphand[i]) + return(i); + } + for (;;) { + for (i = 0; i < RANKS; ++i) + if (comphand[i] && comphand[i] != CARDS && + !asked[i]) + return(i); + for (i = 0; i < RANKS; ++i) + asked[i] = 0; + } + /* NOTREACHED */ +} + +static int +drawcard(int player, int *hand) +{ + int card; + + ++hand[card = deck[--curcard]]; + if (player == USER || hand[card] == CARDS) { + printplayer(player); + (void)printf("drew %s", cards[card]); + if (hand[card] == CARDS) { + (void)printf(" and made a book of %s's!\n", + cards[card]); + chkwinner(player, hand); + } else + (void)printf(".\n"); + } + return(card); +} + +static int +gofish(int askedfor, int player, int *hand) +{ + printplayer(OTHER(player)); + (void)printf("say \"GO FISH!\"\n"); + if (askedfor == drawcard(player, hand)) { + printplayer(player); + (void)printf("drew the guess!\n"); + printplayer(player); + (void)printf("get to ask again!\n"); + return(1); + } + return(0); +} + +static void +goodmove(int player, int move, int *hand, int *opphand) +{ + printplayer(OTHER(player)); + (void)printf("have %d %s%s.\n", + opphand[move], cards[move], opphand[move] == 1 ? "": "'s"); + + hand[move] += opphand[move]; + opphand[move] = 0; + + if (hand[move] == CARDS) { + printplayer(player); + (void)printf("made a book of %s's!\n", cards[move]); + chkwinner(player, hand); + } + + chkwinner(OTHER(player), opphand); + + printplayer(player); + (void)printf("get another guess!\n"); +} + +static void +chkwinner(int player, const int *hand) +{ + int cb, i, ub; + + for (i = 0; i < RANKS; ++i) + if (hand[i] > 0 && hand[i] < CARDS) + return; + printplayer(player); + (void)printf("don't have any more cards!\n"); + (void)printf("My books:"); + cb = countbooks(comphand); + (void)printf("Your books:"); + ub = countbooks(userhand); + (void)printf("\nI have %d, you have %d.\n", cb, ub); + if (ub > cb) { + (void)printf("\nYou win!!!\n"); + if (nrandom(1024) == 0723) + (void)printf("Cheater, cheater, pumpkin eater!\n"); + } else if (cb > ub) { + (void)printf("\nI win!!!\n"); + if (nrandom(1024) == 0723) + (void)printf("Hah! Stupid peasant!\n"); + } else + (void)printf("\nTie!\n"); + exit(0); +} + +static void +printplayer(int player) +{ + switch (player) { + case COMPUTER: + (void)printf("I "); + break; + case USER: + (void)printf("You "); + break; + } +} + +static void +printhand(const int *hand) +{ + int book, i, j; + + for (book = i = 0; i < RANKS; i++) + if (hand[i] < CARDS) + for (j = hand[i]; --j >= 0;) + PRC(i); + else + ++book; + if (book) { + (void)printf(" + Book%s of", book > 1 ? "s" : ""); + for (i = 0; i < RANKS; i++) + if (hand[i] == CARDS) + PRC(i); + } + (void)putchar('\n'); +} + +static int +countcards(const int *hand) +{ + int i, count; + + for (count = i = 0; i < RANKS; i++) + count += *hand++; + return(count); +} + +static int +countbooks(const int *hand) +{ + int i, count; + + for (count = i = 0; i < RANKS; i++) + if (hand[i] == CARDS) { + ++count; + PRC(i); + } + if (!count) + (void)printf(" none"); + (void)putchar('\n'); + return(count); +} + +static void +init(void) +{ + int i, j, temp; + + for (i = 0; i < TOTCARDS; ++i) + deck[i] = i % RANKS; + for (i = 0; i < TOTCARDS - 1; ++i) { + j = nrandom(TOTCARDS-i); + if (j == 0) + continue; + temp = deck[i]; + deck[i] = deck[i+j]; + deck[i+j] = temp; + } + for (i = 0; i < HANDSIZE; ++i) { + ++userhand[deck[--curcard]]; + ++comphand[deck[--curcard]]; + } +} + +static int +nrandom(int n) +{ + + return((int)random() % n); +} + +static void +instructions(void) +{ + int input; + pid_t pid; + int fd; + const char *pager; + int status; + + (void)printf("Would you like instructions (y or n)? "); + input = getchar(); + while (getchar() != '\n'); + if (input != 'y') + return; + + switch (pid = fork()) { + case 0: /* child */ + if (!isatty(1)) + pager = "cat"; + else { + if (!(pager = getenv("PAGER")) || (*pager == 0)) + pager = _PATH_MORE; + } + if ((fd = open(_PATH_INSTR, O_RDONLY)) == -1) + err(1, "open %s", _PATH_INSTR); + if (dup2(fd, 0) == -1) + err(1, "dup2"); + (void)execl("/bin/sh", "sh", "-c", pager, (char *) NULL); + err(1, "exec sh -c %s", pager); + /*NOTREACHED*/ + case -1: + err(1, "fork"); + /*NOTREACHED*/ + default: + (void)waitpid(pid, &status, 0); + break; + } + (void)printf("Hit return to continue...\n"); + while ((input = getchar()) != EOF && input != '\n'); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: fish [-p]\n"); + exit(1); +} diff --git a/games/fish/fish.instr b/games/fish/fish.instr new file mode 100644 index 000000000..b7e87a0a7 --- /dev/null +++ b/games/fish/fish.instr @@ -0,0 +1,29 @@ +This is the traditional children's card game "Go Fish". We each get seven +cards, and the rest of the deck is kept to be drawn from later. The +object of the game is to collect "books", or all of the cards of a single +value. For example, getting four 2's would give you a "book of 2's". + +We take turns asking each other for cards, but you can't ask me for a card +value if you don't have one of them in your hand! If I have any cards of +the value you ask for, I have to give them to you. As long as I have one +of the cards you ask for, you get to keep asking. If you ask me for a +card of which I don't have any, then I'll tell you to "Go Fish!" This +means that you draw a card from the deck. If you draw the card you asked +me for, you get to keep asking me for cards. If not, it's my turn and I ask +you for a card. + +Sometimes you get to ask first, sometimes I do. I'll tell you when it's +your turn to move, I'll draw cards from the deck for you, and I'll tell +you what you have in your hand. (Don't worry, I don't look at your hand +when I'm trying to decide what card to ask for, honest!) + +Your input can be a card name ("A", "2", "3", "4", "5", "6", "7", "8", +"9", "10", "J", "Q" or "K") or the letter "p", or "quit". The letter "p" +makes my game much smarter, and the line "quit" stops the game. Just +hitting the carriage return key displays how many cards I have in my hand, +how many are left in the deck, and which books I've gotten. + +Normally, the game stops when one of us runs out of cards, and the winner +is whoever has the most books! + +Good luck! diff --git a/games/fish/pathnames.h b/games/fish/pathnames.h new file mode 100644 index 000000000..3dced4a86 --- /dev/null +++ b/games/fish/pathnames.h @@ -0,0 +1,35 @@ +/* $NetBSD: pathnames.h,v 1.4 2003/08/07 09:37:13 agc 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. 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_INSTR "/usr/share/games/fish.instr" +#define _PATH_MORE "/usr/bin/more"