1 /* $OpenBSD: cards.c,v 1.12 2016/01/08 18:20:33 mestre 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 #include <err.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 37 #include "monop.ext" 38 #include "pathnames.h" 39 40 /* 41 * These routine deal with the card decks 42 */ 43 44 #define GOJF 'F' /* char for get-out-of-jail-free cards */ 45 46 static char *cardfile = _PATH_CARDS; 47 48 static FILE *deckf; 49 50 static void set_up(DECK *); 51 static void printmes(void); 52 53 /* 54 * This routine initializes the decks from the data file, 55 * which it opens. 56 */ 57 void 58 init_decks(void) 59 { 60 if ((deckf = fopen(cardfile, "r")) == NULL) 61 file_err: 62 err(1, "%s", cardfile); 63 if (fread(&deck[0].num_cards, sizeof(deck[0].num_cards), 1, deckf) != 1) 64 goto file_err; 65 if (fread(&deck[0].top_card, sizeof(deck[0].top_card), 1, deckf) != 1) 66 goto file_err; 67 if (fread(&deck[0].gojf_used, sizeof(deck[0].gojf_used), 1, deckf) != 1) 68 goto file_err; 69 deck[0].num_cards = ntohs(deck[0].num_cards); 70 deck[0].top_card = ntohs(deck[0].top_card); 71 72 if (fread(&deck[1].num_cards, sizeof(deck[1].num_cards), 1, deckf) != 1) 73 goto file_err; 74 if (fread(&deck[1].top_card, sizeof(deck[1].top_card), 1, deckf) != 1) 75 goto file_err; 76 if (fread(&deck[1].gojf_used, sizeof(deck[1].gojf_used), 1, deckf) != 1) 77 goto file_err; 78 deck[1].num_cards = ntohs(deck[1].num_cards); 79 deck[1].top_card = ntohs(deck[1].top_card); 80 81 set_up(&CC_D); 82 set_up(&CH_D); 83 } 84 /* 85 * This routine sets up the offset pointers for the given deck. 86 */ 87 static void 88 set_up(DECK *dp) 89 { 90 int r1, r2; 91 int i; 92 93 if ((dp->offsets = calloc(dp->num_cards, sizeof (int32_t))) == NULL) 94 err(1, NULL); 95 for (i = 0 ; i < dp->num_cards ; i++) { 96 if (fread(&dp->offsets[i], sizeof(dp->offsets[i]), 1, deckf) != 1) 97 err(1, "%s", cardfile); 98 dp->offsets[i] = ntohl(dp->offsets[i]); 99 } 100 dp->top_card = 0; 101 dp->gojf_used = FALSE; 102 for (i = 0; i < dp->num_cards; i++) { 103 long temp; 104 105 r1 = roll(1, dp->num_cards) - 1; 106 r2 = roll(1, dp->num_cards) - 1; 107 temp = dp->offsets[r2]; 108 dp->offsets[r2] = dp->offsets[r1]; 109 dp->offsets[r1] = temp; 110 } 111 } 112 /* 113 * This routine draws a card from the given deck 114 */ 115 void 116 get_card(DECK *dp) 117 { 118 char type_maj, type_min; 119 int16_t num; 120 int i, per_h, per_H, num_h, num_H; 121 OWN *op; 122 123 do { 124 fseek(deckf, dp->offsets[dp->top_card], SEEK_SET); 125 dp->top_card = ++(dp->top_card) % dp->num_cards; 126 type_maj = getc(deckf); 127 } while (dp->gojf_used && type_maj == GOJF); 128 type_min = getc(deckf); 129 fread(&num, sizeof(num), 1, deckf); 130 num = ntohs(num); 131 printmes(); 132 switch (type_maj) { 133 case '+': /* get money */ 134 if (type_min == 'A') { 135 for (i = 0; i < num_play; i++) 136 if (i != player) 137 play[i].money -= num; 138 num = num * (num_play - 1); 139 } 140 cur_p->money += num; 141 break; 142 case '-': /* lose money */ 143 if (type_min == 'A') { 144 for (i = 0; i < num_play; i++) 145 if (i != player) 146 play[i].money += num; 147 num = num * (num_play - 1); 148 } 149 cur_p->money -= num; 150 break; 151 case 'M': /* move somewhere */ 152 switch (type_min) { 153 case 'F': /* move forward */ 154 num -= cur_p->loc; 155 if (num < 0) 156 num += 40; 157 break; 158 case 'J': /* move to jail */ 159 goto_jail(); 160 return; 161 case 'R': /* move to railroad */ 162 spec = TRUE; 163 num = (int)((cur_p->loc + 5)/10)*10 + 5 - cur_p->loc; 164 break; 165 case 'U': /* move to utility */ 166 spec = TRUE; 167 if (cur_p->loc >= 12 && cur_p->loc < 28) 168 num = 28 - cur_p->loc; 169 else { 170 num = 12 - cur_p->loc; 171 if (num < 0) 172 num += 40; 173 } 174 break; 175 case 'B': 176 num = -num; 177 break; 178 } 179 move(num); 180 break; 181 case 'T': /* tax */ 182 if (dp == &CC_D) { 183 per_h = 40; 184 per_H = 115; 185 } 186 else { 187 per_h = 25; 188 per_H = 100; 189 } 190 num_h = num_H = 0; 191 for (op = cur_p->own_list; op; op = op->next) 192 if (op->sqr->type == PRPTY) { 193 if (op->sqr->desc->houses == 5) 194 ++num_H; 195 else 196 num_h += op->sqr->desc->houses; 197 } 198 num = per_h * num_h + per_H * num_H; 199 printf("You had %d Houses and %d Hotels, so that cost you $%d\n", num_h, num_H, num); 200 if (num == 0) 201 lucky(""); 202 else 203 cur_p->money -= num; 204 break; 205 case GOJF: /* get-out-of-jail-free card */ 206 cur_p->num_gojf++; 207 dp->gojf_used = TRUE; 208 break; 209 } 210 spec = FALSE; 211 } 212 213 /* 214 * This routine prints out the message on the card 215 */ 216 static void 217 printmes(void) 218 { 219 char c; 220 221 printline(); 222 fflush(stdout); 223 while ((c = getc(deckf)) != '\0') 224 putchar(c); 225 printline(); 226 fflush(stdout); 227 } 228 229 /* 230 * This routine returns the players get-out-of-jail-free card 231 * to the bottom of a deck. XXX currently does not return to the correct 232 * deck. 233 */ 234 void 235 ret_card(PLAY *plr) 236 { 237 char type_maj; 238 int16_t gojfpos, last_card; 239 int i; 240 DECK *dp; 241 int32_t temp; 242 243 plr->num_gojf--; 244 if (CC_D.gojf_used) 245 dp = &CC_D; 246 else 247 dp = &CH_D; 248 dp->gojf_used = FALSE; 249 250 /* Put at bottom of deck (top_card - 1) and remove it from wherever else 251 * it used to be. 252 */ 253 last_card = dp->top_card - 1; 254 if (last_card < 0) 255 last_card += dp->num_cards; 256 gojfpos = dp->top_card; 257 do { 258 gojfpos = (gojfpos + 1) % dp->num_cards; 259 fseek(deckf, dp->offsets[gojfpos], SEEK_SET); 260 type_maj = getc(deckf); 261 } while (type_maj != GOJF); 262 temp = dp->offsets[gojfpos]; 263 /* Only one of the next two loops does anything */ 264 for (i = gojfpos - 1; i > last_card; i--) 265 dp->offsets[i + 1] = dp->offsets[i]; 266 for (i = gojfpos; i < last_card; i++) 267 dp->offsets[i] = dp->offsets[i + 1]; 268 if (gojfpos > last_card) { 269 dp->offsets[dp->top_card] = temp; 270 dp->top_card++; 271 dp->top_card %= dp->num_cards; 272 } else 273 dp->offsets[last_card] = temp; 274 } 275