1 /* $OpenBSD: cards.c,v 1.8 2003/06/03 03:01:40 millert Exp $ */ 2 /* $NetBSD: cards.c,v 1.3 1995/03/23 08:34:35 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1980, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)cards.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 static const char rcsid[] = "$OpenBSD: cards.c,v 1.8 2003/06/03 03:01:40 millert Exp $"; 38 #endif 39 #endif /* not lint */ 40 41 #include <err.h> 42 #include "monop.ext" 43 #include "pathnames.h" 44 45 /* 46 * These routine deal with the card decks 47 */ 48 49 #define GOJF 'F' /* char for get-out-of-jail-free cards */ 50 51 static char *cardfile = _PATH_CARDS; 52 53 static FILE *deckf; 54 55 static void set_up(DECK *); 56 static void printmes(void); 57 58 /* 59 * This routine initializes the decks from the data file, 60 * which it opens. 61 */ 62 void 63 init_decks() 64 { 65 if ((deckf = fopen(cardfile, "r")) == NULL) 66 file_err: 67 err(1, "%s", cardfile); 68 if (fread(&deck[0].num_cards, sizeof(deck[0].num_cards), 1, deckf) != 1) 69 goto file_err; 70 if (fread(&deck[0].top_card, sizeof(deck[0].top_card), 1, deckf) != 1) 71 goto file_err; 72 if (fread(&deck[0].gojf_used, sizeof(deck[0].gojf_used), 1, deckf) != 1) 73 goto file_err; 74 deck[0].num_cards = ntohs(deck[0].num_cards); 75 deck[0].top_card = ntohs(deck[0].top_card); 76 77 if (fread(&deck[1].num_cards, sizeof(deck[1].num_cards), 1, deckf) != 1) 78 goto file_err; 79 if (fread(&deck[1].top_card, sizeof(deck[1].top_card), 1, deckf) != 1) 80 goto file_err; 81 if (fread(&deck[1].gojf_used, sizeof(deck[1].gojf_used), 1, deckf) != 1) 82 goto file_err; 83 deck[1].num_cards = ntohs(deck[1].num_cards); 84 deck[1].top_card = ntohs(deck[1].top_card); 85 86 set_up(&CC_D); 87 set_up(&CH_D); 88 } 89 /* 90 * This routine sets up the offset pointers for the given deck. 91 */ 92 static void 93 set_up(dp) 94 DECK *dp; 95 { 96 int r1, r2; 97 int i; 98 99 if ((dp->offsets = (int32_t *) calloc(dp->num_cards, sizeof (int32_t))) == NULL) 100 err(1, NULL); 101 for (i = 0 ; i < dp->num_cards ; i++) { 102 if (fread(&dp->offsets[i], sizeof(dp->offsets[i]), 1, deckf) != 1) 103 err(1, "%s", cardfile); 104 dp->offsets[i] = ntohl(dp->offsets[i]); 105 } 106 dp->top_card = 0; 107 dp->gojf_used = FALSE; 108 for (i = 0; i < dp->num_cards; i++) { 109 long temp; 110 111 r1 = roll(1, dp->num_cards) - 1; 112 r2 = roll(1, dp->num_cards) - 1; 113 temp = dp->offsets[r2]; 114 dp->offsets[r2] = dp->offsets[r1]; 115 dp->offsets[r1] = temp; 116 } 117 } 118 /* 119 * This routine draws a card from the given deck 120 */ 121 void 122 get_card(dp) 123 DECK *dp; 124 { 125 char type_maj, type_min; 126 int16_t num; 127 int i, per_h, per_H, num_h, num_H; 128 OWN *op; 129 130 do { 131 fseek(deckf, dp->offsets[dp->top_card], SEEK_SET); 132 dp->top_card = ++(dp->top_card) % dp->num_cards; 133 type_maj = getc(deckf); 134 } while (dp->gojf_used && type_maj == GOJF); 135 type_min = getc(deckf); 136 fread(&num, sizeof(num), 1, deckf); 137 num = ntohs(num); 138 printmes(); 139 switch (type_maj) { 140 case '+': /* get money */ 141 if (type_min == 'A') { 142 for (i = 0; i < num_play; i++) 143 if (i != player) 144 play[i].money -= num; 145 num = num * (num_play - 1); 146 } 147 cur_p->money += num; 148 break; 149 case '-': /* lose 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 'M': /* move somewhere */ 159 switch (type_min) { 160 case 'F': /* move forward */ 161 num -= cur_p->loc; 162 if (num < 0) 163 num += 40; 164 break; 165 case 'J': /* move to jail */ 166 goto_jail(); 167 return; 168 case 'R': /* move to railroad */ 169 spec = TRUE; 170 num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc; 171 break; 172 case 'U': /* move to utility */ 173 spec = TRUE; 174 if (cur_p->loc >= 12 && cur_p->loc < 28) 175 num = 28 - cur_p->loc; 176 else { 177 num = 12 - cur_p->loc; 178 if (num < 0) 179 num += 40; 180 } 181 break; 182 case 'B': 183 num = -num; 184 break; 185 } 186 move(num); 187 break; 188 case 'T': /* tax */ 189 if (dp == &CC_D) { 190 per_h = 40; 191 per_H = 115; 192 } 193 else { 194 per_h = 25; 195 per_H = 100; 196 } 197 num_h = num_H = 0; 198 for (op = cur_p->own_list; op; op = op->next) 199 if (op->sqr->type == PRPTY) { 200 if (op->sqr->desc->houses == 5) 201 ++num_H; 202 else 203 num_h += op->sqr->desc->houses; 204 } 205 num = per_h * num_h + per_H * num_H; 206 printf("You had %d Houses and %d Hotels, so that cost you $%d\n", num_h, num_H, num); 207 if (num == 0) 208 lucky(""); 209 else 210 cur_p->money -= num; 211 break; 212 case GOJF: /* get-out-of-jail-free card */ 213 cur_p->num_gojf++; 214 dp->gojf_used = TRUE; 215 break; 216 } 217 spec = FALSE; 218 } 219 220 /* 221 * This routine prints out the message on the card 222 */ 223 static void 224 printmes() 225 { 226 char c; 227 228 printline(); 229 fflush(stdout); 230 while ((c = getc(deckf)) != '\0') 231 putchar(c); 232 printline(); 233 fflush(stdout); 234 } 235 236 /* 237 * This routine returns the players get-out-of-jail-free card 238 * to the bottom of a deck. XXX currently does not return to the correct 239 * deck. 240 */ 241 void 242 ret_card(plr) 243 PLAY *plr; 244 { 245 char type_maj; 246 int16_t gojfpos, last_card; 247 int i; 248 DECK *dp; 249 int32_t temp; 250 251 plr->num_gojf--; 252 if (CC_D.gojf_used) 253 dp = &CC_D; 254 else 255 dp = &CH_D; 256 dp->gojf_used = FALSE; 257 258 /* Put at bottom of deck (top_card - 1) and remove it from wherever else 259 * it used to be. 260 */ 261 last_card = dp->top_card - 1; 262 if (last_card < 0) 263 last_card += dp->num_cards; 264 gojfpos = dp->top_card; 265 do { 266 gojfpos = (gojfpos + 1) % dp->num_cards; 267 fseek(deckf, dp->offsets[gojfpos], SEEK_SET); 268 type_maj = getc(deckf); 269 } while (type_maj != GOJF); 270 temp = dp->offsets[gojfpos]; 271 /* Only one of the next two loops does anything */ 272 for (i = gojfpos - 1; i > last_card; i--) 273 dp->offsets[i + 1] = dp->offsets[i]; 274 for (i = gojfpos; i < last_card; i++) 275 dp->offsets[i] = dp->offsets[i + 1]; 276 if (gojfpos > last_card) { 277 dp->offsets[dp->top_card] = temp; 278 dp->top_card++; 279 dp->top_card %= dp->num_cards; 280 } else 281 dp->offsets[last_card] = temp; 282 } 283