Annotation of src/games/monop/monop.c, Revision 1.23
1.23 ! dholland 1: /* $NetBSD: monop.c,v 1.22 2008/02/24 03:56:49 christos Exp $ */
1.3 cgd 2:
1.1 cgd 3: /*
1.3 cgd 4: * Copyright (c) 1980, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.14 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.4 christos 32: #include <sys/cdefs.h>
1.1 cgd 33: #ifndef lint
1.4 christos 34: __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
35: The Regents of the University of California. All rights reserved.\n");
1.1 cgd 36: #endif /* not lint */
37:
38: #ifndef lint
1.3 cgd 39: #if 0
40: static char sccsid[] = "@(#)monop.c 8.1 (Berkeley) 5/31/93";
41: #else
1.23 ! dholland 42: __RCSID("$NetBSD: monop.c,v 1.22 2008/02/24 03:56:49 christos Exp $");
1.3 cgd 43: #endif
1.1 cgd 44: #endif /* not lint */
45:
1.4 christos 46: #include <stdio.h>
47: #include <signal.h>
48: #include <stdlib.h>
1.18 dholland 49: #include <time.h>
1.4 christos 50: #include <unistd.h>
1.21 dholland 51: #include "deck.h"
52: #include "monop.h"
1.4 christos 53:
1.15 jsm 54: int main(int, char *[]);
55: static void getplayers(void);
56: static void init_players(void);
57: static void init_monops(void);
58: static void do_quit(int);
1.1 cgd 59:
1.21 dholland 60:
61: bool fixing, /* set if fixing up debt */
62: trading, /* set if in process of trading */
63: told_em, /* set if told user he's out of debt */
64: spec; /* set if moving by card to RR or UTIL */
65:
66: const char *name_list[MAX_PL+2], /* list of players' names */
67: *const comlist[] = { /* list of normal commands */
68: "quit", /* 0 */ "print", /* 1 */
69: "where", /* 2 */ "own holdings", /* 3 */
70: "holdings", /* 4 */ "mortgage", /* 5 */
71: "unmortgage", /* 6 */ "buy houses", /* 7 */
72: "sell houses", /* 8 */ "card", /* 9 */
73: "pay", /* 10 */ "trade", /* 11 */
74: "resign", /* 12 */ "save", /* 13 */
75: "restore", /* 14 */ "roll", /* 15 */
76: "", /* 16 */
77: 0
78: },
79: *const yncoms[] = { /* list of commands for yes/no answers */
80: "yes", /* 0 */ "no", /* 1 */
81: "quit", /* 2 */ "print", /* 3 */
82: "where", /* 4 */ "own holdings", /* 5 */
83: "holdings", /* 6 */
84: 0
85: },
86: *const lucky_mes[] = { /* "got lucky" messages */
87: "You lucky stiff", "You got lucky",
88: "What a lucky person!", "You must have a 4-leaf clover",
89: "My, my! Aren't we lucky!", "Luck smiles upon you",
90: "You got lucky this time", "Lucky person!",
91: "Your karma must certainly be together",
92: "How beautifully Cosmic", "Wow, you must be really with it"
93: /* "I want your autograph", -- Save for later */
94: };
95:
96: int player, /* current player number */
97: num_play, /* current number of players */
98: num_doub, /* # of doubles current player rolled */
99: /* # of "got lucky" messages */
100: num_luck = sizeof lucky_mes / sizeof (char *);
101:
102: /* list of command functions */
103: void (*const func[])(void) = { /* array of function calls for commands */
104: quit, /* quit game |* 0 *| */
105: printboard, /* print board |* 1 *| */
106: where, /* where players are |* 2 *| */
107: list, /* own holdings |* 3 *| */
108: list_all, /* holdings list |* 4 *| */
109: mortgage, /* mortgage property |* 5 *| */
110: unmortgage, /* unmortgage property |* 6 *| */
111: buy_houses, /* buy houses |* 7 *| */
112: sell_houses, /* sell houses |* 8 *| */
113: card, /* card for jail |* 9 *| */
114: pay, /* pay for jail |* 10 *| */
115: trade, /* trade |* 11 *| */
116: resign, /* resign |* 12 *| */
117: save, /* save game |* 13 *| */
118: restore, /* restore game |* 14 *| */
119: do_move, /* roll |* 15 *| */
120: do_move /* "" |* 16 *| */
121: };
122:
123: DECK deck[2]; /* Chance and Community Chest */
124:
125: PLAY *play, /* player structure array ("calloc"ed) */
126: *cur_p; /* pointer to current player's struct */
127:
128: RR_S rr[N_RR]; /* railroad descriptions */
129:
130: UTIL_S util[2]; /* utility descriptions */
131:
132: #define MONINIT(num_in, h_cost, not_m, mon_n, sq1,sq2,sq3) \
133: {0, -1, num_in, 0, h_cost, not_m, mon_n, {sq1,sq2,sq3}, {0,0,0}}
134: /* name owner num_own sq */
135:
136: MON mon[N_MON] = { /* monopoly descriptions */
137: /* num_in h_cost not_m mon_n sqnums */
138: MONINIT(2, 1, "Purple", "PURPLE", 1,3, 0),
139: MONINIT(3, 1, "Lt. Blue", "LT. BLUE", 6,8,9),
140: MONINIT(3, 2, "Violet", "VIOLET", 11,13,14),
141: MONINIT(3, 2, "Orange", "ORANGE", 16,18,19),
142: MONINIT(3, 3, "Red", "RED", 21,23,24),
143: MONINIT(3, 3, "Yellow", "YELLOW", 26,27,29),
144: MONINIT(3, 4, "Green", "GREEN", 31,32,34),
145: MONINIT(2, 4, "Dk. Blue", "DK. BLUE", 37,39, 0),
146: };
147: #undef MONINIT
148:
149: PROP prop[N_PROP] = { /* typical properties */
150: /* morg monop square houses mon_desc rent */
151: {0, 0, 1, 0, &mon[0], { 2, 10, 30, 90, 160, 250} },
152: {0, 0, 3, 0, &mon[0], { 4, 20, 60, 180, 320, 450} },
153: {0, 0, 6, 0, &mon[1], { 6, 30, 90, 270, 400, 550} },
154: {0, 0, 7, 0, &mon[1], { 6, 30, 90, 270, 400, 550} },
155: {0, 0, 9, 0, &mon[1], { 8, 40,100, 300, 450, 600} },
156: {0, 0, 11, 0, &mon[2], {10, 50,150, 450, 625, 750} },
157: {0, 0, 13, 0, &mon[2], {10, 50,150, 450, 625, 750} },
158: {0, 0, 14, 0, &mon[2], {12, 60,180, 500, 700, 900} },
159: {0, 0, 16, 0, &mon[3], {14, 70,200, 550, 750, 950} },
160: {0, 0, 17, 0, &mon[3], {14, 70,200, 550, 750, 950} },
161: {0, 0, 19, 0, &mon[3], {16, 80,220, 600, 800,1000} },
162: {0, 0, 21, 0, &mon[4], {18, 90,250, 700, 875,1050} },
163: {0, 0, 23, 0, &mon[4], {18, 90,250, 700, 875,1050} },
164: {0, 0, 24, 0, &mon[4], {20,100,300, 750, 925,1100} },
165: {0, 0, 26, 0, &mon[5], {22,110,330, 800, 975,1150} },
166: {0, 0, 27, 0, &mon[5], {22,110,330, 800, 975,1150} },
167: {0, 0, 29, 0, &mon[5], {24,120,360, 850,1025,1200} },
168: {0, 0, 31, 0, &mon[6], {26,130,390, 900,1100,1275} },
169: {0, 0, 32, 0, &mon[6], {26,130,390, 900,1100,1275} },
170: {0, 0, 34, 0, &mon[6], {28,150,450,1000,1200,1400} },
171: {0, 0, 37, 0, &mon[7], {35,175,500,1100,1300,1500} },
172: {0, 0, 39, 0, &mon[7], {50,200,600,1400,1700,2000} }
173: };
174:
175: SQUARE board[N_SQRS+1] = { /* board itself (+1 for Jail) */
176: /* name (COLOR) owner type desc cost */
177:
178: {"=== GO ===", -1, SAFE, NULL, 0 },
179: {"Mediterranean Ave. (P)", -1, PRPTY, &prop[0], 60 },
180: {"Community Chest i", -1, CC, NULL, 0 },
181: {"Baltic Ave. (P)", -1, PRPTY, &prop[1], 60 },
182: {"Income Tax", -1, INC_TAX, NULL, 0 },
183: {"Reading RR", -1, RR, &rr[0], 200 },
184: {"Oriental Ave. (L)", -1, PRPTY, &prop[2], 100 },
185: {"Chance i", -1, CHANCE, NULL, 0 },
186: {"Vermont Ave. (L)", -1, PRPTY, &prop[3], 100 },
187: {"Connecticut Ave. (L)", -1, PRPTY, &prop[4], 120 },
188: {"Just Visiting", -1, SAFE, NULL, 0 },
189: {"St. Charles Pl. (V)", -1, PRPTY, &prop[5], 140 },
190: {"Electric Co.", -1, UTIL, &util[0], 150 },
191: {"States Ave. (V)", -1, PRPTY, &prop[6], 140 },
192: {"Virginia Ave. (V)", -1, PRPTY, &prop[7], 160 },
193: {"Pennsylvania RR", -1, RR, &rr[1], 200 },
194: {"St. James Pl. (O)", -1, PRPTY, &prop[8], 180 },
195: {"Community Chest ii", -1, CC, NULL, 0 },
196: {"Tennessee Ave. (O)", -1, PRPTY, &prop[9], 180 },
197: {"New York Ave. (O)", -1, PRPTY, &prop[10], 200 },
198: {"Free Parking", -1, SAFE, NULL, 0 },
199: {"Kentucky Ave. (R)", -1, PRPTY, &prop[11], 220 },
200: {"Chance ii", -1, CHANCE, NULL, 0 },
201: {"Indiana Ave. (R)", -1, PRPTY, &prop[12], 220 },
202: {"Illinois Ave. (R)", -1, PRPTY, &prop[13], 240 },
203: {"B&O RR", -1, RR, &rr[2], 200 },
204: {"Atlantic Ave. (Y)", -1, PRPTY, &prop[14], 260 },
205: {"Ventnor Ave. (Y)", -1, PRPTY, &prop[15], 260 },
206: {"Water Works", -1, UTIL, &util[1], 150 },
207: {"Marvin Gardens (Y)", -1, PRPTY, &prop[16], 280 },
208: {"GO TO JAIL", -1, GOTO_J, NULL, 0 },
209: {"Pacific Ave. (G)", -1, PRPTY, &prop[17], 300 },
210: {"N. Carolina Ave. (G)", -1, PRPTY, &prop[18], 300 },
211: {"Community Chest iii", -1, CC, NULL, 0 },
212: {"Pennsylvania Ave. (G)", -1, PRPTY, &prop[19], 320 },
213: {"Short Line RR", -1, RR, &rr[3], 200 },
214: {"Chance iii", -1, CHANCE, NULL, 0 },
215: {"Park Place (D)", -1, PRPTY, &prop[20], 350 },
216: {"Luxury Tax", -1, LUX_TAX, NULL, 0 },
217: {"Boardwalk (D)", -1, PRPTY, &prop[21], 400 },
218: {"JAIL", -1, IN_JAIL, NULL, 0 }
219: };
220:
221:
1.1 cgd 222: /*
223: * This program implements a monopoly game
224: */
1.4 christos 225: int
1.1 cgd 226: main(ac, av)
1.6 simonb 227: int ac;
228: char *av[];
229: {
1.9 jsm 230: /* Revoke setgid privileges */
1.11 mycroft 231: setgid(getgid());
1.9 jsm 232:
1.22 christos 233: srandom((unsigned long)time(NULL));
1.19 dholland 234: num_luck = sizeof lucky_mes / sizeof (char *);
235: init_decks();
236: init_monops();
1.1 cgd 237: if (ac > 1) {
1.23 ! dholland 238: if (rest_f(av[1]) < 0)
1.1 cgd 239: restore();
240: }
241: else {
242: getplayers();
243: init_players();
244: }
1.5 hubertf 245: signal(SIGINT, do_quit);
1.1 cgd 246: for (;;) {
247: printf("\n%s (%d) (cash $%d) on %s\n", cur_p->name, player + 1,
248: cur_p->money, board[cur_p->loc].name);
249: printturn();
250: force_morg();
251: execute(getinp("-- Command: ", comlist));
252: }
253: }
1.4 christos 254:
255: /*ARGSUSED*/
256: static void
257: do_quit(n)
1.16 perry 258: int n __unused;
1.4 christos 259: {
260: quit();
261: }
1.6 simonb 262:
1.1 cgd 263: /*
264: * This routine gets the names of the players
265: */
1.4 christos 266: static void
267: getplayers()
268: {
1.6 simonb 269: int i, j;
270: char buf[257];
1.1 cgd 271:
272: blew_it:
273: for (;;) {
1.19 dholland 274: if ((num_play = get_int("How many players? ")) <= 1 ||
1.1 cgd 275: num_play > MAX_PL)
1.19 dholland 276: printf("Sorry. Number must range from 2 to %d\n",
277: MAX_PL);
1.1 cgd 278: else
279: break;
280: }
1.22 christos 281: cur_p = play = calloc((size_t)num_play, sizeof (PLAY));
1.8 jsm 282: if (play == NULL)
1.10 jsm 283: err(1, NULL);
1.1 cgd 284: for (i = 0; i < num_play; i++) {
1.19 dholland 285: do {
286: printf("Player %d's name: ", i + 1);
287: fgets(buf, sizeof(buf), stdin);
288: if (feof(stdin)) {
289: printf("End of file on stdin\n");
290: exit(0);
291: }
292: buf[strcspn(buf, "\n")] = '\0';
293: } while (strlen(buf) == 0);
294: name_list[i] = play[i].name = strdup(buf);
1.8 jsm 295: if (name_list[i] == NULL)
1.10 jsm 296: err(1, NULL);
1.1 cgd 297: play[i].money = 1500;
298: }
299: name_list[i++] = "done";
300: name_list[i] = 0;
301: for (i = 0; i < num_play; i++)
1.19 dholland 302: for (j = i + 1; j <= num_play; j++)
1.1 cgd 303: if (strcasecmp(name_list[i], name_list[j]) == 0) {
1.19 dholland 304: if (j != num_play)
1.6 simonb 305: printf("Hey!!! Some of those are "
306: "IDENTICAL!! Let's try that "
1.19 dholland 307: "again...\n");
1.1 cgd 308: else
1.6 simonb 309: printf("\"done\" is a reserved word. "
310: "Please try again\n");
1.1 cgd 311: for (i = 0; i < num_play; i++)
1.4 christos 312: free(play[i].name);
313: free(play);
1.1 cgd 314: goto blew_it;
315: }
316: }
1.6 simonb 317:
1.1 cgd 318: /*
319: * This routine figures out who goes first
320: */
1.4 christos 321: static void
322: init_players()
323: {
1.6 simonb 324: int i, rl, cur_max;
325: bool over = 0;
326: int max_pl = 0;
1.1 cgd 327:
328: again:
329: putchar('\n');
330: for (cur_max = i = 0; i < num_play; i++) {
331: printf("%s (%d) rolls %d\n", play[i].name, i+1, rl=roll(2, 6));
332: if (rl > cur_max) {
333: over = FALSE;
334: cur_max = rl;
335: max_pl = i;
336: }
337: else if (rl == cur_max)
338: over++;
339: }
340: if (over) {
341: printf("%d people rolled the same thing, so we'll try again\n",
342: over + 1);
343: goto again;
344: }
345: player = max_pl;
346: cur_p = &play[max_pl];
347: printf("%s (%d) goes first\n", cur_p->name, max_pl + 1);
348: }
1.6 simonb 349:
1.1 cgd 350: /*
1.12 wiz 351: * This routine initializes the monopoly structures.
1.1 cgd 352: */
1.4 christos 353: static void
1.17 dholland 354: init_monops()
1.4 christos 355: {
1.6 simonb 356: MON *mp;
357: int i;
1.1 cgd 358:
359: for (mp = mon; mp < &mon[N_MON]; mp++) {
360: mp->name = mp->not_m;
361: for (i = 0; i < mp->num_in; i++)
362: mp->sq[i] = &board[mp->sqnums[i]];
363: }
364: }
CVSweb <webmaster@jp.NetBSD.org>