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