Home | History | Annotate | Line # | Download | only in monop
      1 /*	$NetBSD: cards.c,v 1.27 2014/12/29 10:38:52 jnemeth 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.27 2014/12/29 10:38:52 jnemeth 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 owner 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(void)
    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(DECK *dp)
    208 {
    209 	int r1, r2;
    210 	int i;
    211 
    212 	dp->cards = calloc((size_t)dp->num_cards, sizeof(dp->cards[0]));
    213 	if (dp->cards == NULL)
    214 		errx(1, "out of memory");
    215 
    216 	for (i = 0; i < dp->num_cards; i++)
    217 		dp->cards[i] = i;
    218 
    219 	dp->top_card = 0;
    220 	dp->gojf_used = FALSE;
    221 
    222 	for (i = 0; i < dp->num_cards; i++) {
    223 		int temp;
    224 
    225 		r1 = roll(1, dp->num_cards) - 1;
    226 		r2 = roll(1, dp->num_cards) - 1;
    227 		temp = dp->cards[r2];
    228 		dp->cards[r2] = dp->cards[r1];
    229 		dp->cards[r1] = temp;
    230 	}
    231 }
    232 
    233 /*
    234  *	This routine draws a card from the given deck
    235  */
    236 void
    237 get_card(DECK *dp)
    238 {
    239 	char type_maj, type_min;
    240 	int num;
    241 	int i, per_h, per_H, num_h, num_H;
    242 	OWN *op;
    243 	const struct cardinfo *thiscard;
    244 
    245 	do {
    246 		thiscard = &dp->info[dp->top_card];
    247 		type_maj = thiscard->actioncode[0];
    248 		dp->top_card = (dp->top_card + 1) % dp->num_cards;
    249 	} while (dp->gojf_used && type_maj == GOJF);
    250 	type_min = thiscard->actioncode[1];
    251 	num = atoi(thiscard->actioncode+2);
    252 
    253 	printmes(thiscard->text);
    254 	switch (type_maj) {
    255 	  case '+':		/* get money		*/
    256 		if (type_min == 'A') {
    257 			for (i = 0; i < num_play; i++)
    258 				if (i != player)
    259 					play[i].money -= num;
    260 			num = num * (num_play - 1);
    261 		}
    262 		cur_p->money += num;
    263 		break;
    264 	  case '-':		/* lose money		*/
    265 		if (type_min == 'A') {
    266 			for (i = 0; i < num_play; i++)
    267 				if (i != player)
    268 					play[i].money += num;
    269 			num = num * (num_play - 1);
    270 		}
    271 		cur_p->money -= num;
    272 		break;
    273 	  case 'M':		/* move somewhere	*/
    274 		switch (type_min) {
    275 		  case 'F':		/* move forward	*/
    276 			num -= cur_p->loc;
    277 			if (num < 0)
    278 				num += 40;
    279 			break;
    280 		  case 'J':		/* move to jail	*/
    281 			goto_jail();
    282 			return;
    283 		  case 'R':		/* move to railroad	*/
    284 			spec = TRUE;
    285 			num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc;
    286 			break;
    287 		  case 'U':		/* move to utility	*/
    288 			spec = TRUE;
    289 			if (cur_p->loc >= 12 && cur_p->loc < 28)
    290 				num = 28 - cur_p->loc;
    291 			else {
    292 				num = 12 - cur_p->loc;
    293 				if (num < 0)
    294 					num += 40;
    295 			}
    296 			break;
    297 		  case 'B':
    298 			num = -num;
    299 			break;
    300 		}
    301 		move(num);
    302 		break;
    303 	  case 'T':			/* tax			*/
    304 		if (dp == &CC_D) {
    305 			per_h = 40;
    306 			per_H = 115;
    307 		}
    308 		else {
    309 			per_h = 25;
    310 			per_H = 100;
    311 		}
    312 		num_h = num_H = 0;
    313 		for (op = cur_p->own_list; op; op = op->next)
    314 			if (op->sqr->type == PRPTY) {
    315 				if (op->sqr->desc->houses == 5)
    316 					++num_H;
    317 				else
    318 					num_h += op->sqr->desc->houses;
    319 			}
    320 		num = per_h * num_h + per_H * num_H;
    321 		printf(
    322 		    "You had %d Houses and %d Hotels, so that cost you $%d\n",
    323 		    num_h, num_H, num);
    324 		if (num == 0)
    325 			lucky("");
    326 		else
    327 			cur_p->money -= num;
    328 		break;
    329 	  case GOJF:		/* get-out-of-jail-free card	*/
    330 		cur_p->num_gojf++;
    331 		dp->gojf_used = TRUE;
    332 		break;
    333 	}
    334 	spec = FALSE;
    335 }
    336 
    337 /*
    338  *	This routine prints out the message on the card
    339  */
    340 static void
    341 printmes(const char *text)
    342 {
    343 	int i;
    344 
    345 	printline();
    346 	fflush(stdout);
    347 	for (i = 0; text[i] != '\0'; i++)
    348 		putchar(text[i]);
    349 	printline();
    350 	fflush(stdout);
    351 }
    352 
    353 /*
    354  *	This routine returns the players get-out-of-jail-free card
    355  * to the bottom of a deck.  XXX currently does not return to the correct
    356  * deck.
    357  */
    358 void
    359 ret_card(PLAY *plr)
    360 {
    361 	char type_maj;
    362 	int gojfpos, last_card;
    363 	int i;
    364 	DECK *dp;
    365 	int temp;
    366 
    367 	plr->num_gojf--;
    368 	if (CC_D.gojf_used)
    369 		dp = &CC_D;
    370 	else
    371 		dp = &CH_D;
    372 	dp->gojf_used = FALSE;
    373 
    374 	/* Put at bottom of deck (top_card - 1) and remove it from wherever else
    375 	 * it used to be.
    376 	 */
    377 	last_card = dp->top_card - 1;
    378 	if (last_card < 0)
    379 		last_card += dp->num_cards;
    380 	gojfpos = dp->top_card;
    381 	do {
    382 		gojfpos = (gojfpos + 1) % dp->num_cards;
    383 		type_maj = dp->info[gojfpos].actioncode[0];
    384 	} while (type_maj != GOJF);
    385 	temp = dp->cards[gojfpos];
    386 	/* Only one of the next two loops does anything */
    387 	for (i = gojfpos - 1; i > last_card; i--)
    388 		dp->cards[i + 1] = dp->cards[i];
    389 	for (i = gojfpos; i < last_card; i++)
    390 		dp->cards[i] = dp->cards[i + 1];
    391 	if (gojfpos > last_card) {
    392 		dp->cards[dp->top_card] = temp;
    393 		dp->top_card++;
    394 		dp->top_card %= dp->num_cards;
    395 	} else
    396 		dp->cards[last_card] = temp;
    397 }
    398