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