1 /* $NetBSD: cards.c,v 1.11 1999/12/30 01:40:08 simonb 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)cards.c 8.1 (Berkeley) 5/31/93"; 40 #else 41 __RCSID("$NetBSD: cards.c,v 1.11 1999/12/30 01:40:08 simonb Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/types.h> 46 #include <sys/endian.h> 47 #include "monop.ext" 48 #include "pathnames.h" 49 50 /* 51 * These routine deal with the card decks 52 */ 53 54 #define GOJF 'F' /* char for get-out-of-jail-free cards */ 55 56 #ifndef DEV 57 static const char *cardfile = _PATH_CARDS; 58 #else 59 static const char *cardfile = "cards.pck"; 60 #endif 61 62 static FILE *deckf; 63 64 static void set_up __P((DECK *)); 65 static void printmes __P((void)); 66 67 /* 68 * This routine initializes the decks from the data file, 69 * which it opens. 70 */ 71 void 72 init_decks() 73 { 74 int32_t nc; 75 76 if ((deckf=fopen(cardfile, "r")) == NULL) { 77 file_err: 78 perror(cardfile); 79 exit(1); 80 } 81 82 /* read number of community chest cards... */ 83 if (fread(&nc, sizeof(nc), 1, deckf) != 1) 84 goto file_err; 85 CC_D.num_cards = be32toh(nc); 86 /* ... and number of community chest cards. */ 87 if (fread(&nc, sizeof(nc), 1, deckf) != 1) 88 goto file_err; 89 CH_D.num_cards = be32toh(nc); 90 set_up(&CC_D); 91 set_up(&CH_D); 92 } 93 94 /* 95 * This routine sets up the offset pointers for the given deck. 96 */ 97 static void 98 set_up(dp) 99 DECK *dp; 100 { 101 int r1, r2; 102 int i; 103 104 dp->offsets = (off_t *) calloc(sizeof (off_t), dp->num_cards); 105 if (dp->offsets == NULL) 106 errx(1, "out of memory"); 107 if (fread(dp->offsets, sizeof(off_t), dp->num_cards, deckf) != 108 dp->num_cards) { 109 perror(cardfile); 110 exit(1); 111 } 112 /* convert offsets from big-endian byte order */ 113 for (i = 0; i < dp->num_cards; i++) 114 BE64TOH(dp->offsets[i]); 115 dp->last_card = 0; 116 dp->gojf_used = FALSE; 117 for (i = 0; i < dp->num_cards; i++) { 118 off_t temp; 119 120 r1 = roll(1, dp->num_cards) - 1; 121 r2 = roll(1, dp->num_cards) - 1; 122 temp = dp->offsets[r2]; 123 dp->offsets[r2] = dp->offsets[r1]; 124 dp->offsets[r1] = temp; 125 } 126 } 127 128 /* 129 * This routine draws a card from the given deck 130 */ 131 void 132 get_card(dp) 133 DECK *dp; 134 { 135 char type_maj, type_min; 136 int num; 137 int i, per_h, per_H, num_h, num_H; 138 OWN *op; 139 140 do { 141 fseek(deckf, dp->offsets[dp->last_card], SEEK_SET); 142 dp->last_card = ++(dp->last_card) % dp->num_cards; 143 type_maj = getc(deckf); 144 } while (dp->gojf_used && type_maj == GOJF); 145 type_min = getc(deckf); 146 num = ntohl(getw(deckf)); 147 printmes(); 148 switch (type_maj) { 149 case '+': /* get money */ 150 if (type_min == 'A') { 151 for (i = 0; i < num_play; i++) 152 if (i != player) 153 play[i].money -= num; 154 num = num * (num_play - 1); 155 } 156 cur_p->money += num; 157 break; 158 case '-': /* lose money */ 159 if (type_min == 'A') { 160 for (i = 0; i < num_play; i++) 161 if (i != player) 162 play[i].money += num; 163 num = num * (num_play - 1); 164 } 165 cur_p->money -= num; 166 break; 167 case 'M': /* move somewhere */ 168 switch (type_min) { 169 case 'F': /* move forward */ 170 num -= cur_p->loc; 171 if (num < 0) 172 num += 40; 173 break; 174 case 'J': /* move to jail */ 175 goto_jail(); 176 return; 177 case 'R': /* move to railroad */ 178 spec = TRUE; 179 num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc; 180 break; 181 case 'U': /* move to utility */ 182 spec = TRUE; 183 if (cur_p->loc >= 12 && cur_p->loc < 28) 184 num = 28 - cur_p->loc; 185 else { 186 num = 12 - cur_p->loc; 187 if (num < 0) 188 num += 40; 189 } 190 break; 191 case 'B': 192 num = -num; 193 break; 194 } 195 move(num); 196 break; 197 case 'T': /* tax */ 198 if (dp == &CC_D) { 199 per_h = 40; 200 per_H = 115; 201 } 202 else { 203 per_h = 25; 204 per_H = 100; 205 } 206 num_h = num_H = 0; 207 for (op = cur_p->own_list; op; op = op->next) 208 if (op->sqr->type == PRPTY) { 209 if (op->sqr->desc->houses == 5) 210 ++num_H; 211 else 212 num_h += op->sqr->desc->houses; 213 } 214 num = per_h * num_h + per_H * num_H; 215 printf( 216 "You had %d Houses and %d Hotels, so that cost you $%d\n", 217 num_h, num_H, num); 218 if (num == 0) 219 lucky(""); 220 else 221 cur_p->money -= num; 222 break; 223 case GOJF: /* get-out-of-jail-free card */ 224 cur_p->num_gojf++; 225 dp->gojf_used = TRUE; 226 break; 227 } 228 spec = FALSE; 229 } 230 231 /* 232 * This routine prints out the message on the card 233 */ 234 static void 235 printmes() 236 { 237 char c; 238 239 printline(); 240 fflush(stdout); 241 while ((c = getc(deckf)) != '\0') 242 putchar(c); 243 printline(); 244 fflush(stdout); 245 } 246