xref: /netbsd/games/monop/cards.c (revision 5b4f06a6)
1*5b4f06a6Sjnemeth /*	$NetBSD: cards.c,v 1.27 2014/12/29 10:38:52 jnemeth Exp $	*/
242fb1b9dScgd 
361f28255Scgd /*
442fb1b9dScgd  * Copyright (c) 1980, 1993
542fb1b9dScgd  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
15e5aeb4eaSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32b118ad22Schristos #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3442fb1b9dScgd #if 0
3542fb1b9dScgd static char sccsid[] = "@(#)cards.c	8.1 (Berkeley) 5/31/93";
3642fb1b9dScgd #else
37*5b4f06a6Sjnemeth __RCSID("$NetBSD: cards.c,v 1.27 2014/12/29 10:38:52 jnemeth Exp $");
3842fb1b9dScgd #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd 
41e28c4221Ssimonb #include <sys/types.h>
42e28c4221Ssimonb #include <sys/endian.h>
43b51259daSdholland #include "monop.h"
44b51259daSdholland #include "deck.h"
4561f28255Scgd 
4661f28255Scgd /*
4761f28255Scgd  *	These routine deal with the card decks
4861f28255Scgd  */
4961f28255Scgd 
5097464386Sdholland static void set_up(DECK *);
5197464386Sdholland static void printmes(const char *text);
5297464386Sdholland 
5361f28255Scgd #define	GOJF	'F'	/* char for get-out-of-jail-free cards	*/
5461f28255Scgd 
5597464386Sdholland struct cardinfo {
5697464386Sdholland 	const char *actioncode;
5797464386Sdholland 	const char *text;
5897464386Sdholland };
5961f28255Scgd 
6097464386Sdholland static const struct cardinfo cc_cards[] = {
6197464386Sdholland 	{ "FF",
6297464386Sdholland 		">> GET OUT OF JAIL FREE <<\n"
6397464386Sdholland 		"Keep this card until needed or sold\n"
6497464386Sdholland 	},
6597464386Sdholland 	{ "++25",
6697464386Sdholland 		"Receive for Services $25.\n"
6797464386Sdholland 	},
6897464386Sdholland 	{ "++200",
6997464386Sdholland 		"Bank Error in Your Favor.\n"
7097464386Sdholland 		"Collect $200.\n"
7197464386Sdholland 	},
7297464386Sdholland 	{ "++20",
7397464386Sdholland 		"Income Tax Refund.\n"
7497464386Sdholland 		"Collect $20.\n"
7597464386Sdholland 	},
7697464386Sdholland 	{ "--100",
7797464386Sdholland 		"Pay Hospital $100\n"
7897464386Sdholland 	},
7997464386Sdholland 	{ "++100",
8097464386Sdholland 		"Life Insurance Matures.\n"
8197464386Sdholland 		"Collect $100\n"
8297464386Sdholland 	},
8397464386Sdholland 	{ "++45",
8497464386Sdholland 		"From sale of Stock You get $45.\n"
8597464386Sdholland 	},
8697464386Sdholland 	{ "TX",
8797464386Sdholland 		"You are Assessed for street repairs.\n"
8897464386Sdholland 		"\t$40 per House\n"
8997464386Sdholland 		"\t$115 per Hotel\n"
9097464386Sdholland 	},
9197464386Sdholland 	{ "++100",
9297464386Sdholland 		"X-mas Fund Matures.\n"
9397464386Sdholland 	  	"Collect $100.\n"
9497464386Sdholland 	},
9597464386Sdholland 	{ "++11",
9697464386Sdholland 		"You have won Second Prize in a Beauty Contest\n"
9797464386Sdholland 		"Collect $11\n"
9897464386Sdholland 	},
9997464386Sdholland 	{ "MF0",
10097464386Sdholland 		"Advance to GO\n"
10197464386Sdholland 		"(Collect $200)\n"
10297464386Sdholland 	},
10397464386Sdholland 	{ "++100",
10497464386Sdholland 		"You inherit $100\n"
10597464386Sdholland 	},
10697464386Sdholland 	{ "--150",
10797464386Sdholland 		"Pay School Tax of $150.\n"
10897464386Sdholland 	},
10997464386Sdholland 	{ "MJ",
11097464386Sdholland 		"\t\t>> GO TO JAIL <<\n"
11197464386Sdholland 	  	"Go Directly to Jail. Do not pass GO  Do not collect $200.\n"
11297464386Sdholland 	},
11397464386Sdholland 	{ "+A50",
11497464386Sdholland 		"\t\t>> GRAND OPERA OPENING <<\n"
11597464386Sdholland 		"Collect $50 from each player for opening night seats.\n"
11697464386Sdholland 	},
11797464386Sdholland 	{ "--50",
11897464386Sdholland 		"Doctor's Fee:  Pay $50.\n"
11997464386Sdholland 	}
12097464386Sdholland };
12161f28255Scgd 
12297464386Sdholland static const struct cardinfo ch_cards[] = {
12397464386Sdholland 	{ "FF",
12497464386Sdholland 		">> GET OUT OF JAIL FREE <<\n"
12597464386Sdholland 		"Keep this card until needed or sold\n"
12697464386Sdholland 	},
12797464386Sdholland 	{ "MR",
12897464386Sdholland 		"Advance to the nearest Railroad, and pay owner\n"
12997464386Sdholland 		"Twice the rental to which he is otherwise entitled.\n"
13097464386Sdholland 		"If Railroad is unowned you may buy it from the bank\n"
13197464386Sdholland 	},
13297464386Sdholland 	{ "MU",
13397464386Sdholland 		"Advance to the nearest Utility.\n"
13497464386Sdholland 		"If unowned, you may buy it from the bank.\n"
135*5b4f06a6Sjnemeth 		"If owned, throw dice and pay owner a total of ten times\n"
13697464386Sdholland 		"the amount thrown.\n"
13797464386Sdholland 	},
13897464386Sdholland 	{ "MB3",
13997464386Sdholland 		"Go Back 3 Spaces\n"
14097464386Sdholland 	},
14197464386Sdholland 	{ "MR",
14297464386Sdholland 		"Advance to the nearest Railroad, and pay owner\n"
14397464386Sdholland 		"Twice the rental to which he is otherwise entitled.\n"
14497464386Sdholland 		"If Railroad is unowned you may buy it from the bank\n"
14597464386Sdholland 	},
14697464386Sdholland 	{ "MJ",
14797464386Sdholland 		"    >> GO DIRECTLY TO JAIL <<\n"
14897464386Sdholland 		"Do not pass GO, Do not Collect $200.\n"
14997464386Sdholland 	},
15097464386Sdholland 	{ "MF5",
15197464386Sdholland 		"Take a Ride on the Reading.\n"
15297464386Sdholland 		"If you pass GO, collect $200.\n"
15397464386Sdholland 	},
15497464386Sdholland 	{ "MF39",
15597464386Sdholland 		"Take a Walk on the Board Walk.\n"
15697464386Sdholland 		"    (Advance To Board Walk)\n"
15797464386Sdholland 	},
15897464386Sdholland 	{ "MF24",
15997464386Sdholland 		"Advance to Illinois Ave.\n"
16097464386Sdholland 	},
16197464386Sdholland 	{ "MF0",
16297464386Sdholland 		"Advance to Go\n"
16397464386Sdholland 	},
16497464386Sdholland 	{ "MF11",
16597464386Sdholland 		"Advance to St. Charles Place.\n"
16697464386Sdholland 		"If you pass GO, collect $200.\n"
16797464386Sdholland 	},
16897464386Sdholland 	{ "TX",
16997464386Sdholland 		"Make general repairs on all of your Property.\n"
17097464386Sdholland 		"For Each House pay $25.\n"
17197464386Sdholland 		"For Each Hotel pay $100.\n"
17297464386Sdholland 	},
17397464386Sdholland 	{ "-A50",
17497464386Sdholland 		"You have been elected Chairman of the Board.\n"
17597464386Sdholland 		"Pay each player $50.\n"
17697464386Sdholland 	},
17797464386Sdholland 	{ "--15",
17897464386Sdholland 		"Pay Poor Tax of $15\n"
17997464386Sdholland 	},
18097464386Sdholland 	{ "++50",
18197464386Sdholland 		"Bank pays you Dividend of $50.\n"
18297464386Sdholland 	},
18397464386Sdholland 	{ "++150",
18497464386Sdholland 		"Your Building and Loan Matures.\n"
18597464386Sdholland 		"Collect $150.\n"
18697464386Sdholland 	}
18797464386Sdholland };
188b118ad22Schristos 
18961f28255Scgd /*
19097464386Sdholland  * This routine initializes the decks from the data above.
19161f28255Scgd  */
192b118ad22Schristos void
init_decks(void)193adf10d74Sdholland init_decks(void)
194b118ad22Schristos {
19597464386Sdholland 	CC_D.info = cc_cards;
19697464386Sdholland 	CC_D.num_cards = sizeof(cc_cards) / sizeof(cc_cards[0]);
19797464386Sdholland 	CH_D.info = ch_cards;
19897464386Sdholland 	CH_D.num_cards = sizeof(ch_cards) / sizeof(ch_cards[0]);
19961f28255Scgd 	set_up(&CC_D);
20061f28255Scgd 	set_up(&CH_D);
20161f28255Scgd }
202e42b2048Ssimonb 
20361f28255Scgd /*
20461f28255Scgd  *	This routine sets up the offset pointers for the given deck.
20561f28255Scgd  */
206b118ad22Schristos static void
set_up(DECK * dp)207adf10d74Sdholland set_up(DECK *dp)
208e42b2048Ssimonb {
209b118ad22Schristos 	int r1, r2;
21061f28255Scgd 	int i;
21161f28255Scgd 
212dc11f84dSchristos 	dp->cards = calloc((size_t)dp->num_cards, sizeof(dp->cards[0]));
21397464386Sdholland 	if (dp->cards == NULL)
214a9c7f9b0Sjsm 		errx(1, "out of memory");
21597464386Sdholland 
216e28c4221Ssimonb 	for (i = 0; i < dp->num_cards; i++)
21797464386Sdholland 		dp->cards[i] = i;
21897464386Sdholland 
21982ff30a4Sdholland 	dp->top_card = 0;
22061f28255Scgd 	dp->gojf_used = FALSE;
22197464386Sdholland 
22261f28255Scgd 	for (i = 0; i < dp->num_cards; i++) {
22397464386Sdholland 		int temp;
22461f28255Scgd 
22561f28255Scgd 		r1 = roll(1, dp->num_cards) - 1;
22661f28255Scgd 		r2 = roll(1, dp->num_cards) - 1;
22797464386Sdholland 		temp = dp->cards[r2];
22897464386Sdholland 		dp->cards[r2] = dp->cards[r1];
22997464386Sdholland 		dp->cards[r1] = temp;
23061f28255Scgd 	}
23161f28255Scgd }
232e42b2048Ssimonb 
23361f28255Scgd /*
23461f28255Scgd  *	This routine draws a card from the given deck
23561f28255Scgd  */
236b118ad22Schristos void
get_card(DECK * dp)237adf10d74Sdholland get_card(DECK *dp)
238b118ad22Schristos {
239b118ad22Schristos 	char type_maj, type_min;
240b118ad22Schristos 	int num;
24161f28255Scgd 	int i, per_h, per_H, num_h, num_H;
24261f28255Scgd 	OWN *op;
24397464386Sdholland 	const struct cardinfo *thiscard;
24461f28255Scgd 
24561f28255Scgd 	do {
24697464386Sdholland 		thiscard = &dp->info[dp->top_card];
24797464386Sdholland 		type_maj = thiscard->actioncode[0];
24885288e8bSdholland 		dp->top_card = (dp->top_card + 1) % dp->num_cards;
24961f28255Scgd 	} while (dp->gojf_used && type_maj == GOJF);
25097464386Sdholland 	type_min = thiscard->actioncode[1];
25197464386Sdholland 	num = atoi(thiscard->actioncode+2);
25297464386Sdholland 
25397464386Sdholland 	printmes(thiscard->text);
25461f28255Scgd 	switch (type_maj) {
25561f28255Scgd 	  case '+':		/* get money		*/
25661f28255Scgd 		if (type_min == 'A') {
25761f28255Scgd 			for (i = 0; i < num_play; i++)
25861f28255Scgd 				if (i != player)
25961f28255Scgd 					play[i].money -= num;
26061f28255Scgd 			num = num * (num_play - 1);
26161f28255Scgd 		}
26261f28255Scgd 		cur_p->money += num;
26361f28255Scgd 		break;
26461f28255Scgd 	  case '-':		/* lose money		*/
26561f28255Scgd 		if (type_min == 'A') {
26661f28255Scgd 			for (i = 0; i < num_play; i++)
26761f28255Scgd 				if (i != player)
26861f28255Scgd 					play[i].money += num;
26961f28255Scgd 			num = num * (num_play - 1);
27061f28255Scgd 		}
27161f28255Scgd 		cur_p->money -= num;
27261f28255Scgd 		break;
27361f28255Scgd 	  case 'M':		/* move somewhere	*/
27461f28255Scgd 		switch (type_min) {
27561f28255Scgd 		  case 'F':		/* move forward	*/
27661f28255Scgd 			num -= cur_p->loc;
27761f28255Scgd 			if (num < 0)
27861f28255Scgd 				num += 40;
27961f28255Scgd 			break;
28061f28255Scgd 		  case 'J':		/* move to jail	*/
28161f28255Scgd 			goto_jail();
28261f28255Scgd 			return;
28361f28255Scgd 		  case 'R':		/* move to railroad	*/
28461f28255Scgd 			spec = TRUE;
28561f28255Scgd 			num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc;
28661f28255Scgd 			break;
28761f28255Scgd 		  case 'U':		/* move to utility	*/
28861f28255Scgd 			spec = TRUE;
28961f28255Scgd 			if (cur_p->loc >= 12 && cur_p->loc < 28)
29061f28255Scgd 				num = 28 - cur_p->loc;
29161f28255Scgd 			else {
29261f28255Scgd 				num = 12 - cur_p->loc;
29361f28255Scgd 				if (num < 0)
29461f28255Scgd 					num += 40;
29561f28255Scgd 			}
29661f28255Scgd 			break;
29761f28255Scgd 		  case 'B':
29861f28255Scgd 			num = -num;
29961f28255Scgd 			break;
30061f28255Scgd 		}
30161f28255Scgd 		move(num);
30261f28255Scgd 		break;
30361f28255Scgd 	  case 'T':			/* tax			*/
30461f28255Scgd 		if (dp == &CC_D) {
30561f28255Scgd 			per_h = 40;
30661f28255Scgd 			per_H = 115;
30761f28255Scgd 		}
30861f28255Scgd 		else {
30961f28255Scgd 			per_h = 25;
31061f28255Scgd 			per_H = 100;
31161f28255Scgd 		}
31261f28255Scgd 		num_h = num_H = 0;
31361f28255Scgd 		for (op = cur_p->own_list; op; op = op->next)
31404afeca6Sveego 			if (op->sqr->type == PRPTY) {
31561f28255Scgd 				if (op->sqr->desc->houses == 5)
31661f28255Scgd 					++num_H;
31761f28255Scgd 				else
31861f28255Scgd 					num_h += op->sqr->desc->houses;
31904afeca6Sveego 			}
32061f28255Scgd 		num = per_h * num_h + per_H * num_H;
321e42b2048Ssimonb 		printf(
322e42b2048Ssimonb 		    "You had %d Houses and %d Hotels, so that cost you $%d\n",
323e42b2048Ssimonb 		    num_h, num_H, num);
32461f28255Scgd 		if (num == 0)
32561f28255Scgd 			lucky("");
32661f28255Scgd 		else
32761f28255Scgd 			cur_p->money -= num;
32861f28255Scgd 		break;
32961f28255Scgd 	  case GOJF:		/* get-out-of-jail-free card	*/
33061f28255Scgd 		cur_p->num_gojf++;
33161f28255Scgd 		dp->gojf_used = TRUE;
33261f28255Scgd 		break;
33361f28255Scgd 	}
33461f28255Scgd 	spec = FALSE;
33561f28255Scgd }
336b118ad22Schristos 
33761f28255Scgd /*
33861f28255Scgd  *	This routine prints out the message on the card
33961f28255Scgd  */
340b118ad22Schristos static void
printmes(const char * text)34197464386Sdholland printmes(const char *text)
342e42b2048Ssimonb {
34397464386Sdholland 	int i;
34461f28255Scgd 
34561f28255Scgd 	printline();
34661f28255Scgd 	fflush(stdout);
34797464386Sdholland 	for (i = 0; text[i] != '\0'; i++)
34897464386Sdholland 		putchar(text[i]);
34961f28255Scgd 	printline();
35061f28255Scgd 	fflush(stdout);
35161f28255Scgd }
3528b5e597aSdholland 
3538b5e597aSdholland /*
3548b5e597aSdholland  *	This routine returns the players get-out-of-jail-free card
35561715c12Sdholland  * to the bottom of a deck.  XXX currently does not return to the correct
35661715c12Sdholland  * deck.
3578b5e597aSdholland  */
3588b5e597aSdholland void
ret_card(PLAY * plr)359adf10d74Sdholland ret_card(PLAY *plr)
3608b5e597aSdholland {
36161715c12Sdholland 	char type_maj;
36261715c12Sdholland 	int gojfpos, last_card;
36361715c12Sdholland 	int i;
36461715c12Sdholland 	DECK *dp;
365dc11f84dSchristos 	int temp;
36661715c12Sdholland 
3678b5e597aSdholland 	plr->num_gojf--;
3688b5e597aSdholland 	if (CC_D.gojf_used)
36961715c12Sdholland 		dp = &CC_D;
3708b5e597aSdholland 	else
37161715c12Sdholland 		dp = &CH_D;
37261715c12Sdholland 	dp->gojf_used = FALSE;
37361715c12Sdholland 
37461715c12Sdholland 	/* Put at bottom of deck (top_card - 1) and remove it from wherever else
37561715c12Sdholland 	 * it used to be.
37661715c12Sdholland 	 */
37761715c12Sdholland 	last_card = dp->top_card - 1;
37861715c12Sdholland 	if (last_card < 0)
37961715c12Sdholland 		last_card += dp->num_cards;
38061715c12Sdholland 	gojfpos = dp->top_card;
38161715c12Sdholland 	do {
38261715c12Sdholland 		gojfpos = (gojfpos + 1) % dp->num_cards;
38397464386Sdholland 		type_maj = dp->info[gojfpos].actioncode[0];
38461715c12Sdholland 	} while (type_maj != GOJF);
38597464386Sdholland 	temp = dp->cards[gojfpos];
38661715c12Sdholland 	/* Only one of the next two loops does anything */
38761715c12Sdholland 	for (i = gojfpos - 1; i > last_card; i--)
38897464386Sdholland 		dp->cards[i + 1] = dp->cards[i];
38961715c12Sdholland 	for (i = gojfpos; i < last_card; i++)
39097464386Sdholland 		dp->cards[i] = dp->cards[i + 1];
39161715c12Sdholland 	if (gojfpos > last_card) {
39297464386Sdholland 		dp->cards[dp->top_card] = temp;
39361715c12Sdholland 		dp->top_card++;
39461715c12Sdholland 		dp->top_card %= dp->num_cards;
39561715c12Sdholland 	} else
39697464386Sdholland 		dp->cards[last_card] = temp;
3978b5e597aSdholland }
398