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