1*11c3b524SAaron LI /* $NetBSD: cards.c,v 1.27 2014/12/29 10:38:52 jnemeth Exp $ */
2*11c3b524SAaron LI
3*11c3b524SAaron LI /*
4*11c3b524SAaron LI * Copyright (c) 1980, 1993
5*11c3b524SAaron LI * The Regents of the University of California. All rights reserved.
6*11c3b524SAaron LI *
7*11c3b524SAaron LI * Redistribution and use in source and binary forms, with or without
8*11c3b524SAaron LI * modification, are permitted provided that the following conditions
9*11c3b524SAaron LI * are met:
10*11c3b524SAaron LI * 1. Redistributions of source code must retain the above copyright
11*11c3b524SAaron LI * notice, this list of conditions and the following disclaimer.
12*11c3b524SAaron LI * 2. Redistributions in binary form must reproduce the above copyright
13*11c3b524SAaron LI * notice, this list of conditions and the following disclaimer in the
14*11c3b524SAaron LI * documentation and/or other materials provided with the distribution.
15*11c3b524SAaron LI * 3. Neither the name of the University nor the names of its contributors
16*11c3b524SAaron LI * may be used to endorse or promote products derived from this software
17*11c3b524SAaron LI * without specific prior written permission.
18*11c3b524SAaron LI *
19*11c3b524SAaron LI * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*11c3b524SAaron LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*11c3b524SAaron LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*11c3b524SAaron LI * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*11c3b524SAaron LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*11c3b524SAaron LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*11c3b524SAaron LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*11c3b524SAaron LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*11c3b524SAaron LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*11c3b524SAaron LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*11c3b524SAaron LI * SUCH DAMAGE.
30*11c3b524SAaron LI *
31*11c3b524SAaron LI * @(#)cards.c 8.1 (Berkeley) 5/31/93
32*11c3b524SAaron LI */
33*11c3b524SAaron LI
34*11c3b524SAaron LI #include <sys/types.h>
35*11c3b524SAaron LI #include <sys/endian.h>
36*11c3b524SAaron LI #include "monop.h"
37*11c3b524SAaron LI #include "deck.h"
38*11c3b524SAaron LI
39*11c3b524SAaron LI /*
40*11c3b524SAaron LI * These routine deal with the card decks
41*11c3b524SAaron LI */
42*11c3b524SAaron LI
43*11c3b524SAaron LI static void set_up(DECK *);
44*11c3b524SAaron LI static void printmes(const char *text);
45*11c3b524SAaron LI
46*11c3b524SAaron LI #define GOJF 'F' /* char for get-out-of-jail-free cards */
47*11c3b524SAaron LI
48*11c3b524SAaron LI struct cardinfo {
49*11c3b524SAaron LI const char *actioncode;
50*11c3b524SAaron LI const char *text;
51*11c3b524SAaron LI };
52*11c3b524SAaron LI
53*11c3b524SAaron LI static const struct cardinfo cc_cards[] = {
54*11c3b524SAaron LI { "FF",
55*11c3b524SAaron LI ">> GET OUT OF JAIL FREE <<\n"
56*11c3b524SAaron LI "Keep this card until needed or sold\n"
57*11c3b524SAaron LI },
58*11c3b524SAaron LI { "++25",
59*11c3b524SAaron LI "Receive for Services $25.\n"
60*11c3b524SAaron LI },
61*11c3b524SAaron LI { "++200",
62*11c3b524SAaron LI "Bank Error in Your Favor.\n"
63*11c3b524SAaron LI "Collect $200.\n"
64*11c3b524SAaron LI },
65*11c3b524SAaron LI { "++20",
66*11c3b524SAaron LI "Income Tax Refund.\n"
67*11c3b524SAaron LI "Collect $20.\n"
68*11c3b524SAaron LI },
69*11c3b524SAaron LI { "--100",
70*11c3b524SAaron LI "Pay Hospital $100\n"
71*11c3b524SAaron LI },
72*11c3b524SAaron LI { "++100",
73*11c3b524SAaron LI "Life Insurance Matures.\n"
74*11c3b524SAaron LI "Collect $100\n"
75*11c3b524SAaron LI },
76*11c3b524SAaron LI { "++45",
77*11c3b524SAaron LI "From sale of Stock You get $45.\n"
78*11c3b524SAaron LI },
79*11c3b524SAaron LI { "TX",
80*11c3b524SAaron LI "You are Assessed for street repairs.\n"
81*11c3b524SAaron LI "\t$40 per House\n"
82*11c3b524SAaron LI "\t$115 per Hotel\n"
83*11c3b524SAaron LI },
84*11c3b524SAaron LI { "++100",
85*11c3b524SAaron LI "X-mas Fund Matures.\n"
86*11c3b524SAaron LI "Collect $100.\n"
87*11c3b524SAaron LI },
88*11c3b524SAaron LI { "++11",
89*11c3b524SAaron LI "You have won Second Prize in a Beauty Contest\n"
90*11c3b524SAaron LI "Collect $11\n"
91*11c3b524SAaron LI },
92*11c3b524SAaron LI { "MF0",
93*11c3b524SAaron LI "Advance to GO\n"
94*11c3b524SAaron LI "(Collect $200)\n"
95*11c3b524SAaron LI },
96*11c3b524SAaron LI { "++100",
97*11c3b524SAaron LI "You inherit $100\n"
98*11c3b524SAaron LI },
99*11c3b524SAaron LI { "--150",
100*11c3b524SAaron LI "Pay School Tax of $150.\n"
101*11c3b524SAaron LI },
102*11c3b524SAaron LI { "MJ",
103*11c3b524SAaron LI "\t\t>> GO TO JAIL <<\n"
104*11c3b524SAaron LI "Go Directly to Jail. Do not pass GO Do not collect $200.\n"
105*11c3b524SAaron LI },
106*11c3b524SAaron LI { "+A50",
107*11c3b524SAaron LI "\t\t>> GRAND OPERA OPENING <<\n"
108*11c3b524SAaron LI "Collect $50 from each player for opening night seats.\n"
109*11c3b524SAaron LI },
110*11c3b524SAaron LI { "--50",
111*11c3b524SAaron LI "Doctor's Fee: Pay $50.\n"
112*11c3b524SAaron LI }
113*11c3b524SAaron LI };
114*11c3b524SAaron LI
115*11c3b524SAaron LI static const struct cardinfo ch_cards[] = {
116*11c3b524SAaron LI { "FF",
117*11c3b524SAaron LI ">> GET OUT OF JAIL FREE <<\n"
118*11c3b524SAaron LI "Keep this card until needed or sold\n"
119*11c3b524SAaron LI },
120*11c3b524SAaron LI { "MR",
121*11c3b524SAaron LI "Advance to the nearest Railroad, and pay owner\n"
122*11c3b524SAaron LI "Twice the rental to which he is otherwise entitled.\n"
123*11c3b524SAaron LI "If Railroad is unowned you may buy it from the bank\n"
124*11c3b524SAaron LI },
125*11c3b524SAaron LI { "MU",
126*11c3b524SAaron LI "Advance to the nearest Utility.\n"
127*11c3b524SAaron LI "If unowned, you may buy it from the bank.\n"
128*11c3b524SAaron LI "If owned, throw dice and pay owner a total of ten times\n"
129*11c3b524SAaron LI "the amount thrown.\n"
130*11c3b524SAaron LI },
131*11c3b524SAaron LI { "MB3",
132*11c3b524SAaron LI "Go Back 3 Spaces\n"
133*11c3b524SAaron LI },
134*11c3b524SAaron LI { "MR",
135*11c3b524SAaron LI "Advance to the nearest Railroad, and pay owner\n"
136*11c3b524SAaron LI "Twice the rental to which he is otherwise entitled.\n"
137*11c3b524SAaron LI "If Railroad is unowned you may buy it from the bank\n"
138*11c3b524SAaron LI },
139*11c3b524SAaron LI { "MJ",
140*11c3b524SAaron LI " >> GO DIRECTLY TO JAIL <<\n"
141*11c3b524SAaron LI "Do not pass GO, Do not Collect $200.\n"
142*11c3b524SAaron LI },
143*11c3b524SAaron LI { "MF5",
144*11c3b524SAaron LI "Take a Ride on the Reading.\n"
145*11c3b524SAaron LI "If you pass GO, collect $200.\n"
146*11c3b524SAaron LI },
147*11c3b524SAaron LI { "MF39",
148*11c3b524SAaron LI "Take a Walk on the Board Walk.\n"
149*11c3b524SAaron LI " (Advance To Board Walk)\n"
150*11c3b524SAaron LI },
151*11c3b524SAaron LI { "MF24",
152*11c3b524SAaron LI "Advance to Illinois Ave.\n"
153*11c3b524SAaron LI },
154*11c3b524SAaron LI { "MF0",
155*11c3b524SAaron LI "Advance to Go\n"
156*11c3b524SAaron LI },
157*11c3b524SAaron LI { "MF11",
158*11c3b524SAaron LI "Advance to St. Charles Place.\n"
159*11c3b524SAaron LI "If you pass GO, collect $200.\n"
160*11c3b524SAaron LI },
161*11c3b524SAaron LI { "TX",
162*11c3b524SAaron LI "Make general repairs on all of your Property.\n"
163*11c3b524SAaron LI "For Each House pay $25.\n"
164*11c3b524SAaron LI "For Each Hotel pay $100.\n"
165*11c3b524SAaron LI },
166*11c3b524SAaron LI { "-A50",
167*11c3b524SAaron LI "You have been elected Chairman of the Board.\n"
168*11c3b524SAaron LI "Pay each player $50.\n"
169*11c3b524SAaron LI },
170*11c3b524SAaron LI { "--15",
171*11c3b524SAaron LI "Pay Poor Tax of $15\n"
172*11c3b524SAaron LI },
173*11c3b524SAaron LI { "++50",
174*11c3b524SAaron LI "Bank pays you Dividend of $50.\n"
175*11c3b524SAaron LI },
176*11c3b524SAaron LI { "++150",
177*11c3b524SAaron LI "Your Building and Loan Matures.\n"
178*11c3b524SAaron LI "Collect $150.\n"
179*11c3b524SAaron LI }
180*11c3b524SAaron LI };
181*11c3b524SAaron LI
182*11c3b524SAaron LI /*
183*11c3b524SAaron LI * This routine initializes the decks from the data above.
184*11c3b524SAaron LI */
185*11c3b524SAaron LI void
init_decks(void)186*11c3b524SAaron LI init_decks(void)
187*11c3b524SAaron LI {
188*11c3b524SAaron LI CC_D.info = cc_cards;
189*11c3b524SAaron LI CC_D.num_cards = sizeof(cc_cards) / sizeof(cc_cards[0]);
190*11c3b524SAaron LI CH_D.info = ch_cards;
191*11c3b524SAaron LI CH_D.num_cards = sizeof(ch_cards) / sizeof(ch_cards[0]);
192*11c3b524SAaron LI set_up(&CC_D);
193*11c3b524SAaron LI set_up(&CH_D);
194*11c3b524SAaron LI }
195*11c3b524SAaron LI
196*11c3b524SAaron LI /*
197*11c3b524SAaron LI * This routine sets up the offset pointers for the given deck.
198*11c3b524SAaron LI */
199*11c3b524SAaron LI static void
set_up(DECK * dp)200*11c3b524SAaron LI set_up(DECK *dp)
201*11c3b524SAaron LI {
202*11c3b524SAaron LI int r1, r2;
203*11c3b524SAaron LI int i;
204*11c3b524SAaron LI
205*11c3b524SAaron LI dp->cards = calloc((size_t)dp->num_cards, sizeof(dp->cards[0]));
206*11c3b524SAaron LI if (dp->cards == NULL)
207*11c3b524SAaron LI errx(1, "out of memory");
208*11c3b524SAaron LI
209*11c3b524SAaron LI for (i = 0; i < dp->num_cards; i++)
210*11c3b524SAaron LI dp->cards[i] = i;
211*11c3b524SAaron LI
212*11c3b524SAaron LI dp->top_card = 0;
213*11c3b524SAaron LI dp->gojf_used = FALSE;
214*11c3b524SAaron LI
215*11c3b524SAaron LI for (i = 0; i < dp->num_cards; i++) {
216*11c3b524SAaron LI int temp;
217*11c3b524SAaron LI
218*11c3b524SAaron LI r1 = roll(1, dp->num_cards) - 1;
219*11c3b524SAaron LI r2 = roll(1, dp->num_cards) - 1;
220*11c3b524SAaron LI temp = dp->cards[r2];
221*11c3b524SAaron LI dp->cards[r2] = dp->cards[r1];
222*11c3b524SAaron LI dp->cards[r1] = temp;
223*11c3b524SAaron LI }
224*11c3b524SAaron LI }
225*11c3b524SAaron LI
226*11c3b524SAaron LI /*
227*11c3b524SAaron LI * This routine draws a card from the given deck
228*11c3b524SAaron LI */
229*11c3b524SAaron LI void
get_card(DECK * dp)230*11c3b524SAaron LI get_card(DECK *dp)
231*11c3b524SAaron LI {
232*11c3b524SAaron LI char type_maj, type_min;
233*11c3b524SAaron LI int num;
234*11c3b524SAaron LI int i, per_h, per_H, num_h, num_H;
235*11c3b524SAaron LI OWN *op;
236*11c3b524SAaron LI const struct cardinfo *thiscard;
237*11c3b524SAaron LI
238*11c3b524SAaron LI do {
239*11c3b524SAaron LI thiscard = &dp->info[dp->top_card];
240*11c3b524SAaron LI type_maj = thiscard->actioncode[0];
241*11c3b524SAaron LI dp->top_card = (dp->top_card + 1) % dp->num_cards;
242*11c3b524SAaron LI } while (dp->gojf_used && type_maj == GOJF);
243*11c3b524SAaron LI type_min = thiscard->actioncode[1];
244*11c3b524SAaron LI num = atoi(thiscard->actioncode+2);
245*11c3b524SAaron LI
246*11c3b524SAaron LI printmes(thiscard->text);
247*11c3b524SAaron LI switch (type_maj) {
248*11c3b524SAaron LI case '+': /* get money */
249*11c3b524SAaron LI if (type_min == 'A') {
250*11c3b524SAaron LI for (i = 0; i < num_play; i++)
251*11c3b524SAaron LI if (i != player)
252*11c3b524SAaron LI play[i].money -= num;
253*11c3b524SAaron LI num = num * (num_play - 1);
254*11c3b524SAaron LI }
255*11c3b524SAaron LI cur_p->money += num;
256*11c3b524SAaron LI break;
257*11c3b524SAaron LI case '-': /* lose money */
258*11c3b524SAaron LI if (type_min == 'A') {
259*11c3b524SAaron LI for (i = 0; i < num_play; i++)
260*11c3b524SAaron LI if (i != player)
261*11c3b524SAaron LI play[i].money += num;
262*11c3b524SAaron LI num = num * (num_play - 1);
263*11c3b524SAaron LI }
264*11c3b524SAaron LI cur_p->money -= num;
265*11c3b524SAaron LI break;
266*11c3b524SAaron LI case 'M': /* move somewhere */
267*11c3b524SAaron LI switch (type_min) {
268*11c3b524SAaron LI case 'F': /* move forward */
269*11c3b524SAaron LI num -= cur_p->loc;
270*11c3b524SAaron LI if (num < 0)
271*11c3b524SAaron LI num += 40;
272*11c3b524SAaron LI break;
273*11c3b524SAaron LI case 'J': /* move to jail */
274*11c3b524SAaron LI goto_jail();
275*11c3b524SAaron LI return;
276*11c3b524SAaron LI case 'R': /* move to railroad */
277*11c3b524SAaron LI spec = TRUE;
278*11c3b524SAaron LI num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc;
279*11c3b524SAaron LI break;
280*11c3b524SAaron LI case 'U': /* move to utility */
281*11c3b524SAaron LI spec = TRUE;
282*11c3b524SAaron LI if (cur_p->loc >= 12 && cur_p->loc < 28)
283*11c3b524SAaron LI num = 28 - cur_p->loc;
284*11c3b524SAaron LI else {
285*11c3b524SAaron LI num = 12 - cur_p->loc;
286*11c3b524SAaron LI if (num < 0)
287*11c3b524SAaron LI num += 40;
288*11c3b524SAaron LI }
289*11c3b524SAaron LI break;
290*11c3b524SAaron LI case 'B':
291*11c3b524SAaron LI num = -num;
292*11c3b524SAaron LI break;
293*11c3b524SAaron LI }
294*11c3b524SAaron LI move(num);
295*11c3b524SAaron LI break;
296*11c3b524SAaron LI case 'T': /* tax */
297*11c3b524SAaron LI if (dp == &CC_D) {
298*11c3b524SAaron LI per_h = 40;
299*11c3b524SAaron LI per_H = 115;
300*11c3b524SAaron LI }
301*11c3b524SAaron LI else {
302*11c3b524SAaron LI per_h = 25;
303*11c3b524SAaron LI per_H = 100;
304*11c3b524SAaron LI }
305*11c3b524SAaron LI num_h = num_H = 0;
306*11c3b524SAaron LI for (op = cur_p->own_list; op; op = op->next)
307*11c3b524SAaron LI if (op->sqr->type == PRPTY) {
308*11c3b524SAaron LI if (op->sqr->desc->houses == 5)
309*11c3b524SAaron LI ++num_H;
310*11c3b524SAaron LI else
311*11c3b524SAaron LI num_h += op->sqr->desc->houses;
312*11c3b524SAaron LI }
313*11c3b524SAaron LI num = per_h * num_h + per_H * num_H;
314*11c3b524SAaron LI printf(
315*11c3b524SAaron LI "You had %d Houses and %d Hotels, so that cost you $%d\n",
316*11c3b524SAaron LI num_h, num_H, num);
317*11c3b524SAaron LI if (num == 0)
318*11c3b524SAaron LI lucky("");
319*11c3b524SAaron LI else
320*11c3b524SAaron LI cur_p->money -= num;
321*11c3b524SAaron LI break;
322*11c3b524SAaron LI case GOJF: /* get-out-of-jail-free card */
323*11c3b524SAaron LI cur_p->num_gojf++;
324*11c3b524SAaron LI dp->gojf_used = TRUE;
325*11c3b524SAaron LI break;
326*11c3b524SAaron LI }
327*11c3b524SAaron LI spec = FALSE;
328*11c3b524SAaron LI }
329*11c3b524SAaron LI
330*11c3b524SAaron LI /*
331*11c3b524SAaron LI * This routine prints out the message on the card
332*11c3b524SAaron LI */
333*11c3b524SAaron LI static void
printmes(const char * text)334*11c3b524SAaron LI printmes(const char *text)
335*11c3b524SAaron LI {
336*11c3b524SAaron LI int i;
337*11c3b524SAaron LI
338*11c3b524SAaron LI printline();
339*11c3b524SAaron LI fflush(stdout);
340*11c3b524SAaron LI for (i = 0; text[i] != '\0'; i++)
341*11c3b524SAaron LI putchar(text[i]);
342*11c3b524SAaron LI printline();
343*11c3b524SAaron LI fflush(stdout);
344*11c3b524SAaron LI }
345*11c3b524SAaron LI
346*11c3b524SAaron LI /*
347*11c3b524SAaron LI * This routine returns the players get-out-of-jail-free card
348*11c3b524SAaron LI * to the bottom of a deck. XXX currently does not return to the correct
349*11c3b524SAaron LI * deck.
350*11c3b524SAaron LI */
351*11c3b524SAaron LI void
ret_card(PLAY * plr)352*11c3b524SAaron LI ret_card(PLAY *plr)
353*11c3b524SAaron LI {
354*11c3b524SAaron LI char type_maj;
355*11c3b524SAaron LI int gojfpos, last_card;
356*11c3b524SAaron LI int i;
357*11c3b524SAaron LI DECK *dp;
358*11c3b524SAaron LI int temp;
359*11c3b524SAaron LI
360*11c3b524SAaron LI plr->num_gojf--;
361*11c3b524SAaron LI if (CC_D.gojf_used)
362*11c3b524SAaron LI dp = &CC_D;
363*11c3b524SAaron LI else
364*11c3b524SAaron LI dp = &CH_D;
365*11c3b524SAaron LI dp->gojf_used = FALSE;
366*11c3b524SAaron LI
367*11c3b524SAaron LI /* Put at bottom of deck (top_card - 1) and remove it from wherever else
368*11c3b524SAaron LI * it used to be.
369*11c3b524SAaron LI */
370*11c3b524SAaron LI last_card = dp->top_card - 1;
371*11c3b524SAaron LI if (last_card < 0)
372*11c3b524SAaron LI last_card += dp->num_cards;
373*11c3b524SAaron LI gojfpos = dp->top_card;
374*11c3b524SAaron LI do {
375*11c3b524SAaron LI gojfpos = (gojfpos + 1) % dp->num_cards;
376*11c3b524SAaron LI type_maj = dp->info[gojfpos].actioncode[0];
377*11c3b524SAaron LI } while (type_maj != GOJF);
378*11c3b524SAaron LI temp = dp->cards[gojfpos];
379*11c3b524SAaron LI /* Only one of the next two loops does anything */
380*11c3b524SAaron LI for (i = gojfpos - 1; i > last_card; i--)
381*11c3b524SAaron LI dp->cards[i + 1] = dp->cards[i];
382*11c3b524SAaron LI for (i = gojfpos; i < last_card; i++)
383*11c3b524SAaron LI dp->cards[i] = dp->cards[i + 1];
384*11c3b524SAaron LI if (gojfpos > last_card) {
385*11c3b524SAaron LI dp->cards[dp->top_card] = temp;
386*11c3b524SAaron LI dp->top_card++;
387*11c3b524SAaron LI dp->top_card %= dp->num_cards;
388*11c3b524SAaron LI } else
389*11c3b524SAaron LI dp->cards[last_card] = temp;
390*11c3b524SAaron LI }
391