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