]> Zhao Yanbai Git Server - minix.git/commitdiff
Importing games/monop
authorThomas Cort <tcort@minix3.org>
Sun, 16 Mar 2014 14:42:24 +0000 (10:42 -0400)
committerLionel Sambuc <lionel@minix3.org>
Mon, 28 Jul 2014 15:05:19 +0000 (17:05 +0200)
No Minix specific changes needed.

Change-Id: I362b974a95911d26fcd8a4401129ca946179d93c

21 files changed:
distrib/sets/lists/minix/mi
games/Makefile
games/monop/Makefile [new file with mode: 0644]
games/monop/cards.c [new file with mode: 0644]
games/monop/deck.h [new file with mode: 0644]
games/monop/execute.c [new file with mode: 0644]
games/monop/getinp.c [new file with mode: 0644]
games/monop/houses.c [new file with mode: 0644]
games/monop/jail.c [new file with mode: 0644]
games/monop/misc.c [new file with mode: 0644]
games/monop/monop.6 [new file with mode: 0644]
games/monop/monop.c [new file with mode: 0644]
games/monop/monop.h [new file with mode: 0644]
games/monop/morg.c [new file with mode: 0644]
games/monop/print.c [new file with mode: 0644]
games/monop/prop.c [new file with mode: 0644]
games/monop/rent.c [new file with mode: 0644]
games/monop/roll.c [new file with mode: 0644]
games/monop/spec.c [new file with mode: 0644]
games/monop/trade.c [new file with mode: 0644]
releasetools/nbsd_ports

index 559a0e0c647d86c067c54a05798f0791fd74f00e..d974710093f2aa91371c5653b281a3bb6199a874 100644 (file)
 ./usr/games/factor                     minix-sys
 ./usr/games/fortune                    minix-sys
 ./usr/games/hide                       minix-sys
+./usr/games/monop                      minix-sys
 ./usr/games/morse                      minix-sys
 ./usr/games/number                     minix-sys
 ./usr/games/pig                                minix-sys
 ./usr/man/man6/bcd.6                           minix-sys
 ./usr/man/man6/factor.6                                minix-sys
 ./usr/man/man6/fortune.6                       minix-sys
+./usr/man/man6/monop.6                         minix-sys
 ./usr/man/man6/morse.6                         minix-sys
 ./usr/man/man6/number.6                                minix-sys
 ./usr/man/man6/pig.6                           minix-sys
index 75d15e4259c9b88bc1732883b7897c3eec10865f..0f02325dae46ce36d620658a475b5365bd1f557a 100644 (file)
@@ -11,7 +11,7 @@ SUBDIR=       adventure \
        bcd \
        \
        factor fortune \
-       morse number \
+       monop morse number \
        pig ppt primes
 
 .if !defined(__MINIX)
diff --git a/games/monop/Makefile b/games/monop/Makefile
new file mode 100644 (file)
index 0000000..45eea38
--- /dev/null
@@ -0,0 +1,12 @@
+#      $NetBSD: Makefile,v 1.30 2008/02/24 02:43:18 dholland Exp $
+#      @(#)Makefile    8.1 (Berkeley) 5/31/93
+
+.include <bsd.own.mk>
+
+PROG=  monop
+SRCS=  monop.c cards.c execute.c getinp.c houses.c jail.c misc.c \
+       morg.c print.c prop.c rent.c roll.c spec.c trade.c
+MAN=   monop.6
+HIDEGAME=hidegame
+
+.include <bsd.prog.mk>
diff --git a/games/monop/cards.c b/games/monop/cards.c
new file mode 100644 (file)
index 0000000..bae1de8
--- /dev/null
@@ -0,0 +1,397 @@
+/*     $NetBSD: cards.c,v 1.25 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cards.c    8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: cards.c,v 1.25 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/endian.h>
+#include "monop.h"
+#include "deck.h"
+
+/*
+ *     These routine deal with the card decks
+ */
+
+static void set_up(DECK *);
+static void printmes(const char *text);
+
+#define        GOJF    'F'     /* char for get-out-of-jail-free cards  */
+
+struct cardinfo {
+       const char *actioncode;
+       const char *text;
+};
+
+static const struct cardinfo cc_cards[] = {
+       { "FF",
+               ">> GET OUT OF JAIL FREE <<\n"
+               "Keep this card until needed or sold\n"
+       },
+       { "++25",
+               "Receive for Services $25.\n"
+       },
+       { "++200",
+               "Bank Error in Your Favor.\n"
+               "Collect $200.\n"
+       },
+       { "++20",
+               "Income Tax Refund.\n"
+               "Collect $20.\n"
+       },
+       { "--100",
+               "Pay Hospital $100\n"
+       },
+       { "++100",
+               "Life Insurance Matures.\n"
+               "Collect $100\n"
+       },
+       { "++45",
+               "From sale of Stock You get $45.\n"
+       },
+       { "TX",
+               "You are Assessed for street repairs.\n"
+               "\t$40 per House\n"
+               "\t$115 per Hotel\n"
+       },
+       { "++100",
+               "X-mas Fund Matures.\n"
+               "Collect $100.\n"
+       },
+       { "++11",
+               "You have won Second Prize in a Beauty Contest\n"
+               "Collect $11\n"
+       },
+       { "MF0",
+               "Advance to GO\n"
+               "(Collect $200)\n"
+       },
+       { "++100",
+               "You inherit $100\n"
+       },
+       { "--150",
+               "Pay School Tax of $150.\n"
+       },
+       { "MJ",
+               "\t\t>> GO TO JAIL <<\n"
+               "Go Directly to Jail. Do not pass GO  Do not collect $200.\n"
+       },
+       { "+A50",
+               "\t\t>> GRAND OPERA OPENING <<\n"
+               "Collect $50 from each player for opening night seats.\n"
+       },
+       { "--50",
+               "Doctor's Fee:  Pay $50.\n"
+       }
+};
+
+static const struct cardinfo ch_cards[] = {
+       { "FF",
+               ">> GET OUT OF JAIL FREE <<\n"
+               "Keep this card until needed or sold\n"
+       },
+       { "MR",
+               "Advance to the nearest Railroad, and pay owner\n"
+               "Twice the rental to which he is otherwise entitled.\n"
+               "If Railroad is unowned you may buy it from the bank\n"
+       },
+       { "MU",
+               "Advance to the nearest Utility.\n"
+               "If unowned, you may buy it from the bank.\n"
+               "If owned, throw dice and pay oner a total of ten times\n"
+               "the amount thrown.\n"
+       },
+       { "MB3",
+               "Go Back 3 Spaces\n"
+       },
+       { "MR",
+               "Advance to the nearest Railroad, and pay owner\n"
+               "Twice the rental to which he is otherwise entitled.\n"
+               "If Railroad is unowned you may buy it from the bank\n"
+       },
+       { "MJ",
+               "    >> GO DIRECTLY TO JAIL <<\n"
+               "Do not pass GO, Do not Collect $200.\n"
+       },
+       { "MF5",
+               "Take a Ride on the Reading.\n"
+               "If you pass GO, collect $200.\n"
+       },
+       { "MF39",
+               "Take a Walk on the Board Walk.\n"
+               "    (Advance To Board Walk)\n"
+       },
+       { "MF24",
+               "Advance to Illinois Ave.\n"
+       },
+       { "MF0",
+               "Advance to Go\n"
+       },
+       { "MF11",
+               "Advance to St. Charles Place.\n"
+               "If you pass GO, collect $200.\n"
+       },
+       { "TX",
+               "Make general repairs on all of your Property.\n"
+               "For Each House pay $25.\n"
+               "For Each Hotel pay $100.\n"
+       },
+       { "-A50",
+               "You have been elected Chairman of the Board.\n"
+               "Pay each player $50.\n"
+       },
+       { "--15",
+               "Pay Poor Tax of $15\n"
+       },
+       { "++50",
+               "Bank pays you Dividend of $50.\n"
+       },
+       { "++150",
+               "Your Building and Loan Matures.\n"
+               "Collect $150.\n"
+       }
+};
+
+/*
+ * This routine initializes the decks from the data above.
+ */
+void
+init_decks(void)
+{
+       CC_D.info = cc_cards;
+       CC_D.num_cards = sizeof(cc_cards) / sizeof(cc_cards[0]);
+       CH_D.info = ch_cards;
+       CH_D.num_cards = sizeof(ch_cards) / sizeof(ch_cards[0]);
+       set_up(&CC_D);
+       set_up(&CH_D);
+}
+
+/*
+ *     This routine sets up the offset pointers for the given deck.
+ */
+static void
+set_up(DECK *dp)
+{
+       int r1, r2;
+       int i;
+
+       dp->cards = calloc((size_t)dp->num_cards, sizeof(dp->cards[0]));
+       if (dp->cards == NULL)
+               errx(1, "out of memory");
+
+       for (i = 0; i < dp->num_cards; i++)
+               dp->cards[i] = i;
+
+       dp->top_card = 0;
+       dp->gojf_used = FALSE;
+
+       for (i = 0; i < dp->num_cards; i++) {
+               int temp;
+
+               r1 = roll(1, dp->num_cards) - 1;
+               r2 = roll(1, dp->num_cards) - 1;
+               temp = dp->cards[r2];
+               dp->cards[r2] = dp->cards[r1];
+               dp->cards[r1] = temp;
+       }
+}
+
+/*
+ *     This routine draws a card from the given deck
+ */
+void
+get_card(DECK *dp)
+{
+       char type_maj, type_min;
+       int num;
+       int i, per_h, per_H, num_h, num_H;
+       OWN *op;
+       const struct cardinfo *thiscard;
+
+       do {
+               thiscard = &dp->info[dp->top_card];
+               type_maj = thiscard->actioncode[0];
+               dp->top_card = (dp->top_card + 1) % dp->num_cards;
+       } while (dp->gojf_used && type_maj == GOJF);
+       type_min = thiscard->actioncode[1];
+       num = atoi(thiscard->actioncode+2);
+
+       printmes(thiscard->text);
+       switch (type_maj) {
+         case '+':             /* get money            */
+               if (type_min == 'A') {
+                       for (i = 0; i < num_play; i++)
+                               if (i != player)
+                                       play[i].money -= num;
+                       num = num * (num_play - 1);
+               }
+               cur_p->money += num;
+               break;
+         case '-':             /* lose money           */
+               if (type_min == 'A') {
+                       for (i = 0; i < num_play; i++)
+                               if (i != player)
+                                       play[i].money += num;
+                       num = num * (num_play - 1);
+               }
+               cur_p->money -= num;
+               break;
+         case 'M':             /* move somewhere       */
+               switch (type_min) {
+                 case 'F':             /* move forward */
+                       num -= cur_p->loc;
+                       if (num < 0)
+                               num += 40;
+                       break;
+                 case 'J':             /* move to jail */
+                       goto_jail();
+                       return;
+                 case 'R':             /* move to railroad     */
+                       spec = TRUE;
+                       num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc;
+                       break;
+                 case 'U':             /* move to utility      */
+                       spec = TRUE;
+                       if (cur_p->loc >= 12 && cur_p->loc < 28)
+                               num = 28 - cur_p->loc;
+                       else {
+                               num = 12 - cur_p->loc;
+                               if (num < 0)
+                                       num += 40;
+                       }
+                       break;
+                 case 'B':
+                       num = -num;
+                       break;
+               }
+               move(num);
+               break;
+         case 'T':                     /* tax                  */
+               if (dp == &CC_D) {
+                       per_h = 40;
+                       per_H = 115;
+               }
+               else {
+                       per_h = 25;
+                       per_H = 100;
+               }
+               num_h = num_H = 0;
+               for (op = cur_p->own_list; op; op = op->next)
+                       if (op->sqr->type == PRPTY) {
+                               if (op->sqr->desc->houses == 5)
+                                       ++num_H;
+                               else
+                                       num_h += op->sqr->desc->houses;
+                       }
+               num = per_h * num_h + per_H * num_H;
+               printf(
+                   "You had %d Houses and %d Hotels, so that cost you $%d\n",
+                   num_h, num_H, num);
+               if (num == 0)
+                       lucky("");
+               else
+                       cur_p->money -= num;
+               break;
+         case GOJF:            /* get-out-of-jail-free card    */
+               cur_p->num_gojf++;
+               dp->gojf_used = TRUE;
+               break;
+       }
+       spec = FALSE;
+}
+
+/*
+ *     This routine prints out the message on the card
+ */
+static void
+printmes(const char *text)
+{
+       int i;
+
+       printline();
+       fflush(stdout);
+       for (i = 0; text[i] != '\0'; i++)
+               putchar(text[i]);
+       printline();
+       fflush(stdout);
+}
+
+/*
+ *     This routine returns the players get-out-of-jail-free card
+ * to the bottom of a deck.  XXX currently does not return to the correct
+ * deck.
+ */
+void
+ret_card(PLAY *plr)
+{
+       char type_maj;
+       int gojfpos, last_card;
+       int i;
+       DECK *dp;
+       int temp;
+
+       plr->num_gojf--;
+       if (CC_D.gojf_used)
+               dp = &CC_D;
+       else
+               dp = &CH_D;
+       dp->gojf_used = FALSE;
+
+       /* Put at bottom of deck (top_card - 1) and remove it from wherever else
+        * it used to be.
+        */
+       last_card = dp->top_card - 1;
+       if (last_card < 0)
+               last_card += dp->num_cards;
+       gojfpos = dp->top_card;
+       do {
+               gojfpos = (gojfpos + 1) % dp->num_cards;
+               type_maj = dp->info[gojfpos].actioncode[0];
+       } while (type_maj != GOJF);
+       temp = dp->cards[gojfpos];
+       /* Only one of the next two loops does anything */
+       for (i = gojfpos - 1; i > last_card; i--)
+               dp->cards[i + 1] = dp->cards[i];
+       for (i = gojfpos; i < last_card; i++)
+               dp->cards[i] = dp->cards[i + 1];
+       if (gojfpos > last_card) {
+               dp->cards[dp->top_card] = temp;
+               dp->top_card++;
+               dp->top_card %= dp->num_cards;
+       } else
+               dp->cards[last_card] = temp;
+}
diff --git a/games/monop/deck.h b/games/monop/deck.h
new file mode 100644 (file)
index 0000000..7e3f191
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: deck.h,v 1.9 2008/02/24 02:43:18 dholland 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. 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.
+ *
+ *     @(#)deck.h      8.1 (Berkeley) 5/31/93
+ */
+
+#include <sys/types.h>
+
+#define        bool    char
+
+struct cardinfo; /* private to cards.c */
+
+#define        CC_D    deck[0]
+#define        CH_D    deck[1]
+
+struct dk_st {                 /* deck description structure           */
+       int     num_cards;              /* number of cards in deck      */
+       int     top_card;               /* number of last card picked   */
+       bool    gojf_used;              /* set if gojf card out of deck */
+       int     *cards;                 /* which cards (indexes info[]) */
+       const struct cardinfo *info;    /* the static card data */
+};
+
+typedef struct dk_st   DECK;
+
+extern DECK    deck[2];
+
+/* cards.c */
+void init_decks(void);
+void get_card(DECK *);
+
diff --git a/games/monop/execute.c b/games/monop/execute.c
new file mode 100644 (file)
index 0000000..3466c7e
--- /dev/null
@@ -0,0 +1,761 @@
+/*     $NetBSD: execute.c,v 1.22 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)execute.c  8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: execute.c,v 1.22 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "deck.h"
+#include "monop.h"
+
+#define MIN_FORMAT_VERSION 1
+#define CUR_FORMAT_VERSION 1
+#define MAX_FORMAT_VERSION 1
+
+typedef        struct stat     STAT;
+typedef        struct tm       TIME;
+
+static char    buf[257];
+
+static bool    new_play;       /* set if move on to new player         */
+
+static void show_move(void);
+
+static void restore_reset(void);
+static int restore_parseline(char *txt);
+static int restore_toplevel_attr(const char *attribute, char *txt);
+static int restore_player_attr(const char *attribute, char *txt);
+static int restore_deck_attr(const char *attribute, char *txt);
+static int restore_square_attr(const char *attribute, char *txt);
+static int getnum(const char *what, char *txt, int min, int max, int *ret);
+static int getnum_withbrace(const char *what, char *txt, int min, int max,
+               int *ret);
+
+/*
+ *     This routine executes the given command by index number
+ */
+void
+execute(int com_num)
+{
+       new_play = FALSE;       /* new_play is true if fixing   */
+       (*func[com_num])();
+       notify();
+       force_morg();
+       if (new_play)
+               next_play();
+       else if (num_doub)
+               printf("%s rolled doubles.  Goes again\n", cur_p->name);
+}
+
+/*
+ *     This routine moves a piece around.
+ */
+void
+do_move(void)
+{
+       int r1, r2;
+       bool was_jail;
+
+       new_play = was_jail = FALSE;
+       printf("roll is %d, %d\n", r1=roll(1, 6), r2=roll(1, 6));
+       if (cur_p->loc == JAIL) {
+               was_jail++;
+               if (!move_jail(r1, r2)) {
+                       new_play++;
+                       goto ret;
+               }
+       }
+       else {
+               if (r1 == r2 && ++num_doub == 3) {
+                       printf("That's 3 doubles.  You go to jail\n");
+                       goto_jail();
+                       new_play++;
+                       goto ret;
+               }
+               move(r1+r2);
+       }
+       if (r1 != r2 || was_jail)
+               new_play++;
+ret:
+       return;
+}
+
+/*
+ *     This routine moves a normal move
+ */
+void
+move(int rl)
+{
+       int old_loc;
+
+       old_loc = cur_p->loc;
+       cur_p->loc = (cur_p->loc + rl) % N_SQRS;
+       if (cur_p->loc < old_loc && rl > 0) {
+               cur_p->money += 200;
+               printf("You pass %s and get $200\n", board[0].name);
+       }
+       show_move();
+}
+
+/*
+ *     This routine shows the results of a move
+ */
+static void
+show_move(void)
+{
+       SQUARE *sqp;
+
+       sqp = &board[cur_p->loc];
+       printf("That puts you on %s\n", sqp->name);
+       switch (sqp->type) {
+         case SAFE:
+               printf("That is a safe place\n");
+               break;
+         case CC:
+               cc();
+               break;
+         case CHANCE:
+               chance();
+               break;
+         case INC_TAX:
+               inc_tax();
+               break;
+         case GOTO_J:
+               goto_jail();
+               break;
+         case LUX_TAX:
+               lux_tax();
+               break;
+         case PRPTY:
+         case RR:
+         case UTIL:
+               if (sqp->owner < 0) {
+                       printf("That would cost $%d\n", sqp->cost);
+                       if (getyn("Do you want to buy? ") == 0) {
+                               buy(player, sqp);
+                               cur_p->money -= sqp->cost;
+                       }
+                       else if (num_play > 2)
+                               bid();
+               }
+               else if (sqp->owner == player)
+                       printf("You own it.\n");
+               else
+                       rent(sqp);
+       }
+}
+
+/*
+ * Reset the game state.
+ */
+static void
+reset_game(void)
+{
+       int i;
+
+       for (i = 0; i < N_SQRS; i++) {
+               board[i].owner = -1;
+               if (board[i].type == PRPTY) {
+                       board[i].desc->morg = 0;
+                       board[i].desc->houses = 0;
+               } else if (board[i].type == RR || board[i].type == UTIL) {
+                       board[i].desc->morg = 0;
+               }
+       }
+
+       for (i = 0; i < 2; i++) {
+               deck[i].top_card = 0;
+               deck[i].gojf_used = FALSE;
+       }
+
+       if (play) {
+               for (i = 0; i < num_play; i++) {
+                       free(play[i].name);
+                       play[i].name = NULL;
+               }
+               free(play);
+               play = NULL;
+       }
+
+       for (i = 0; i < MAX_PL+2; i++) {
+               name_list[i] = NULL;
+       }
+
+       cur_p = NULL;
+       num_play = 0;
+       player = 0;
+       num_doub = 0;
+       fixing = FALSE;
+       trading = FALSE;
+       told_em = FALSE;
+       spec = FALSE;
+}
+
+
+/*
+ *     This routine saves the current game for use at a later date
+ */
+void
+save(void)
+{
+       char *sp;
+       FILE *outf;
+       time_t t;
+       struct stat sb;
+       int i, j;
+
+       printf("Which file do you wish to save it in? ");
+       fgets(buf, sizeof(buf), stdin);
+       if (feof(stdin))
+               return;
+       sp = strchr(buf, '\n');
+       if (sp)
+               *sp = '\0';
+
+       /*
+        * check for existing files, and confirm overwrite if needed
+        */
+
+       if (stat(buf, &sb) == 0
+           && getyn("File exists.  Do you wish to overwrite? ") > 0)
+               return;
+
+       outf = fopen(buf, "w");
+       if (outf == NULL) {
+               warn("%s", buf);
+               return;
+       }
+       printf("\"%s\" ", buf);
+       time(&t);                       /* get current time             */
+
+       /* Header */
+       fprintf(outf, "NetBSD monop format v%d\n", CUR_FORMAT_VERSION);
+       fprintf(outf, "time %s", ctime(&t));  /* ctime includes a \n */
+       fprintf(outf, "numplayers %d\n", num_play);
+       fprintf(outf, "currentplayer %d\n", player);
+       fprintf(outf, "doubles %d\n", num_doub);
+
+       /* Players */
+       for (i = 0; i < num_play; i++) {
+               fprintf(outf, "player %d {\n", i);
+               fprintf(outf, "    name %s\n", name_list[i]);
+               fprintf(outf, "    money %d\n", play[i].money);
+               fprintf(outf, "    loc %d\n", play[i].loc);
+               fprintf(outf, "    num_gojf %d\n", play[i].num_gojf);
+               fprintf(outf, "    in_jail %d\n", play[i].in_jail);
+               fprintf(outf, "}\n");
+       }
+
+       /* Decks */
+       for (i = 0; i < 2; i++) {
+               fprintf(outf, "deck %d {\n", i);
+               fprintf(outf, "    numcards %d\n", deck[i].num_cards);
+               fprintf(outf, "    topcard %d\n", deck[i].top_card);
+               fprintf(outf, "    gojf_used %d\n", deck[i].gojf_used);
+               fprintf(outf, "    cards");
+               for (j = 0; j < deck[i].num_cards; j++)
+                       fprintf(outf, " %d", deck[i].cards[j]);
+               fprintf(outf, "\n");
+               fprintf(outf, "}\n");
+       }
+
+       /* Board */
+       for (i = 0; i < N_SQRS; i++) {
+               fprintf(outf, "square %d {\n", i);
+               fprintf(outf, "owner %d\n", board[i].owner);
+               if (board[i].owner < 0) {
+                       /* nothing */
+               } else if (board[i].type == PRPTY) {
+                       fprintf(outf, "morg %d\n", board[i].desc->morg);
+                       fprintf(outf, "houses %d\n", board[i].desc->houses);
+               } else if (board[i].type == RR || board[i].type == UTIL) {
+                       fprintf(outf, "morg %d\n", board[i].desc->morg);
+               }
+               fprintf(outf, "}\n");
+       }
+       if (ferror(outf) || fflush(outf))
+               warnx("write error");
+       fclose(outf);
+
+       strcpy(buf, ctime(&t));
+       for (sp = buf; *sp != '\n'; sp++)
+               continue;
+       *sp = '\0';
+       printf("[%s]\n", buf);
+}
+
+/*
+ *     This routine restores an old game from a file
+ */
+void
+restore(void)
+{
+       char *sp;
+
+       for (;;) {
+               printf("Which file do you wish to restore from? ");
+               fgets(buf, sizeof(buf), stdin);
+               if (feof(stdin))
+                       return;
+               sp = strchr(buf, '\n');
+               if (sp)
+                       *sp = '\0';
+               if (rest_f(buf) == 0)
+                       break;
+       }
+}
+
+/*
+ * This does the actual restoring.  It returns zero on success,
+ * and -1 on failure.
+ */
+int
+rest_f(const char *file)
+{
+       char *sp;
+       FILE *inf;
+       char xbuf[80];
+       STAT sbuf;
+       char readbuf[512];
+       int ret = 0;
+
+       inf = fopen(file, "r");
+       if (inf == NULL) {
+               warn("%s", file);
+               return -1;
+       }
+       printf("\"%s\" ", file);
+       if (fstat(fileno(inf), &sbuf) < 0) {
+               err(1, "%s: fstat", file);
+       }
+
+       /* Clear the game state to prevent brokenness on misordered files. */
+       reset_game();
+
+       /* Reset the parser */
+       restore_reset();
+
+       /* Note: can't use buf[], file might point at it. (Lame...) */
+       while (fgets(readbuf, sizeof(readbuf), inf)) {
+               /*
+                * The input buffer is long enough to handle anything
+                * that's supposed to be in the output buffer, so if
+                * we get a partial line, complain.
+                */
+               sp = strchr(readbuf, '\n');
+               if (sp == NULL) {
+                       printf("file is corrupt: long lines.\n");
+                       ret = -1;
+                       break;
+               }
+               *sp = '\0';
+
+               if (restore_parseline(readbuf)) {
+                       ret = -1;
+                       break;
+               }
+       }
+
+       if (ferror(inf))
+               warnx("%s: read error", file);
+       fclose(inf);
+
+       if (ret < 0)
+               return -1;
+
+       name_list[num_play] = "done";
+
+       if (play == NULL || cur_p == NULL || num_play < 2) {
+               printf("save file is incomplete.\n");
+               return -1;
+       }
+
+       /*
+        * We could at this point crosscheck the following:
+        *    - there are only two GOJF cards floating around
+        *    - total number of houses and hotels does not exceed maximums
+        *    - no props are both built and mortgaged
+        * but for now we don't.
+        */
+
+       strcpy(xbuf, ctime(&sbuf.st_mtime));
+       for (sp = xbuf; *sp != '\n'; sp++)
+               continue;
+       *sp = '\0';
+       printf("[%s]\n", xbuf);
+       return 0;
+}
+
+/*
+ * State of the restore parser
+ */
+static int restore_version;
+static enum {
+       RI_NONE,
+       RI_PLAYER,
+       RI_DECK,
+       RI_SQUARE
+} restore_item;
+static int restore_itemnum;
+
+/*
+ * Reset the restore parser
+ */
+static void
+restore_reset(void)
+{
+       restore_version = -1;
+       restore_item = RI_NONE;
+       restore_itemnum = -1;
+}
+
+/*
+ * Handle one line of the save file
+ */
+static int
+restore_parseline(char *txt)
+{
+       char *attribute;
+       char *s;
+
+       if (restore_version < 0) {
+               /* Haven't seen the header yet. Demand it right away. */
+               if (!strncmp(txt, "NetBSD monop format v", 21)) {
+                       return getnum("format version", txt+21,
+                                     MIN_FORMAT_VERSION,
+                                     MAX_FORMAT_VERSION,
+                                     &restore_version);
+               }
+               printf("file is not a monop save file.\n");
+               return -1;
+       }
+
+       /* Check for lines that are right braces. */
+       if (!strcmp(txt, "}")) {
+               if (restore_item == RI_NONE) {
+                       printf("mismatched close brace.\n");
+                       return -1;
+               }
+               restore_item = RI_NONE;
+               restore_itemnum = -1;
+               return 0;
+       }
+
+       /* Any other line must begin with a word, which is the attribute. */
+       s = txt;
+       while (*s==' ')
+               s++;
+       attribute = s;
+       s = strchr(attribute, ' ');
+       if (s == NULL) {
+               printf("file is corrupt: attribute %s lacks value.\n",
+                   attribute);
+               return -1;
+       }
+       *(s++) = '\0';
+       while (*s==' ')
+               s++;
+       /* keep the remaining text for further handling */
+       txt = s;
+
+       switch (restore_item) {
+           case RI_NONE:
+               /* toplevel attributes */
+               return restore_toplevel_attr(attribute, txt);
+
+           case RI_PLAYER:
+               /* player attributes */
+               return restore_player_attr(attribute, txt);
+
+           case RI_DECK:
+               /* deck attributes */
+               return restore_deck_attr(attribute, txt);
+
+           case RI_SQUARE:
+               /* board square attributes */
+               return restore_square_attr(attribute, txt);
+       }
+       /* NOTREACHED */
+       printf("internal logic error\n");
+       return -1;
+}
+
+static int
+restore_toplevel_attr(const char *attribute, char *txt)
+{
+       if (!strcmp(attribute, "time")) {
+               /* nothing */
+       } else if (!strcmp(attribute, "numplayers")) {
+               if (getnum("numplayers", txt, 2, MAX_PL, &num_play) < 0) {
+                       return -1;
+               }
+               if (play != NULL) {
+                       printf("numplayers: multiple settings\n");
+                       return -1;
+               }
+               play = calloc((size_t)num_play, sizeof(play[0]));
+               if (play == NULL) {
+                       err(1, "calloc");
+               }
+       } else if (!strcmp(attribute, "currentplayer")) {
+               if (getnum("currentplayer", txt, 0, num_play-1, &player) < 0) {
+                       return -1;
+               }
+               if (play == NULL) {
+                       printf("currentplayer: before numplayers\n");
+                       return -1;
+               }
+               cur_p = &play[player];
+       } else if (!strcmp(attribute, "doubles")) {
+               if (getnum("doubles", txt, 0, 2, &num_doub) < 0) {
+                       return -1;
+               }
+       } else if (!strcmp(attribute, "player")) {
+               if (getnum_withbrace("player", txt, 0, num_play-1,
+                   &restore_itemnum) < 0) {
+                       return -1;
+               }
+               restore_item = RI_PLAYER;
+       } else if (!strcmp(attribute, "deck")) {
+               if (getnum_withbrace("deck", txt, 0, 1,
+                   &restore_itemnum) < 0) {
+                       return -1;
+               }
+               restore_item = RI_DECK;
+       } else if (!strcmp(attribute, "square")) {
+               if (getnum_withbrace("square", txt, 0, N_SQRS-1,
+                   &restore_itemnum) < 0) {
+                       return -1;
+               }
+               restore_item = RI_SQUARE;
+       } else {
+               printf("unknown attribute %s\n", attribute);
+               return -1;
+       }
+       return 0;
+}
+
+static int
+restore_player_attr(const char *attribute, char *txt)
+{
+       PLAY *pp;
+       int tmp;
+
+       if (play == NULL) {
+               printf("player came before numplayers.\n");
+               return -1;
+       }
+       pp = &play[restore_itemnum];
+
+       if (!strcmp(attribute, "name")) {
+               if (pp->name != NULL) {
+                       printf("player has multiple names.\n");
+                       return -1;
+               }
+               /* XXX should really systematize the max name length */
+               if (strlen(txt) > 256) {
+                       txt[256] = 0;
+               }
+               pp->name = strdup(txt);
+               if (pp->name == NULL)
+                       err(1, "strdup");
+               name_list[restore_itemnum] = pp->name;
+       } else if (!strcmp(attribute, "money")) {
+               if (getnum(attribute, txt, 0, INT_MAX, &pp->money) < 0) {
+                       return -1;
+               }
+       } else if (!strcmp(attribute, "loc")) {
+               /* note: not N_SQRS-1 */
+               if (getnum(attribute, txt, 0, N_SQRS, &tmp) < 0) {
+                       return -1;
+               }
+               pp->loc = tmp;
+       } else if (!strcmp(attribute, "num_gojf")) {
+               if (getnum(attribute, txt, 0, 2, &tmp) < 0) {
+                       return -1;
+               }
+               pp->num_gojf = tmp;
+       } else if (!strcmp(attribute, "in_jail")) {
+               if (getnum(attribute, txt, 0, 3, &tmp) < 0) {
+                       return -1;
+               }
+               pp->in_jail = tmp;
+               if (pp->in_jail > 0 && pp->loc != JAIL) {
+                       printf("player escaped from jail?\n");
+                       return -1;
+               }
+       } else {
+               printf("unknown attribute %s\n", attribute);
+               return -1;
+       }
+       return 0;
+}
+
+static int
+restore_deck_attr(const char *attribute, char *txt)
+{
+       int tmp, j;
+       char *s;
+       DECK *dp;
+
+       dp = &deck[restore_itemnum];
+
+       if (!strcmp(attribute, "numcards")) {
+               if (getnum(attribute, txt, dp->num_cards, dp->num_cards,
+                   &tmp) < 0) {
+                       return -1;
+               }
+       } else if (!strcmp(attribute, "topcard")) {
+               if (getnum(attribute, txt, 0, dp->num_cards,
+                   &dp->top_card) < 0) {
+                       return -1;
+               }
+       } else if (!strcmp(attribute, "gojf_used")) {
+               if (getnum(attribute, txt, 0, 1, &tmp) < 0) {
+                       return -1;
+               }
+               dp->gojf_used = tmp;
+       } else if (!strcmp(attribute, "cards")) {
+               errno = 0;
+               s = txt;
+               for (j = 0; j<dp->num_cards; j++) {
+                       tmp = strtol(s, &s, 10);
+                       if (tmp < 0 || tmp >= dp->num_cards) {
+                               printf("cards: out of range value\n");
+                               return -1;
+                       }
+                       dp->cards[j] = tmp;
+               }
+               if (errno) {
+                       printf("cards: invalid values\n");
+                       return -1;
+               }
+       } else {
+               printf("unknown attribute %s\n", attribute);
+               return -1;
+       }
+       return 0;
+}
+
+static int
+restore_square_attr(const char *attribute, char *txt)
+{
+       SQUARE *sp = &board[restore_itemnum];
+       int tmp;
+
+       if (!strcmp(attribute, "owner")) {
+               if (getnum(attribute, txt, -1, num_play-1, &tmp) < 0) {
+                       return -1;
+               }
+               sp->owner = tmp;
+               if (tmp >= 0)
+                       add_list(tmp, &play[tmp].own_list, restore_itemnum);
+       } else if (!strcmp(attribute, "morg")) {
+               if (sp->type != PRPTY && sp->type != RR && sp->type != UTIL) {
+                       printf("unownable property is mortgaged.\n");
+                       return -1;
+               }
+               if (getnum(attribute, txt, 0, 1, &tmp) < 0) {
+                       return -1;
+               }
+               sp->desc->morg = tmp;
+       } else if (!strcmp(attribute, "houses")) {
+               if (sp->type != PRPTY) {
+                       printf("unbuildable property has houses.\n");
+                       return -1;
+               }
+               if (getnum(attribute, txt, 0, 5, &tmp) < 0) {
+                       return -1;
+               }
+               sp->desc->houses = tmp;
+       } else {
+               printf("unknown attribute %s\n", attribute);
+               return -1;
+       }
+       return 0;
+}
+
+static int
+getnum(const char *what, char *txt, int min, int max, int *ret)
+{
+       char *s;
+       long l;
+
+       errno = 0;
+       l = strtol(txt, &s, 10);
+       if (errno || strlen(s)>0) {
+               printf("%s: not a number.\n", what);
+               return -1;
+       }
+       if (l < min || l > max) {
+               printf("%s: out of range.\n", what);
+       }
+       *ret = l;
+       return 0;
+}
+
+static int
+getnum_withbrace(const char *what, char *txt, int min, int max, int *ret)
+{
+       char *s;
+       s = strchr(txt, ' ');
+       if (s == NULL) {
+               printf("%s: expected open brace\n", what);
+               return -1;
+       }
+       *(s++) = '\0';
+       while (*s == ' ')
+               s++;
+       if (*s != '{') {
+               printf("%s: expected open brace\n", what);
+               return -1;
+       }
+       if (s[1] != 0) {
+               printf("%s: garbage after open brace\n", what);
+               return -1;
+       }
+       return getnum(what, txt, min, max, ret);
+}
diff --git a/games/monop/getinp.c b/games/monop/getinp.c
new file mode 100644 (file)
index 0000000..3d0dc63
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $NetBSD: getinp.c,v 1.19 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)getinp.c   8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: getinp.c,v 1.19 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "monop.h"
+
+#define        LINE    70
+
+static char    buf[257];
+
+static int comp(const char *);
+
+int
+getinp(const char *prompt, const char *const lst [])
+{
+       int i, n_match, match = 0;
+       char *sp;
+
+       for (;;) {
+               printf("%s", prompt);
+               fgets(buf, sizeof(buf), stdin);
+               if (feof(stdin)) {
+                       return 0;
+               }
+               if (buf[0] == '?' && buf[1] == '\n') {
+                       printf("Valid inputs are: ");
+                       for (i = 0, match = 18; lst[i]; i++) {
+                               if ((match+=(n_match=strlen(lst[i]))) > LINE) {
+                                       printf("\n\t");
+                                       match = n_match + 8;
+                               }
+                               if (*lst[i] == '\0') {
+                                       match += 8;
+                                       printf("<RETURN>");
+                               }
+                               else
+                                       printf("%s", lst[i]);
+                               if (lst[i+1])
+                                       printf(", ");
+                               else
+                                       putchar('\n');
+                               match += 2;
+                       }
+                       continue;
+               }
+               if ((sp = strchr(buf, '\n')) != NULL)
+                       *sp = '\0';
+               for (sp = buf; *sp; sp++)
+                       *sp = tolower((unsigned char)*sp);
+               for (i = n_match = 0; lst[i]; i++)
+                       if (comp(lst[i])) {
+                               n_match++;
+                               match = i;
+                       }
+               if (n_match == 1)
+                       return match;
+               else if (buf[0] != '\0')
+                       printf("Illegal response: \"%s\".  "
+                           "Use '?' to get list of valid answers\n", buf);
+       }
+}
+
+static int
+comp(const char *s1)
+{
+       const char *sp, *tsp;
+       char c;
+
+       if (buf[0] != '\0')
+               for (sp = buf, tsp = s1; *sp; ) {
+                       c = tolower((unsigned char)*tsp);
+                       tsp++;
+                       if (c != *sp++)
+                               return 0;
+               }
+       else if (*s1 != '\0')
+               return 0;
+       return 1;
+}
diff --git a/games/monop/houses.c b/games/monop/houses.c
new file mode 100644 (file)
index 0000000..ce313cc
--- /dev/null
@@ -0,0 +1,387 @@
+/*     $NetBSD: houses.c,v 1.15 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)houses.c   8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: houses.c,v 1.15 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+static const char      *names[N_MON+2];
+static char    cur_prop[80];
+
+static MON     *monops[N_MON];
+
+static void buy_h(MON *);
+static void sell_h(MON *);
+static void list_cur(MON *);
+static int get_avail_houses(void);
+static int get_avail_hotels(void);
+static bool ready_for_hotels(MON *);
+
+/*
+ *     These routines deal with buying and selling houses
+ */
+void
+buy_houses(void)
+{
+       int num_mon;
+       MON *mp;
+       OWN *op;
+       bool good, got_morg;
+       int i,p;
+
+over:
+       num_mon = 0;
+       good = TRUE;
+       got_morg = FALSE;
+       for (op = cur_p->own_list; op && op->sqr->type != PRPTY; op = op->next)
+               continue;
+       while (op)
+               if (op->sqr->desc->monop) {
+                       mp = op->sqr->desc->mon_desc;
+                       names[num_mon] = (monops[num_mon]=mp)->name;
+                       num_mon++;
+                       got_morg = good = FALSE;
+                       for (i = 0; i < mp->num_in; i++) {
+                               if (op->sqr->desc->morg)
+                                       got_morg = TRUE;
+                               if (op->sqr->desc->houses != 5)
+                                       good = TRUE;
+                               op = op->next;
+                       }
+                       if (!good || got_morg)
+                               --num_mon;
+               }
+               else
+                       op = op->next;
+       if (num_mon == 0) {
+               if (got_morg)
+                       printf("You can't build on mortgaged monopolies.\n");
+               else if (!good)
+                       printf("You can't build any more.\n");
+               else
+                       printf("But you don't have any monopolies!!\n");
+               return;
+       }
+       if (num_mon == 1)
+               buy_h(monops[0]);
+       else {
+               names[num_mon++] = "done";
+               names[num_mon--] = 0;
+               if ((p = getinp(
+                   "Which property do you wish to buy houses for? ",
+                   names)) == num_mon)
+                       return;
+               buy_h(monops[p]);
+               goto over;
+       }
+}
+
+static void
+buy_h(MON *mnp)
+{
+       int i;
+       MON *mp;
+       int price;
+       short input[3], result[3];
+       int wanted_houses, wanted_hotels;
+       int total_purchase;
+       PROP *pp;
+       int avail_houses, avail_hotels;
+       bool buying_hotels;
+
+       mp = mnp;
+       price = mp->h_cost * 50;
+
+       avail_houses = get_avail_houses();
+       avail_hotels = get_avail_hotels();
+       buying_hotels = ready_for_hotels(mnp);
+
+       if (avail_houses == 0 && !buying_hotels) {
+               printf("Building shortage:  no houses available.");
+               return;
+       }
+       if (avail_hotels == 0 && buying_hotels) {
+               printf("Building shortage:  no hotels available.");
+               return;
+       }
+
+blew_it:
+       list_cur(mp);
+       printf("Houses will cost $%d\n", price);
+       printf("How many houses do you wish to buy for\n");
+       for (i = 0; i < mp->num_in; i++) {
+               pp = mp->sq[i]->desc;
+over:
+               if (pp->houses == 5) {
+                       printf("%s (H):\n", mp->sq[i]->name);
+                       input[i] = 0;
+                       result[i] = 5;
+                       continue;
+               }
+               (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ",
+                       mp->sq[i]->name, pp->houses);
+               input[i] = get_int(cur_prop);
+               result[i] = input[i] + pp->houses;
+               if (result[i] > 5 || result[i] < 0) {
+                       printf("That's too many.  The most you can buy is %d\n",
+                           5 - pp->houses);
+                               goto over;
+                       }
+       }
+       if (mp->num_in == 3 &&
+           (abs(result[0] - result[1]) > 1 ||
+           abs(result[0] - result[2]) > 1 ||
+            abs(result[1] - result[2]) > 1)) {
+err:           printf("That makes the spread too wide.  Try again\n");
+               goto blew_it;
+       }
+       else if (mp->num_in == 2 && abs(result[0] - result[1]) > 1)
+               goto err;
+
+       wanted_houses = 0;
+       wanted_hotels = 0;
+       total_purchase = 0;
+
+       for (i = 0; i < mp->num_in; i++) {
+               wanted_houses += input[i];
+               total_purchase += input[i];
+               if (result[i] == 5 && input[i] > 0) {
+                       wanted_hotels++;
+                       wanted_houses--;
+               }
+       }
+       if (wanted_houses > avail_houses) {
+               printf("You have asked for %d %s but only %d are available.  "
+                   "Try again\n",
+                   wanted_houses, wanted_houses == 1 ? "house" : "houses",
+                   avail_houses);
+               goto blew_it;
+       } else if (wanted_hotels > avail_hotels) {
+               printf("You have asked for %d %s but only %d are available.  "
+                   "Try again\n",
+                   wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels",
+                   avail_hotels);
+               goto blew_it;
+       }
+
+       if (total_purchase) {
+               printf("You asked for %d %s and %d %s for $%d\n",
+                   wanted_houses, wanted_houses == 1 ? "house" : "houses",
+                   wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels",
+                   total_purchase * price);
+               if (getyn("Is that ok? ") == 0) {
+                       cur_p->money -= total_purchase * price;
+                       for (i = 0; i < mp->num_in; i++)
+                               mp->sq[i]->desc->houses = result[i];
+               }
+       }
+}
+
+/*
+ *     This routine sells houses.
+ */
+void
+sell_houses(void)
+{
+       int num_mon;
+       MON *mp;
+       OWN *op;
+       bool good;
+       int p;
+
+over:
+       num_mon = 0;
+       good = TRUE;
+       for (op = cur_p->own_list; op;)
+               if (op->sqr->type == PRPTY && op->sqr->desc->monop) {
+                       mp = op->sqr->desc->mon_desc;
+                       names[num_mon] = (monops[num_mon]=mp)->name;
+                       num_mon++;
+                       good = 0;
+                       do
+                               if (!good && op->sqr->desc->houses != 0)
+                                       good = TRUE;
+                       while (op->next && op->sqr->desc->mon_desc == mp
+                           && (op = op->next));
+                       if (!good)
+                               --num_mon;
+               } else
+                       op = op->next;
+       if (num_mon == 0) {
+               printf("You don't have any houses to sell!!\n");
+               return;
+       }
+       if (num_mon == 1)
+               sell_h(monops[0]);
+       else {
+               names[num_mon++] = "done";
+               names[num_mon--] = 0;
+               if ((p = getinp(
+                   "Which property do you wish to sell houses from? ",
+                   names)) == num_mon)
+                       return;
+               sell_h(monops[p]);
+               notify();
+               goto over;
+       }
+}
+
+static void
+sell_h(MON *mnp)
+{
+       int i;
+       MON *mp;
+       int price;
+       short input[3],temp[3];
+       int tot;
+       PROP *pp;
+
+       mp = mnp;
+       price = mp->h_cost * 25;
+blew_it:
+       printf("Houses will get you $%d apiece\n", price);
+       list_cur(mp);
+       printf("How many houses do you wish to sell from\n");
+       for (i = 0; i < mp->num_in; i++) {
+               pp = mp->sq[i]->desc;
+over:
+               if (pp->houses == 0) {
+                       printf("%s (0):\n", mp->sq[i]->name);
+                       input[i] = temp[i] = 0;
+                       continue;
+               }
+               if (pp->houses < 5)
+                       (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ",
+                               mp->sq[i]->name,pp->houses);
+               else
+                       (void)snprintf(cur_prop, sizeof(cur_prop), "%s (H): ",
+                               mp->sq[i]->name);
+               input[i] = get_int(cur_prop);
+               temp[i] = pp->houses - input[i];
+               if (temp[i] < 0) {
+                       printf(
+                           "That's too many.  The most you can sell is %d\n",
+                           pp->houses);
+                               goto over;
+                       }
+       }
+       if (mp->num_in == 3 && (abs(temp[0] - temp[1]) > 1 ||
+           abs(temp[0] - temp[2]) > 1 || abs(temp[1] - temp[2]) > 1)) {
+err:           printf("That makes the spread too wide.  Try again\n");
+               goto blew_it;
+       }
+       else if (mp->num_in == 2 && abs(temp[0] - temp[1]) > 1)
+               goto err;
+       for (tot = i = 0; i < mp->num_in; i++)
+               tot += input[i];
+       if (tot) {
+               printf("You asked to sell %d house%s for $%d\n", tot,
+                   tot == 1 ? "" : "s", tot * price);
+               if (getyn("Is that ok? ") == 0) {
+                       cur_p->money += tot * price;
+                       for (tot = i = 0; i < mp->num_in; i++)
+                               mp->sq[i]->desc->houses = temp[i];
+               }
+       }
+}
+
+static void
+list_cur(MON *mp)
+{
+       int i;
+       SQUARE *sqp;
+
+       for (i = 0; i < mp->num_in; i++) {
+               sqp = mp->sq[i];
+               if (sqp->desc->houses == 5)
+                       printf("%s (H) ", sqp->name);
+               else
+                       printf("%s (%d) ", sqp->name, sqp->desc->houses);
+       }
+       putchar('\n');
+}
+
+static int
+get_avail_houses(void)
+{
+       int i, c;
+       SQUARE *sqp;
+
+       c = 0;
+       for (i = 0; i < N_SQRS; i++) {
+               sqp = &board[i];
+               if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) {
+                       if (sqp->desc->houses < 5 && sqp->desc->houses > 0)
+                               c += sqp->desc->houses;
+               }
+       }
+       return(N_HOUSE - c);
+}
+
+static int
+get_avail_hotels(void)
+{
+       int i, c;
+       SQUARE *sqp;
+
+       c = 0;
+       for (i = 0; i < N_SQRS; i++) {
+               sqp = &board[i];
+               if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) {
+                       if (sqp->desc->houses == 5)
+                               c++;
+               }
+       }
+       return(N_HOTEL - c);
+}
+
+/*
+ * If we can put a hotel on, we can't put any houses on, and if we can
+ * put houses on, then we can't put a hotel on yet.
+ */
+static bool
+ready_for_hotels(MON *mp)
+{
+       int i;
+
+       for (i = 0; i < mp->num_in; i++) {
+               if (mp->sq[i]->desc->houses < 4)
+                       return(FALSE);
+       }
+       return(TRUE);
+}
diff --git a/games/monop/jail.c b/games/monop/jail.c
new file mode 100644 (file)
index 0000000..62b9ea0
--- /dev/null
@@ -0,0 +1,123 @@
+/*     $NetBSD: jail.c,v 1.10 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)jail.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: jail.c,v 1.10 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+/*
+ *     This routine uses a get-out-of-jail-free card to get the
+ * player out of jail.
+ */
+void
+card(void)
+{
+       if (cur_p->loc != JAIL) {
+               printf("But you're not IN Jail\n");
+               return;
+       }
+       if (cur_p->num_gojf == 0) {
+               printf("But you don't HAVE a get out of jail free card\n");
+               return;
+       }
+       ret_card(cur_p);
+       cur_p->loc = 10;                        /* just visiting        */
+       cur_p->in_jail = 0;
+}
+
+/*
+ *     This routine deals with paying your way out of jail.
+ */
+void
+pay(void)
+{
+       if (cur_p->loc != JAIL) {
+               printf("But you're not IN Jail\n");
+               return;
+       }
+       cur_p->loc = 10;
+       cur_p->money -= 50;
+       cur_p->in_jail = 0;
+       printf("That cost you $50\n");
+}
+
+/*
+ *     This routine deals with a move in jail
+ */
+int
+move_jail(int r1, int r2)
+{
+       if (r1 != r2) {
+               printf("Sorry, that doesn't get you out\n");
+               if (++(cur_p->in_jail) == 3) {
+                       printf("It's your third turn and you didn't roll "
+                           "doubles.  You have to pay $50\n");
+                       cur_p->money -= 50;
+moveit:
+                       cur_p->loc = 10;
+                       cur_p->in_jail = 0;
+                       move(r1+r2);
+                       r1 = r2 - 1;    /* kludge: stop new roll w/doub */
+                       return TRUE;
+               }
+               return FALSE;
+       } else {
+               printf("Double roll gets you out.\n");
+               goto moveit;
+       }
+}
+
+void
+printturn(void)
+{
+       if (cur_p->loc != JAIL)
+               return;
+       printf("(This is your ");
+       switch (cur_p->in_jail) {
+         case 0:
+               printf("1st");
+               break;
+         case 1:
+               printf("2nd");
+               break;
+         case 2:
+               printf("3rd (and final)");
+               break;
+       }
+       printf(" turn in JAIL)\n");
+}
diff --git a/games/monop/misc.c b/games/monop/misc.c
new file mode 100644 (file)
index 0000000..aaa9eb3
--- /dev/null
@@ -0,0 +1,299 @@
+/*     $NetBSD: misc.c,v 1.23 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)misc.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: misc.c,v 1.23 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <ctype.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "monop.h"
+
+static void is_monop(MON *, int);
+
+/*
+ *     This routine executes a truncated set of commands until a
+ * "yes or "no" answer is gotten.
+ */
+int
+getyn(const char *prompt)
+{
+       int com;
+
+       for (;;)
+               if ((com=getinp(prompt, yncoms)) < 2)
+                       return com;
+               else
+                       (*func[com-2])();
+}
+
+/*
+ *     This routine tells the player if he's out of money.
+ */
+void
+notify(void)
+{
+       if (cur_p->money < 0)
+               printf("That leaves you $%d in debt\n", -cur_p->money);
+       else if (cur_p->money == 0)
+               printf("that leaves you broke\n");
+       else if (fixing && !told_em && cur_p->money > 0) {
+               printf("-- You are now Solvent ---\n");
+               told_em = TRUE;
+       }
+}
+
+/*
+ *     This routine switches to the next player
+ */
+void
+next_play(void)
+{
+       player = (player + 1) % num_play;
+       cur_p = &play[player];
+       num_doub = 0;
+}
+
+/*
+ *     This routine gets an integer from the keyboard after the
+ * given prompt.
+ */
+int
+get_int(const char *prompt)
+{
+       long num;
+       char *sp;
+       char buf[257];
+
+       for (;;) {
+               printf("%s", prompt);
+               fgets(buf, sizeof(buf), stdin);
+               /* if stdin is closed we cant really play anymore */
+               if (feof(stdin))
+                       quit();
+               sp = strchr(buf, '\n');
+               if (sp)
+                       *sp = '\0';
+               errno = 0;
+               num = strtol(buf, &sp, 10);
+               if (errno || strlen(sp) > 0 || num < 0 || num >= INT_MAX) {
+                       printf("I can't understand that\n");
+                       continue;
+               }
+               return num;
+       }
+}
+
+/*
+ *     This routine sets the monopoly flag from the list given.
+ */
+void
+set_ownlist(int pl)
+{
+       int num;                /* general counter              */
+       MON *orig;              /* remember starting monop ptr  */
+       OWN *op;                /* current owned prop           */
+       OWN *orig_op;           /* original prop before loop    */
+
+       op = play[pl].own_list;
+#ifdef DEBUG
+       printf("op [%p] = play[pl [%d] ].own_list;\n", op, pl);
+#endif
+       while (op) {
+#ifdef DEBUG
+               printf("op->sqr->type = %d\n", op->sqr->type);
+#endif
+               switch (op->sqr->type) {
+                 case UTIL:
+#ifdef DEBUG
+                       printf("  case UTIL:\n");
+#endif
+                       for (num = 0; op && op->sqr->type == UTIL;
+                           op = op->next)
+                               num++;
+                       play[pl].num_util = num;
+#ifdef DEBUG
+                       printf("play[pl].num_util = num [%d];\n", num);
+#endif
+                       break;
+                 case RR:
+#ifdef DEBUG
+                       printf("  case RR:\n");
+#endif
+                       for (num = 0; op && op->sqr->type == RR;
+                           op = op->next) {
+#ifdef DEBUG
+                               printf("iter: %d\n", num);
+                               printf("op = %p, op->sqr = %p, "
+                                   "op->sqr->type = %d\n", op, op->sqr,
+                                   op->sqr->type);
+#endif
+                               num++;
+                       }
+                       play[pl].num_rr = num;
+#ifdef DEBUG
+                       printf("play[pl].num_rr = num [%d];\n", num);
+#endif
+                       break;
+                 case PRPTY:
+#ifdef DEBUG
+                       printf("  case PRPTY:\n");
+#endif
+                       orig = op->sqr->desc->mon_desc;
+                       orig_op = op;
+                       num = 0;
+                       while (op && op->sqr->desc->mon_desc == orig) {
+#ifdef DEBUG
+                               printf("iter: %d\n", num);
+#endif
+                               num++;
+#ifdef DEBUG
+                               printf("op = op->next ");
+#endif
+                               op = op->next;
+#ifdef DEBUG
+                               printf("[%p];\n", op);
+#endif
+                       }
+#ifdef DEBUG
+                       printf("num = %d\n", num);
+#endif
+                       if (orig == NULL) {
+                               printf("panic:  bad monopoly descriptor: "
+                                   "orig = %p\n", orig);
+                               printf("player # %d\n", pl+1);
+                               printhold(pl);
+                               printf("orig_op = %p\n", orig_op);
+                               if (orig_op) {
+                                       printf("orig_op->sqr->type = %d (PRPTY)\n",
+                                           orig_op->sqr->type);
+                                       printf("orig_op->next = %p\n",
+                                           orig_op->next);
+                                       printf("orig_op->sqr->desc = %p\n",
+                                           orig_op->sqr->desc);
+                               }
+                               printf("op = %p\n", op);
+                               if (op) {
+                                       printf("op->sqr->type = %d (PRPTY)\n",
+                                           op->sqr->type);
+                                       printf("op->next = %p\n", op->next);
+                                       printf("op->sqr->desc = %p\n",
+                                           op->sqr->desc);
+                               }
+                               printf("num = %d\n", num);
+                               exit(1);
+                       }
+#ifdef DEBUG
+                       printf("orig->num_in = %d\n", orig->num_in);
+#endif
+                       if (num == orig->num_in)
+                               is_monop(orig, pl);
+                       else
+                               is_not_monop(orig);
+                       break;
+               }
+       }
+}
+
+/*
+ *     This routine sets things up as if it is a new monopoly
+ */
+static void
+is_monop(MON *mp, int pl)
+{
+       int i;
+
+       mp->owner = pl;
+       mp->num_own = mp->num_in;
+       for (i = 0; i < mp->num_in; i++)
+               mp->sq[i]->desc->monop = TRUE;
+       mp->name = mp->mon_n;
+}
+
+/*
+ *     This routine sets things up as if it is no longer a monopoly
+ */
+void
+is_not_monop(MON *mp)
+{
+       int i;
+
+       mp->owner = -1;
+       for (i = 0; i < mp->num_in; i++)
+               mp->sq[i]->desc->monop = FALSE;
+       mp->name = mp->not_m;
+}
+
+/*
+ *     This routine gives a list of the current player's routine
+ */
+void
+list(void)
+{
+       printhold(player);
+}
+
+/*
+ *     This routine gives a list of a given players holdings
+ */
+void
+list_all(void)
+{
+       int pl;
+
+       while ((pl = getinp("Whose holdings do you want to see? ", name_list))
+           < num_play)
+               printhold(pl);
+}
+
+/*
+ *     This routine gives the players a chance before it exits.
+ */
+void
+quit(void)
+{
+       putchar('\n');
+
+       /* We dont even have a chance to input y/n if stdin is closed */
+       if (feof(stdin))
+               exit(0);
+
+       if (getyn("Do you all really want to quit? ") == 0)
+               exit(0);
+}
diff --git a/games/monop/monop.6 b/games/monop/monop.6
new file mode 100644 (file)
index 0000000..ee8bf2a
--- /dev/null
@@ -0,0 +1,178 @@
+.\"    $NetBSD: monop.6,v 1.19 2008/02/24 03:50:07 dholland Exp $
+.\"
+.\" Copyright (c) 1980 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.
+.\"
+.\"    @(#)monop.6     6.5 (Berkeley) 3/25/93
+.\"
+.Dd February 23, 2008
+.Dt MONOP 6
+.Os
+.Sh NAME
+.Nm monop
+.Nd Monopoly game
+.Sh SYNOPSIS
+.Nm
+.Op Ar file
+.Sh DESCRIPTION
+.Nm
+is reminiscent of the Parker Brother's game Monopoly, and
+monitors a game between 2 to 9 users.
+It is assumed that the rules of Monopoly are known.
+The game follows the standard rules, with the exception that,
+if a property goes up for auction and there are only two solvent players,
+no auction is held and the property remains unowned.
+.Pp
+The game, in effect, lends the player money,
+so it is possible to buy something which you cannot afford.
+However, as soon as a person goes into debt, he must
+.Dq fix the problem ,
+i.e., make himself solvent, before play can continue.
+If this is not possible, the player's property reverts to his debtee,
+either a player or the bank.
+A player can resign at any time to any person or the bank,
+which puts the property back on the board, unowned.
+.Pp
+Any time that the response to a question is a
+.Em string ,
+e.g., a name, place or person, you can type
+.Sq Ic \&?
+to get a list of valid answers.
+It is not possible to input a negative number, nor is it ever necessary.
+.Pp
+.Em A Summary of Commands :
+.Bl -tag -width item
+.It Ic quit
+quit game: This allows you to quit the game.
+It asks you if you're sure.
+.It Ic print
+print board: This prints out the current board.
+The columns have the following meanings (column headings are the same for the
+.Ic where ,
+.Ic own holdings ,
+and
+.Ic holdings
+commands):
+.Pp
+.Bl -tag -width indent -compact
+.It Name
+The first ten characters of the name of the square.
+.It Own
+The
+.Em number
+of the owner of the property.
+.It Price
+The cost of the property (if any).
+.It Mg
+This field has a
+.Sq *
+in it if the property is mortgaged.
+.It \&#
+If the property is a Utility or Railroad, this is the number
+of such owned by the owner.
+If the property is land, this is the number of houses on it.
+.It Rent
+Current rent on the property.
+If it is not owned, there is no rent.
+.El
+.It Ic where
+where players are: Tells you where all the players are.
+A
+.Sq *
+indicates the current player.
+.It Ic own holdings
+List your own holdings,
+i.e., money, get-out-of-jail-free cards, and property.
+.It Ic holdings
+holdings list: Look at anyone's holdings.
+It will ask you whose holdings you wish to look at.
+When you are finished, type
+.Sq Ic done .
+.It Ic mortgage
+mortgage property:
+Sets up a list of mortgageable property, and asks which you wish to mortgage.
+.It Ic unmortgage
+unmortgage property:
+Unmortgage mortgaged property.
+.It Ic buy
+buy houses:
+Sets up a list of monopolies on which you can buy houses.
+If there is more than one, it asks you which you want to buy for.
+It then asks you how many for each piece of property,
+giving the current amount in parentheses after the property name.
+If you build in an unbalanced manner
+(a disparity of more than one house within the same monopoly),
+it asks you to re-input things.
+.It Ic sell
+sell houses:
+Sets up a list of monopolies from which you can sell houses.
+It operates in an analogous manner to
+.Ic buy .
+.It Ic card
+card for jail:
+Use a get-out-of-jail-free card to get out of jail.
+If you're not in jail, or you don't have one, it tells you so.
+.It Ic pay
+pay for jail:
+Pay $50 to get out of jail, from whence you are put on Just Visiting.
+Difficult to do if you're not there.
+.It Ic trade
+This allows you to trade with another player.
+It asks you whom you wish to trade with,
+and then asks you what each wishes to give up.
+You can get a summary at the end, and, in all cases,
+it asks for confirmation of the trade before doing it.
+.It Ic resign
+Resign to another player or the bank.
+If you resign to the bank, all property reverts to its virgin state,
+and get-out-of-jail-free cards revert to the deck.
+.It Ic save
+save game:
+Save the current game in a file for later play.
+You can continue play after saving,
+either by adding the file in which you saved the game after the
+.Nm
+command, or by using the
+.Ic restore
+command (see below).
+It will ask you which file you wish to save it in,
+and, if the file exists, confirm that you wish to overwrite it.
+.It Ic restore
+restore game:
+Read in a previously saved game from a file.
+It leaves the file intact.
+.It Ic roll
+Roll the dice and move forward to your new location.
+If you simply hit the
+.Aq RETURN
+key instead of a command, it is the same as typing
+.Ic roll .
+.El
+.Sh AUTHORS
+.An Ken Arnold
+.Sh BUGS
+No command can be given an argument instead of a response to a query.
diff --git a/games/monop/monop.c b/games/monop/monop.c
new file mode 100644 (file)
index 0000000..7da1c30
--- /dev/null
@@ -0,0 +1,360 @@
+/*     $NetBSD: monop.c,v 1.27 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
+ The Regents of the University of California.  All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)monop.c    8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: monop.c,v 1.27 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include "deck.h"
+#include "monop.h"
+
+int main(int, char *[]);
+static void getplayers(void);
+static void init_players(void);
+static void init_monops(void);
+static void do_quit(int);
+
+
+bool   fixing,                 /* set if fixing up debt                */
+       trading,                /* set if in process of trading         */
+       told_em,                /* set if told user he's out of debt    */
+       spec;                   /* set if moving by card to RR or UTIL  */
+
+const char *name_list[MAX_PL+2];       /* list of players' names       */
+static const char *const comlist[] = { /* list of normal commands      */
+       "quit",         /*  0 */        "print",        /*  1 */
+       "where",        /*  2 */        "own holdings", /*  3 */
+       "holdings",     /*  4 */        "mortgage",     /*  5 */
+       "unmortgage",   /*  6 */        "buy houses",   /*  7 */
+       "sell houses",  /*  8 */        "card",         /*  9 */
+       "pay",          /* 10 */        "trade",        /* 11 */
+       "resign",       /* 12 */        "save",         /* 13 */
+       "restore",      /* 14 */        "roll",         /* 15 */
+       "",             /* 16 */
+       0
+};
+const char *const yncoms[] = { /* list of commands for yes/no answers  */
+       "yes",          /*  0 */        "no",           /*  1 */
+       "quit",         /*  2 */        "print",        /*  3 */
+       "where",        /*  4 */        "own holdings", /*  5 */
+       "holdings",     /*  6 */
+       0
+};
+const char *const lucky_mes[]  = {     /* "got lucky" messages         */
+       "You lucky stiff",              "You got lucky",
+       "What a lucky person!",         "You must have a 4-leaf clover",
+       "My, my!  Aren't we lucky!",    "Luck smiles upon you",
+       "You got lucky this time",      "Lucky person!",
+       "Your karma must certainly be together",
+       "How beautifully Cosmic",       "Wow, you must be really with it"
+       /* "I want your autograph",     -- Save for later */
+};
+
+int    player,                 /* current player number                */
+       num_play,               /* current number of players            */
+       num_doub,               /* # of doubles current player rolled   */
+                               /* # of "got lucky" messages            */
+       num_luck        = sizeof lucky_mes / sizeof (char *);
+
+/* list of command functions           */
+void (*const func[])(void) = { /* array of function calls for commands */
+       quit,                   /* quit game            |*  0 *|        */
+       printboard,             /* print board          |*  1 *|        */
+       where,                  /* where players are    |*  2 *|        */
+       list,                   /* own holdings         |*  3 *|        */
+       list_all,               /* holdings list        |*  4 *|        */
+       mortgage,               /* mortgage property    |*  5 *|        */
+       unmortgage,             /* unmortgage property  |*  6 *|        */
+       buy_houses,             /* buy houses           |*  7 *|        */
+       sell_houses,            /* sell houses          |*  8 *|        */
+       card,                   /* card for jail        |*  9 *|        */
+       pay,                    /* pay for jail         |* 10 *|        */
+       trade,                  /* trade                |* 11 *|        */
+       resign,                 /* resign               |* 12 *|        */
+       save,                   /* save game            |* 13 *|        */
+       restore,                /* restore game         |* 14 *|        */
+       do_move,                /* roll                 |* 15 *|        */
+       do_move                 /* ""                   |* 16 *|        */
+       };
+
+DECK   deck[2];                /* Chance and Community Chest           */
+
+PLAY   *play,                  /* player structure array ("calloc"ed)  */
+       *cur_p;                 /* pointer to current player's struct   */
+
+static RR_S rr[N_RR];          /* railroad descriptions                */
+
+static UTIL_S util[2];         /* utility descriptions                 */
+
+#define MONINIT(num_in, h_cost, not_m, mon_n, sq1,sq2,sq3) \
+     {0,    -1, num_in, 0,      h_cost, not_m, mon_n, {sq1,sq2,sq3}, {0,0,0}}
+/* name  owner          num_own                                      sq */
+
+static MON mon[N_MON] = {      /* monopoly descriptions                */
+/*   num_in h_cost  not_m      mon_n       sqnums */
+MONINIT(2,  1, "Purple",       "PURPLE",   1,3, 0),
+MONINIT(3,  1, "Lt. Blue",     "LT. BLUE", 6,8,9),
+MONINIT(3,  2, "Violet",       "VIOLET",   11,13,14),
+MONINIT(3,  2, "Orange",       "ORANGE",   16,18,19),
+MONINIT(3,  3, "Red",          "RED",      21,23,24),
+MONINIT(3,  3, "Yellow",       "YELLOW",   26,27,29),
+MONINIT(3,  4, "Green",        "GREEN",    31,32,34),
+MONINIT(2,  4, "Dk. Blue",     "DK. BLUE", 37,39, 0),
+};
+#undef MONINIT
+
+PROP   prop[N_PROP]    = {     /* typical properties                   */
+/* morg        monop   square  houses  mon_desc        rent    */
+{0,    0,      1,      0,      &mon[0],        { 2, 10, 30,  90, 160, 250} },
+{0,    0,      3,      0,      &mon[0],        { 4, 20, 60, 180, 320, 450} },
+{0,    0,      6,      0,      &mon[1],        { 6, 30, 90, 270, 400, 550} },
+{0,    0,      7,      0,      &mon[1],        { 6, 30, 90, 270, 400, 550} },
+{0,    0,      9,      0,      &mon[1],        { 8, 40,100, 300, 450, 600} },
+{0,    0,      11,     0,      &mon[2],        {10, 50,150, 450, 625, 750} },
+{0,    0,      13,     0,      &mon[2],        {10, 50,150, 450, 625, 750} },
+{0,    0,      14,     0,      &mon[2],        {12, 60,180, 500, 700, 900} },
+{0,    0,      16,     0,      &mon[3],        {14, 70,200, 550, 750, 950} },
+{0,    0,      17,     0,      &mon[3],        {14, 70,200, 550, 750, 950} },
+{0,    0,      19,     0,      &mon[3],        {16, 80,220, 600, 800,1000} },
+{0,    0,      21,     0,      &mon[4],        {18, 90,250, 700, 875,1050} },
+{0,    0,      23,     0,      &mon[4],        {18, 90,250, 700, 875,1050} },
+{0,    0,      24,     0,      &mon[4],        {20,100,300, 750, 925,1100} },
+{0,    0,      26,     0,      &mon[5],        {22,110,330, 800, 975,1150} },
+{0,    0,      27,     0,      &mon[5],        {22,110,330, 800, 975,1150} },
+{0,    0,      29,     0,      &mon[5],        {24,120,360, 850,1025,1200} },
+{0,    0,      31,     0,      &mon[6],        {26,130,390, 900,1100,1275} },
+{0,    0,      32,     0,      &mon[6],        {26,130,390, 900,1100,1275} },
+{0,    0,      34,     0,      &mon[6],        {28,150,450,1000,1200,1400} },
+{0,    0,      37,     0,      &mon[7],        {35,175,500,1100,1300,1500} },
+{0,    0,      39,     0,      &mon[7],        {50,200,600,1400,1700,2000} }
+};
+
+SQUARE board[N_SQRS+1] = {     /* board itself (+1 for Jail)           */
+/* name (COLOR)                        owner   type    desc            cost    */
+
+{"=== GO ===",                 -1,     SAFE,   NULL,           0       },
+{"Mediterranean Ave. (P)",     -1,     PRPTY,  &prop[0],       60      },
+{"Community Chest i",          -1,     CC,     NULL,           0       },
+{"Baltic Ave. (P)",            -1,     PRPTY,  &prop[1],       60      },
+{"Income Tax",                 -1,     INC_TAX, NULL,          0       },
+{"Reading RR",                 -1,     RR,     &rr[0],         200     },
+{"Oriental Ave. (L)",          -1,     PRPTY,  &prop[2],       100     },
+{"Chance i",                   -1,     CHANCE, NULL,           0       },
+{"Vermont Ave. (L)",           -1,     PRPTY,  &prop[3],       100     },
+{"Connecticut Ave. (L)",       -1,     PRPTY,  &prop[4],       120     },
+{"Just Visiting",              -1,     SAFE,   NULL,           0       },
+{"St. Charles Pl. (V)",                -1,     PRPTY,  &prop[5],       140     },
+{"Electric Co.",               -1,     UTIL,   &util[0],       150     },
+{"States Ave. (V)",            -1,     PRPTY,  &prop[6],       140     },
+{"Virginia Ave. (V)",          -1,     PRPTY,  &prop[7],       160     },
+{"Pennsylvania RR",            -1,     RR,     &rr[1],         200     },
+{"St. James Pl. (O)",          -1,     PRPTY,  &prop[8],       180     },
+{"Community Chest ii",         -1,     CC,     NULL,           0       },
+{"Tennessee Ave. (O)",         -1,     PRPTY,  &prop[9],       180     },
+{"New York Ave. (O)",          -1,     PRPTY,  &prop[10],      200     },
+{"Free Parking",               -1,     SAFE,   NULL,           0       },
+{"Kentucky Ave. (R)",          -1,     PRPTY,  &prop[11],      220     },
+{"Chance ii",                  -1,     CHANCE, NULL,           0       },
+{"Indiana Ave. (R)",           -1,     PRPTY,  &prop[12],      220     },
+{"Illinois Ave. (R)",          -1,     PRPTY,  &prop[13],      240     },
+{"B&O RR",                     -1,     RR,     &rr[2],         200     },
+{"Atlantic Ave. (Y)",          -1,     PRPTY,  &prop[14],      260     },
+{"Ventnor Ave. (Y)",           -1,     PRPTY,  &prop[15],      260     },
+{"Water Works",                        -1,     UTIL,   &util[1],       150     },
+{"Marvin Gardens (Y)",         -1,     PRPTY,  &prop[16],      280     },
+{"GO TO JAIL",                 -1,     GOTO_J, NULL,           0       },
+{"Pacific Ave. (G)",           -1,     PRPTY,  &prop[17],      300     },
+{"N. Carolina Ave. (G)",       -1,     PRPTY,  &prop[18],      300     },
+{"Community Chest iii",                -1,     CC,     NULL,           0       },
+{"Pennsylvania Ave. (G)",      -1,     PRPTY,  &prop[19],      320     },
+{"Short Line RR",              -1,     RR,     &rr[3],         200     },
+{"Chance iii",                 -1,     CHANCE, NULL,           0       },
+{"Park Place (D)",             -1,     PRPTY,  &prop[20],      350     },
+{"Luxury Tax",                 -1,     LUX_TAX, NULL,          0       },
+{"Boardwalk (D)",              -1,     PRPTY,  &prop[21],      400     },
+{"JAIL",                       -1,     IN_JAIL, NULL,          0       }
+};
+
+
+/*
+ *     This program implements a monopoly game
+ */
+int
+main(int ac, char *av[])
+{
+       /* Revoke setgid privileges */
+       setgid(getgid());
+
+       srandom((unsigned long)time(NULL));
+       num_luck = sizeof lucky_mes / sizeof (char *);
+       init_decks();
+       init_monops();
+       if (ac > 1) {
+               if (rest_f(av[1]) < 0)
+                       restore();
+       }
+       else {
+               getplayers();
+               init_players();
+       }
+       signal(SIGINT, do_quit);
+       for (;;) {
+               printf("\n%s (%d) (cash $%d) on %s\n", cur_p->name, player + 1,
+                       cur_p->money, board[cur_p->loc].name);
+               printturn();
+               force_morg();
+               execute(getinp("-- Command: ", comlist));
+       }
+}
+
+/*ARGSUSED*/
+static void
+do_quit(int n __unused)
+{
+       quit();
+}
+
+/*
+ *     This routine gets the names of the players
+ */
+static void
+getplayers(void)
+{
+       int i, j;
+       char buf[257];
+
+blew_it:
+       for (;;) {
+               if ((num_play = get_int("How many players? ")) <= 1 ||
+                   num_play > MAX_PL)
+                       printf("Sorry. Number must range from 2 to %d\n",
+                           MAX_PL);
+               else
+                       break;
+       }
+       cur_p = play = calloc((size_t)num_play, sizeof (PLAY));
+       if (play == NULL)
+               err(1, NULL);
+       for (i = 0; i < num_play; i++) {
+               do {
+                       printf("Player %d's name: ", i + 1);
+                       fgets(buf, sizeof(buf), stdin);
+                       if (feof(stdin)) {
+                               quit();
+                       }
+                       buf[strcspn(buf, "\n")] = '\0';
+               } while (strlen(buf) == 0);
+               name_list[i] = play[i].name = strdup(buf);
+               if (name_list[i] == NULL)
+                       err(1, NULL);
+               play[i].money = 1500;
+       }
+       name_list[i++] = "done";
+       name_list[i] = 0;
+       for (i = 0; i < num_play; i++)
+               for (j = i + 1; j <= num_play; j++)
+                       if (strcasecmp(name_list[i], name_list[j]) == 0) {
+                               if (j != num_play)
+                                       printf("Hey!!! Some of those are "
+                                           "IDENTICAL!!  Let's try that "
+                                           "again...\n");
+                               else
+                                       printf("\"done\" is a reserved word.  "
+                                           "Please try again\n");
+                               for (i = 0; i < num_play; i++)
+                                       free(play[i].name);
+                               free(play);
+                               goto blew_it;
+                       }
+}
+
+/*
+ *     This routine figures out who goes first
+ */
+static void
+init_players(void)
+{
+       int i, rl, cur_max;
+       bool over = 0;
+       int max_pl = 0;
+
+again:
+       putchar('\n');
+       for (cur_max = i = 0; i < num_play; i++) {
+               printf("%s (%d) rolls %d\n", play[i].name, i+1, rl=roll(2, 6));
+               if (rl > cur_max) {
+                       over = FALSE;
+                       cur_max = rl;
+                       max_pl = i;
+               }
+               else if (rl == cur_max)
+                       over++;
+       }
+       if (over) {
+               printf("%d people rolled the same thing, so we'll try again\n",
+                   over + 1);
+               goto again;
+       }
+       player = max_pl;
+       cur_p = &play[max_pl];
+       printf("%s (%d) goes first\n", cur_p->name, max_pl + 1);
+}
+
+/*
+ *     This routine initializes the monopoly structures.
+ */
+static void
+init_monops(void)
+{
+       MON *mp;
+       int i;
+
+       for (mp = mon; mp < &mon[N_MON]; mp++) {
+               mp->name = mp->not_m;
+               for (i = 0; i < mp->num_in; i++)
+                       mp->sq[i] = &board[mp->sqnums[i]];
+       }
+}
diff --git a/games/monop/monop.h b/games/monop/monop.h
new file mode 100644 (file)
index 0000000..ecc7420
--- /dev/null
@@ -0,0 +1,221 @@
+/*     $NetBSD: monop.h,v 1.19 2009/08/12 08:10:49 dholland 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. 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.
+ *
+ *     @(#)monop.h     8.1 (Berkeley) 5/31/93
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define        bool    char
+
+#define        TRUE    (1)
+#define        FALSE   (0)
+
+#define        N_MON   8       /* number of monopolies                 */
+#define        N_PROP  22      /* number of normal property squares    */
+#define        N_RR    4       /* number of railroads                  */
+#define        N_UTIL  2       /* number of utilities                  */
+#define        N_SQRS  40      /* number of squares on board           */
+#define        MAX_PL  9       /* maximum number of players            */
+#define        MAX_PRP (N_PROP+N_RR+N_UTIL) /* max # ownable property  */
+#define        N_HOUSE 32      /* total number of houses available     */
+#define        N_HOTEL 12      /* total number of hotels available     */
+
+                               /* square type numbers                  */
+#define        PRPTY   0       /* normal property                      */
+#define        RR      1       /* railroad                             */
+#define        UTIL    2       /* water works - electric co            */
+#define        SAFE    3       /* safe spot                            */
+#define        CC      4       /* community chest                      */
+#define        CHANCE  5       /* chance (surprise!!!)                 */
+#define        INC_TAX 6       /* Income tax */
+#define        GOTO_J  7       /* Go To Jail! */
+#define        LUX_TAX 8       /* Luxury tax */
+#define        IN_JAIL 9       /* In jail */
+
+#define        JAIL    40      /* JAIL square number                   */
+
+#define        lucky(str)      printf("%s%s\n",str,lucky_mes[roll(1,num_luck)-1])
+#define        printline()     printf("------------------------------\n")
+#define        sqnum(sqp)      ((short)(sqp - board))
+
+struct sqr_st {                        /* structure for square                 */
+       const char      *name;          /* place name                   */
+       short   owner;                  /* owner number                 */
+       short   type;                   /* place type                   */
+       struct prp_st   *desc;          /* description struct           */
+       int     cost;                   /* cost                         */
+};
+
+typedef struct sqr_st  SQUARE;
+
+struct mon_st {                        /* monopoly description structure       */
+       const char      *name;          /* monop. name (color)          */
+       short   owner;                  /* owner of monopoly            */
+       short   num_in;                 /* # in monopoly                */
+       short   num_own;                /* # owned (-1: not poss. monop)*/
+       short   h_cost;                 /* price of houses              */
+       const char      *not_m;         /* name if not monopoly         */
+       const char      *mon_n;         /* name if a monopoly           */
+       unsigned char   sqnums[3];      /* Square numbers (used to init)*/
+       SQUARE  *sq[3];                 /* list of squares in monop     */
+};
+
+typedef struct mon_st  MON;
+
+/*
+ * This struct describes a property.  For railroads and utilities, only
+ * the "morg" member is used.
+ */
+struct prp_st {                        /* property description structure       */
+       bool    morg;                   /* set if mortgaged             */
+       bool    monop;                  /* set if monopoly              */
+       short   square;                 /* square description           */
+       short   houses;                 /* number of houses             */
+       MON     *mon_desc;              /* name of color                */
+       int     rent[6];                /* rents                        */
+};
+
+struct own_st {                        /* element in list owned things         */
+       SQUARE  *sqr;                   /* pointer to square            */
+       struct own_st   *next;          /* next in list                 */
+};
+
+typedef struct own_st  OWN;
+
+struct plr_st {                        /* player description structure         */
+       char    *name;                  /* owner name                   */
+       short   num_gojf;               /* # of get-out-of-jail-free's  */
+       short   num_rr;                 /* # of railroads owned         */
+       short   num_util;               /* # of water works/elec. co.   */
+       short   loc;                    /* location on board            */
+       short   in_jail;                /* count of turns in jail       */
+       int     money;                  /* amount of money              */
+       OWN     *own_list;              /* start of property list       */
+};
+
+typedef struct plr_st  PLAY;
+typedef struct prp_st  PROP;
+typedef struct prp_st  RR_S;
+typedef struct prp_st  UTIL_S;
+
+extern bool    trading, spec, fixing, told_em;
+
+extern const char      *const yncoms[], *name_list[], *const lucky_mes[];
+
+extern int     num_play, player, num_doub, num_luck;
+
+extern void (*const func[])(void);
+
+/*extern MON   mon[N_MON];*/
+
+extern PLAY    *play, *cur_p;
+
+extern PROP    prop[N_PROP];
+
+/*extern RR_S  rr[N_RR];*/
+
+extern SQUARE  board[N_SQRS + 1];
+
+/*extern UTIL_S        util[2];*/
+
+
+/* cards.c */
+void ret_card(PLAY *);
+
+/* execute.c */
+void execute(int);
+void do_move(void);
+void move(int);
+void save(void);
+void restore(void);
+int rest_f(const char *);
+
+/* getinp.c */
+int getinp(const char *, const char *const []);
+
+/* houses.c */
+void buy_houses(void);
+void sell_houses(void);
+
+/* jail.c */
+void card(void);
+void pay(void);
+int move_jail(int, int );
+void printturn(void);
+
+/* misc.c */
+int getyn(const char *);
+void notify(void);
+void next_play(void);
+int get_int(const char *);
+void set_ownlist(int);
+void is_not_monop(MON *);
+void list(void);
+void list_all(void);
+void quit(void);
+
+/* morg.c */
+void mortgage(void);
+void unmortgage(void);
+void force_morg(void);
+
+/* print.c */
+void printboard(void);
+void where(void);
+void printsq(int, bool);
+void printhold(int);
+
+/* prop.c */
+void buy(int, SQUARE *);
+void add_list(int, OWN **, int);
+void del_list(int, OWN **, short);
+void bid(void);
+int prop_worth(PLAY *);
+
+/* rent.c */
+void rent(SQUARE *);
+
+/* roll.c */
+int roll(int, int);
+
+/* spec.c */
+void inc_tax(void);
+void goto_jail(void);
+void lux_tax(void);
+void cc(void);
+void chance(void);
+
+/* trade.c */
+void trade(void);
+void resign(void);
diff --git a/games/monop/morg.c b/games/monop/morg.c
new file mode 100644 (file)
index 0000000..74da515
--- /dev/null
@@ -0,0 +1,229 @@
+/*     $NetBSD: morg.c,v 1.19 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)morg.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: morg.c,v 1.19 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+/*
+ *     These routines deal with mortgaging.
+ */
+
+static const char      *names[MAX_PRP+2],
+               *const morg_coms[]      = {
+                       "quit",         /*  0 */
+                       "print",        /*  1 */
+                       "where",        /*  2 */
+                       "own holdings", /*  3 */
+                       "holdings",     /*  4 */
+                       "mortgage",     /*  5 */
+                       "unmortgage",   /*  6 */
+                       "buy",          /*  7 */
+                       "sell",         /*  8 */
+                       "card",         /*  9 */
+                       "pay",          /* 10 */
+                       "trade",        /* 11 */
+                       "resign",       /* 12 */
+                       "save game",    /* 13 */
+                       "restore game", /* 14 */
+                       0
+               };
+
+static short   square[MAX_PRP+2];
+
+static int     num_good, got_houses;
+
+
+static int set_mlist(void);
+static void m(int);
+static int set_umlist(void);
+static void unm(int);
+
+/*
+ *     This routine is the command level response the mortgage command.
+ * it gets the list of mortgageable property and asks which are to
+ * be mortgaged.
+ */
+void
+mortgage(void)
+{
+       int propnum;
+
+       for (;;) {
+               if (set_mlist() == 0) {
+                       if (got_houses)
+                               printf("You can't mortgage property with "
+                                   "houses on it.\n");
+                       else
+                               printf("You don't have any un-mortgaged "
+                                   "property.\n");
+                       return;
+               }
+               if (num_good == 1) {
+                       printf("Your only mortgageable property is %s\n",
+                           names[0]);
+                       if (getyn("Do you want to mortgage it? ") == 0)
+                               m(square[0]);
+                       return;
+               }
+               propnum = getinp("Which property do you want to mortgage? ",
+                               names);
+               if (propnum == num_good)
+                       return;
+               m(square[propnum]);
+               notify();
+       }
+}
+
+/*
+ *     This routine sets up the list of mortgageable property
+ */
+static int
+set_mlist(void)
+{
+       OWN *op;
+
+       num_good = 0;
+       for (op = cur_p->own_list; op; op = op->next)
+               if (!op->sqr->desc->morg) {
+                       if (op->sqr->type == PRPTY && op->sqr->desc->houses)
+                               got_houses++;
+                       else {
+                               names[num_good] = op->sqr->name;
+                               square[num_good++] = sqnum(op->sqr);
+                       }
+               }
+       names[num_good++] = "done";
+       names[num_good--] = 0;
+       return num_good;
+}
+
+/*
+ *     This routine actually mortgages the property.
+ */
+static void
+m(int propnum)
+{
+       int price;
+
+       price = board[propnum].cost/2;
+       board[propnum].desc->morg = TRUE;
+       printf("That got you $%d\n",price);
+       cur_p->money += price;
+}
+
+/*
+ *     This routine is the command level repsponse to the unmortgage
+ * command.  It gets the list of mortgaged property and asks which are
+ * to be unmortgaged.
+ */
+void
+unmortgage(void)
+{
+       int propnum;
+
+       for (;;) {
+               if (set_umlist() == 0) {
+                       printf("You don't have any mortgaged property.\n");
+                       return;
+               }
+               if (num_good == 1) {
+                       printf("Your only mortgaged property is %s\n",
+                           names[0]);
+                       if (getyn("Do you want to unmortgage it? ") == 0)
+                               unm(square[0]);
+                       return;
+               }
+               propnum = getinp("Which property do you want to unmortgage? ",
+                   names);
+               if (propnum == num_good)
+                       return;
+               unm(square[propnum]);
+       }
+}
+
+/*
+ *     This routine sets up the list of mortgaged property
+ */
+static int
+set_umlist(void)
+{
+       OWN *op;
+
+       num_good = 0;
+       for (op = cur_p->own_list; op; op = op->next)
+               if (op->sqr->desc->morg) {
+                       names[num_good] = op->sqr->name;
+                       square[num_good++] = sqnum(op->sqr);
+               }
+       names[num_good++] = "done";
+       names[num_good--] = 0;
+       return num_good;
+}
+
+/*
+ *     This routine actually unmortgages the property
+ */
+static void
+unm(int propnum)
+{
+       int price;
+
+       price = board[propnum].cost/2;
+       board[propnum].desc->morg = FALSE;
+       price += price/10;
+       printf("That cost you $%d\n",price);
+       cur_p->money -= price;
+       (void)set_umlist();
+}
+
+/*
+ *     This routine forces the indebted player to fix his
+ * financial woes.  It is fine to have $0 but not to be in debt.
+ */
+void
+force_morg(void)
+{
+       told_em = fixing = TRUE;
+       while (cur_p->money < 0) {
+               told_em = FALSE;
+               (*func[(getinp("How are you going to fix it up? ", morg_coms))])();
+               notify();
+       }
+       fixing = FALSE;
+}
diff --git a/games/monop/print.c b/games/monop/print.c
new file mode 100644 (file)
index 0000000..4b7b662
--- /dev/null
@@ -0,0 +1,197 @@
+/*     $NetBSD: print.c,v 1.13 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)print.c    8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: print.c,v 1.13 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+static const char *header = "Name      Own      Price Mg # Rent";
+
+static void printmorg(const SQUARE *);
+
+/*
+ *     This routine prints out the current board
+ */
+void
+printboard(void)
+{
+       int i;
+
+       printf("%s\t%s\n", header, header);
+       for (i = 0; i < N_SQRS/2; i++) {
+               printsq(i, FALSE);
+               putchar('\t');
+               printsq(i+N_SQRS/2, TRUE);
+       }
+}
+
+/*
+ *     This routine lists where each player is.
+ */
+void
+where(void)
+{
+       int i;
+
+       printf("%s Player\n", header);
+       for (i = 0; i < num_play; i++) {
+               printsq(play[i].loc, FALSE);
+               printf(" %s (%d)", play[i].name, i+1);
+               if (cur_p == &play[i])
+                       printf(" *");
+               putchar('\n');
+       }
+}
+
+/*
+ *     This routine prints out an individual square
+ */
+void
+printsq(int sqn, bool eoln)
+{
+       int rnt;
+       PROP *pp;
+       SQUARE *sqp;
+
+       sqp = &board[sqn];
+       printf("%-10.10s", sqp->name);
+       switch (sqp->type) {
+         case SAFE:
+         case CC:
+         case CHANCE:
+         case INC_TAX:
+         case GOTO_J:
+         case LUX_TAX:
+         case IN_JAIL:
+               if (!eoln)
+                       printf("                        ");
+               break;
+         case PRPTY:
+               pp = sqp->desc;
+               if (sqp->owner < 0) {
+                       printf(" - %-8.8s %3d", pp->mon_desc->name, sqp->cost);
+                       if (!eoln)
+                               printf("         ");
+                       break;
+               }
+               printf(" %d %-8.8s %3d", sqp->owner+1, pp->mon_desc->name,
+                       sqp->cost);
+               printmorg(sqp);
+               if (pp->monop) {
+                       if (pp->houses < 5)
+                               if (pp->houses > 0)
+                                       printf("%d %4d", pp->houses,
+                                               pp->rent[pp->houses]);
+                               else
+                                       printf("0 %4d", pp->rent[0] * 2);
+                       else
+                               printf("H %4d", pp->rent[5]);
+               } else
+                       printf("  %4d", pp->rent[0]);
+               break;
+         case UTIL:
+               if (sqp->owner < 0) {
+                       printf(" -          150");
+                       if (!eoln)
+                               printf("         ");
+                       break;
+               }
+               printf(" %d          150", sqp->owner+1);
+               printmorg(sqp);
+               printf("%d", play[sqp->owner].num_util);
+               if (!eoln)
+                       printf("    ");
+               break;
+         case RR:
+               if (sqp->owner < 0) {
+                       printf(" - Railroad 200");
+                       if (!eoln)
+                               printf("         ");
+                       break;
+               }
+               printf(" %d Railroad 200", sqp->owner+1);
+               printmorg(sqp);
+               rnt = 25;
+               rnt <<= play[sqp->owner].num_rr - 1;
+               printf("%d %4d", play[sqp->owner].num_rr,
+                   25 << (play[sqp->owner].num_rr - 1));
+               break;
+       }
+       if (eoln)
+               putchar('\n');
+}
+
+/*
+ *     This routine prints out the mortgage flag.
+ */
+static void
+printmorg(const SQUARE *sqp)
+{
+       if (sqp->desc->morg)
+               printf(" * ");
+       else
+               printf("   ");
+}
+
+/*
+ *     This routine lists the holdings of the player given
+ */
+void
+printhold(int pl)
+{
+       OWN *op;
+       PLAY *pp;
+
+       pp = &play[pl];
+       printf("%s's (%d) holdings (Total worth: $%d):\n", name_list[pl],
+           pl + 1, pp->money + prop_worth(pp));
+       printf("\t$%d", pp->money);
+       if (pp->num_gojf) {
+               printf(", %d get-out-of-jail-free card", pp->num_gojf);
+               if (pp->num_gojf > 1)
+                       putchar('s');
+       }
+       putchar('\n');
+       if (pp->own_list) {
+               printf("\t%s\n", header);
+               for (op = pp->own_list; op; op = op->next) {
+                       putchar('\t');
+                       printsq(sqnum(op->sqr), TRUE);
+               }
+       }
+}
diff --git a/games/monop/prop.c b/games/monop/prop.c
new file mode 100644 (file)
index 0000000..0b6bef8
--- /dev/null
@@ -0,0 +1,224 @@
+/*     $NetBSD: prop.c,v 1.20 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)prop.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: prop.c,v 1.20 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+
+#include "monop.h"
+
+static int value(SQUARE *);
+
+/*
+ *     This routine deals with buying property, setting all the
+ * appropriate flags.
+ */
+void
+buy(int playernum, SQUARE *sqrp)
+{
+       trading = FALSE;
+       sqrp->owner = playernum;
+       add_list(playernum, &(play[playernum].own_list), cur_p->loc);
+}
+
+/*
+ *     This routine adds an item to the list.
+ */
+void
+add_list(int plr, OWN **head, int op_sqr)
+{
+       int val;
+       OWN *tp, *last_tp;
+       OWN *op;
+
+       op = calloc(1, sizeof (OWN));
+       if (op == NULL)
+               errx(1, "out of memory");
+       op->sqr = &board[op_sqr];
+       val = value(op->sqr);
+       last_tp = NULL;
+       for (tp = *head; tp && value(tp->sqr) < val; tp = tp->next)
+               if (val == value(tp->sqr)) {
+                       free(op);
+                       return;
+               }
+               else
+                       last_tp = tp;
+       op->next = tp;
+       if (last_tp != NULL)
+               last_tp->next = op;
+       else
+               *head = op;
+       if (!trading)
+               set_ownlist(plr);
+}
+
+/*
+ *     This routine deletes property from the list.
+ */
+void
+del_list(int plr, OWN **head, short op_sqr)
+{
+       OWN *op, *last_op;
+
+       switch (board[op_sqr].type) {
+         case PRPTY:
+               board[op_sqr].desc->mon_desc->num_own--;
+               break;
+         case RR:
+               play[plr].num_rr--;
+               break;
+         case UTIL:
+               play[plr].num_util--;
+               break;
+       }
+       last_op = NULL;
+       for (op = *head; op; op = op->next)
+               if (op->sqr == &board[op_sqr])
+                       break;
+               else
+                       last_op = op;
+       if (op == NULL)
+               return;
+       if (last_op == NULL)
+               *head = op->next;
+       else {
+               last_op->next = op->next;
+               free(op);
+       }
+}
+
+/*
+ *     This routine calculates the value for sorting of the
+ * given square.
+ */
+static int
+value(SQUARE *sqp)
+{
+       int sqr;
+
+       sqr = sqnum(sqp);
+       switch (sqp->type) {
+         case SAFE:
+               return 0;
+         default:              /* Specials, etc */
+               return 1;
+         case UTIL:
+               if (sqr == 12)
+                       return 2;
+               else
+                       return 3;
+         case RR:
+               return 4 + sqr/10;
+         case PRPTY:
+               return 8 + (sqp->desc) - prop;
+       }
+}
+
+/*
+ * This routine accepts bids for the current piece of property.
+ */
+void
+bid(void)
+{
+       static bool in[MAX_PL];
+       int i, num_in, cur_max;
+       char buf[257];
+       int cur_bid;
+
+       printf("\nSo it goes up for auction.  Type your bid after your name\n");
+       for (i = 0; i < num_play; i++)
+               in[i] = TRUE;
+       i = -1;
+       cur_max = 0;
+       num_in = num_play;
+       while (num_in > 1 || (cur_max == 0 && num_in > 0)) {
+               i = (i + 1) % num_play;
+               if (in[i]) {
+                       do {
+                               (void)snprintf(buf, sizeof(buf), "%s: ",
+                                   name_list[i]);
+                               cur_bid = get_int(buf);
+                               if (cur_bid == 0) {
+                                       in[i] = FALSE;
+                                       if (--num_in == 0)
+                                               break;
+                               } else if (cur_bid <= cur_max) {
+                                       printf("You must bid higher than %d "
+                                           "to stay in\n", cur_max);
+                                       printf("(bid of 0 drops you out)\n");
+                               } else if (cur_bid > play[i].money) {
+                                       printf("You can't bid more than your cash ($%d)\n",
+                                           play[i].money);
+                                       cur_bid = -1;
+                               }
+                       } while (cur_bid != 0 && cur_bid <= cur_max);
+                       cur_max = (cur_bid ? cur_bid : cur_max);
+               }
+       }
+       if (cur_max != 0) {
+               while (!in[i])
+                       i = (i + 1) % num_play;
+               printf("It goes to %s (%d) for $%d\n",play[i].name,i+1,cur_max);
+               buy(i, &board[cur_p->loc]);
+               play[i].money -= cur_max;
+       }
+       else
+               printf("Nobody seems to want it, so we'll leave it for "
+                   "later\n");
+}
+
+/*
+ *     This routine calculates the value of the property
+ * of given player.
+ */
+int
+prop_worth(PLAY *plp)
+{
+       OWN *op;
+       int worth;
+
+       worth = 0;
+       for (op = plp->own_list; op; op = op->next) {
+               if (op->sqr->type == PRPTY && op->sqr->desc->monop)
+                       worth += op->sqr->desc->mon_desc->h_cost * 50 *
+                           op->sqr->desc->houses;
+               worth += op->sqr->cost;
+       }
+       return worth;
+}
diff --git a/games/monop/rent.c b/games/monop/rent.c
new file mode 100644 (file)
index 0000000..55f131f
--- /dev/null
@@ -0,0 +1,96 @@
+/*     $NetBSD: rent.c,v 1.9 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rent.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: rent.c,v 1.9 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+/*
+ *     This routine has the player pay rent
+ */
+void
+rent(SQUARE *sqp)
+{
+       int rnt = 0;
+       PROP *pp;
+       PLAY *plp;
+
+       plp = &play[sqp->owner];
+       printf("Owned by %s\n", plp->name);
+       if (sqp->desc->morg) {
+               lucky("The thing is mortgaged.  ");
+               return;
+       }
+       switch (sqp->type) {
+         case PRPTY:
+               pp = sqp->desc;
+               if (pp->monop)
+                       if (pp->houses == 0)
+                               printf("rent is %d\n", rnt=pp->rent[0] * 2);
+                       else if (pp->houses < 5)
+                               printf("with %d house%s, rent is %d\n",
+                                   pp->houses, pp->houses == 1 ? "" : "s",
+                                   rnt=pp->rent[pp->houses]);
+                       else
+                               printf("with a hotel, rent is %d\n",
+                                   rnt=pp->rent[pp->houses]);
+               else
+                       printf("rent is %d\n", rnt = pp->rent[0]);
+               break;
+         case RR:
+               rnt = 25;
+               rnt <<= (plp->num_rr - 1);
+               if (spec)
+                       rnt <<= 1;
+               printf("rent is %d\n", rnt);
+               break;
+         case UTIL:
+               rnt = roll(2, 6);
+               if (plp->num_util == 2 || spec) {
+                       printf("rent is 10 * roll (%d) = %d\n", rnt, rnt * 10);
+                       rnt *= 10;
+               }
+               else {
+                       printf("rent is 4 * roll (%d) = %d\n", rnt, rnt * 4);
+                       rnt *= 4;
+               }
+               break;
+       }
+       cur_p->money -= rnt;
+       plp->money += rnt;
+}
diff --git a/games/monop/roll.c b/games/monop/roll.c
new file mode 100644 (file)
index 0000000..373fc73
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: roll.c,v 1.14 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)roll.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: roll.c,v 1.14 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+
+#include "monop.h"
+
+/*
+ *     This routine rolls ndie nside-sided dice.
+ */
+
+int
+roll(int ndie, int nsides)
+{
+       long tot;
+
+       tot = 0;
+       while (ndie--)
+               tot += (random() % nsides) + 1;
+       return (int)tot;
+}
diff --git a/games/monop/spec.c b/games/monop/spec.c
new file mode 100644 (file)
index 0000000..801aa76
--- /dev/null
@@ -0,0 +1,115 @@
+/*     $NetBSD: spec.c,v 1.11 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)spec.c     8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: spec.c,v 1.11 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+#include "deck.h"
+
+static const char      *const perc[]   = {
+       "10%", "ten percent", "%", "$200", "200", 0
+       };
+
+/*
+ * collect income tax
+ */
+void
+inc_tax(void)
+{
+       int worth, com_num;
+
+       com_num = getinp("Do you wish to lose 10% of your total worth or "
+           "$200? ", perc);
+       worth = cur_p->money + prop_worth(cur_p);
+       printf("You were worth $%d", worth);
+       worth /= 10;
+       if (com_num > 2) {
+               if (worth < 200)
+                       printf(".  Good try, but not quite.\n");
+               else if (worth > 200)
+                       lucky(".\nGood guess.  ");
+               cur_p->money -= 200;
+       }
+       else {
+               printf(", so you pay $%d", worth);
+               if (worth > 200)
+                       printf("  OUCH!!!!.\n");
+               else if (worth < 200)
+                       lucky("\nGood guess.  ");
+               cur_p->money -= worth;
+       }
+       if (worth == 200)
+               lucky("\nIt makes no difference!  ");
+}
+
+/*
+ * move player to jail
+ */
+void
+goto_jail(void)
+{
+       cur_p->loc = JAIL;
+}
+
+/*
+ * landing on luxury tax
+ */
+void
+lux_tax(void)
+{
+       printf("You lose $75\n");
+       cur_p->money -= 75;
+}
+
+/*
+ * draw community chest card
+ */
+void
+cc(void)
+{
+       get_card(&CC_D);
+}
+
+/*
+ * draw chance card
+ */
+void
+chance(void)
+{
+       get_card(&CH_D);
+}
diff --git a/games/monop/trade.c b/games/monop/trade.c
new file mode 100644 (file)
index 0000000..63d2e8a
--- /dev/null
@@ -0,0 +1,329 @@
+/*     $NetBSD: trade.c,v 1.16 2012/06/19 05:35:32 dholland 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. 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 <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)trade.c    8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: trade.c,v 1.16 2012/06/19 05:35:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "monop.h"
+
+struct trd_st {                        /* how much to give to other player     */
+       int     trader;                 /* trader number                */
+       int     cash;                   /* amount of cash               */
+       int     gojf;                   /* # get-out-of-jail-free cards */
+       OWN     *prop_list;             /* property list                */
+};
+
+typedef        struct trd_st   TRADE;
+
+static const char      *plist[MAX_PRP+2];
+
+static int     used[MAX_PRP];
+
+static TRADE   trades[2];
+
+static void get_list(int, int );
+static int set_list(OWN *);
+static void summate(void);
+static void do_trade(void);
+static void move_em(TRADE *, TRADE *);
+
+void
+trade(void)
+{
+       int tradee, i;
+
+       trading = TRUE;
+       for (i = 0; i < 2; i++) {
+               trades[i].cash = 0;
+               trades[i].gojf = FALSE;
+               trades[i].prop_list = NULL;
+       }
+over:
+       if (num_play == 1) {
+               printf("There ain't no-one around to trade WITH!!\n");
+               return;
+       }
+       if (num_play > 2) {
+               tradee = getinp("Which player do you wish to trade with? ",
+                   name_list);
+               if (tradee == num_play)
+                       return;
+               if (tradee == player) {
+                       printf("You can't trade with yourself!\n");
+                       goto over;
+               }
+       }
+       else
+               tradee = 1 - player;
+       get_list(0, player);
+       get_list(1, tradee);
+       if (getyn("Do you wish a summary? ") == 0)
+               summate();
+       if (getyn("Is the trade ok? ") == 0)
+               do_trade();
+}
+
+/*
+ *     This routine gets the list of things to be trader for the
+ * player, and puts in the structure given.
+ */
+static void
+get_list(int struct_no, int play_no)
+{
+       int sn, pn;
+       PLAY *pp;
+       int numin, propnum, num_prp;
+       OWN *op;
+       TRADE *tp;
+
+       for (numin = 0; numin < MAX_PRP; numin++)
+               used[numin] = FALSE;
+       sn = struct_no, pn = play_no;
+       pp = &play[pn];
+       tp = &trades[sn];
+       tp->trader = pn;
+       printf("player %s (%d):\n", pp->name, pn+1);
+       if (pp->own_list) {
+               numin = set_list(pp->own_list);
+               for (num_prp = numin; num_prp; ) {
+                       propnum=getinp("Which property do you wish to trade? ",
+                           plist);
+                       if (propnum == numin)
+                               break;
+                       else if (used[propnum])
+                               printf("You've already allocated that.\n");
+                       else {
+                               num_prp--;
+                               used[propnum] = TRUE;
+                               for (op = pp->own_list; propnum--; op = op->next)
+                                       continue;
+                               add_list(pn, &(tp->prop_list), sqnum(op->sqr));
+                       }
+               }
+       }
+       if (pp->money > 0) {
+               printf("You have $%d.  ", pp->money);
+               tp->cash = get_int("How much are you trading? ");
+       }
+       if (pp->num_gojf > 0) {
+once_more:
+               printf("You have %d get-out-of-jail-free cards. ",pp->num_gojf);
+               tp->gojf = get_int("How many are you trading? ");
+               if (tp->gojf > pp->num_gojf) {
+                       printf("You don't have that many.  Try again.\n");
+                       goto once_more;
+               }
+       }
+}
+
+/*
+ *     This routine sets up the list of tradable property.
+ */
+static int
+set_list(OWN *the_list)
+{
+       int i;
+       OWN *op;
+
+       i = 0;
+       for (op = the_list; op; op = op->next)
+               if (!used[i])
+                       plist[i++] = op->sqr->name;
+       plist[i++] = "done";
+       plist[i--] = 0;
+       return i;
+}
+
+/*
+ *     This routine summates the trade.
+ */
+static void
+summate(void)
+{
+       bool some;
+       int i;
+       TRADE *tp;
+       OWN *op;
+
+       for (i = 0; i < 2; i++) {
+               tp = &trades[i];
+               some = FALSE;
+               printf("Player %s (%d) gives:\n", play[tp->trader].name,
+                       tp->trader+1);
+               if (tp->cash > 0)
+                       printf("\t$%d\n", tp->cash), some++;
+               if (tp->gojf > 0)
+                       printf("\t%d get-out-of-jail-free card(s)\n", tp->gojf),
+                       some++;
+               if (tp->prop_list) {
+                       for (op = tp->prop_list; op; op = op->next)
+                               putchar('\t'), printsq(sqnum(op->sqr), TRUE);
+                       some++;
+               }
+               if (!some)
+                       printf("\t-- Nothing --\n");
+       }
+}
+
+/*
+ *     This routine actually executes the trade.
+ */
+static void
+do_trade(void)
+{
+       move_em(&trades[0], &trades[1]);
+       move_em(&trades[1], &trades[0]);
+}
+
+/*
+ *     This routine does a switch from one player to another
+ */
+static void
+move_em(TRADE *from, TRADE *to)
+{
+       PLAY *pl_fr, *pl_to;
+       OWN *op;
+
+       pl_fr = &play[from->trader];
+       pl_to = &play[to->trader];
+
+       pl_fr->money -= from->cash;
+       pl_to->money += from->cash;
+       pl_fr->num_gojf -= from->gojf;
+       pl_to->num_gojf += from->gojf;
+       for (op = from->prop_list; op; op = op->next) {
+               add_list(to->trader, &(pl_to->own_list), sqnum(op->sqr));
+               op->sqr->owner = to->trader;
+               del_list(from->trader, &(pl_fr->own_list), sqnum(op->sqr));
+       }
+       set_ownlist(to->trader);
+}
+
+/*
+ *     This routine lets a player resign
+ */
+void
+resign(void)
+{
+       int i, new_own;
+       OWN *op;
+       SQUARE *sqp;
+
+       if (cur_p->money <= 0) {
+               switch (board[cur_p->loc].type) {
+                 case UTIL:
+                 case RR:
+                 case PRPTY:
+                       new_own = board[cur_p->loc].owner;
+                       /* If you ran out of money by buying current location */
+                       if (new_own == player)
+                               new_own = num_play;
+                       break;
+                 default:              /* Chance, taxes, etc */
+                       new_own = num_play;
+                       break;
+               }
+               if (new_own == num_play)
+                       printf("You would resign to the bank\n");
+               else
+                       printf("You would resign to %s\n", name_list[new_own]);
+       }
+       else if (num_play == 1) {
+               new_own = num_play;
+               printf("You would resign to the bank\n");
+       }
+       else {
+               name_list[num_play] = "bank";
+               do {
+                       new_own = getinp("Who do you wish to resign to? ",
+                           name_list);
+                       if (new_own == player)
+                               printf("You can't resign to yourself!!\n");
+               } while (new_own == player);
+               name_list[num_play] = "done";
+       }
+       if (getyn("Do you really want to resign? ") != 0)
+               return;
+       if (num_play == 1) {
+               printf("Then NOBODY wins (not even YOU!)\n");
+               exit(0);
+       }
+       if (new_own < num_play) {       /* resign to player             */
+               printf("resigning to player\n");
+               trades[0].trader = new_own;
+               trades[0].cash = trades[0].gojf = 0;
+               trades[0].prop_list = NULL;
+               trades[1].trader = player;
+               trades[1].cash = cur_p->money > 0 ? cur_p->money : 0;
+               trades[1].gojf = cur_p->num_gojf;
+               trades[1].prop_list = cur_p->own_list;
+               do_trade();
+       }
+       else {                          /* resign to bank               */
+               printf("resigning to bank\n");
+               for (op = cur_p->own_list; op; op = op->next) {
+                       sqp = op->sqr;
+                       sqp->owner = -1;
+                       sqp->desc->morg = FALSE;
+                       if (sqp->type == PRPTY) {
+                               is_not_monop(sqp->desc->mon_desc);
+                               sqp->desc->houses = 0;
+                       }
+               }
+               if (cur_p->num_gojf)
+                       ret_card(cur_p);
+       }
+       free(play[player].name);
+       for (i = player; i < num_play; i++) {
+               name_list[i] = name_list[i+1];
+               if (i + 1 < num_play)
+                       play[i] = play[i+1];
+       }
+       name_list[num_play--] = NULL;
+       for (i = 0; i < N_SQRS; i++)
+               if (board[i].owner > player)
+                       --board[i].owner;
+       player = player == 0 ? num_play - 1 : player - 1;
+       next_play();
+       if (num_play < 2) {
+               printf("\nThen %s WINS!!!!!\n", play[0].name);
+               printhold(0);
+               printf("That's a grand worth of $%d.\n",
+                       play[0].money+prop_worth(&play[0]));
+               exit(0);
+       }
+}
index 8691ba3e3846976bb57e36d094e666e8a429953b..1f9545eb5978befd3ead51a1027ac0ca3f2ab458 100644 (file)
@@ -74,6 +74,7 @@
 2013/12/1 12:00:00,games/fortune
 2013/12/1 12:00:00,games/Makefile
 2013/12/1 12:00:00,games/Makefile.inc
+2013/12/1 12:00:00,games/monop
 2013/12/1 12:00:00,games/morse
 2013/12/1 12:00:00,games/number
 2013/12/1 12:00:00,games/pig