1 /* $NetBSD: houses.c,v 1.15 2012/06/19 05:35:32 dholland 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)houses.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 __RCSID("$NetBSD: houses.c,v 1.15 2012/06/19 05:35:32 dholland Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include "monop.h" 42 43 static const char *names[N_MON+2]; 44 static char cur_prop[80]; 45 46 static MON *monops[N_MON]; 47 48 static void buy_h(MON *); 49 static void sell_h(MON *); 50 static void list_cur(MON *); 51 static int get_avail_houses(void); 52 static int get_avail_hotels(void); 53 static bool ready_for_hotels(MON *); 54 55 /* 56 * These routines deal with buying and selling houses 57 */ 58 void 59 buy_houses(void) 60 { 61 int num_mon; 62 MON *mp; 63 OWN *op; 64 bool good, got_morg; 65 int i,p; 66 67 over: 68 num_mon = 0; 69 good = TRUE; 70 got_morg = FALSE; 71 for (op = cur_p->own_list; op && op->sqr->type != PRPTY; op = op->next) 72 continue; 73 while (op) 74 if (op->sqr->desc->monop) { 75 mp = op->sqr->desc->mon_desc; 76 names[num_mon] = (monops[num_mon]=mp)->name; 77 num_mon++; 78 got_morg = good = FALSE; 79 for (i = 0; i < mp->num_in; i++) { 80 if (op->sqr->desc->morg) 81 got_morg = TRUE; 82 if (op->sqr->desc->houses != 5) 83 good = TRUE; 84 op = op->next; 85 } 86 if (!good || got_morg) 87 --num_mon; 88 } 89 else 90 op = op->next; 91 if (num_mon == 0) { 92 if (got_morg) 93 printf("You can't build on mortgaged monopolies.\n"); 94 else if (!good) 95 printf("You can't build any more.\n"); 96 else 97 printf("But you don't have any monopolies!!\n"); 98 return; 99 } 100 if (num_mon == 1) 101 buy_h(monops[0]); 102 else { 103 names[num_mon++] = "done"; 104 names[num_mon--] = 0; 105 if ((p = getinp( 106 "Which property do you wish to buy houses for? ", 107 names)) == num_mon) 108 return; 109 buy_h(monops[p]); 110 goto over; 111 } 112 } 113 114 static void 115 buy_h(MON *mnp) 116 { 117 int i; 118 MON *mp; 119 int price; 120 short input[3], result[3]; 121 int wanted_houses, wanted_hotels; 122 int total_purchase; 123 PROP *pp; 124 int avail_houses, avail_hotels; 125 bool buying_hotels; 126 127 mp = mnp; 128 price = mp->h_cost * 50; 129 130 avail_houses = get_avail_houses(); 131 avail_hotels = get_avail_hotels(); 132 buying_hotels = ready_for_hotels(mnp); 133 134 if (avail_houses == 0 && !buying_hotels) { 135 printf("Building shortage: no houses available."); 136 return; 137 } 138 if (avail_hotels == 0 && buying_hotels) { 139 printf("Building shortage: no hotels available."); 140 return; 141 } 142 143 blew_it: 144 list_cur(mp); 145 printf("Houses will cost $%d\n", price); 146 printf("How many houses do you wish to buy for\n"); 147 for (i = 0; i < mp->num_in; i++) { 148 pp = mp->sq[i]->desc; 149 over: 150 if (pp->houses == 5) { 151 printf("%s (H):\n", mp->sq[i]->name); 152 input[i] = 0; 153 result[i] = 5; 154 continue; 155 } 156 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ", 157 mp->sq[i]->name, pp->houses); 158 input[i] = get_int(cur_prop); 159 result[i] = input[i] + pp->houses; 160 if (result[i] > 5 || result[i] < 0) { 161 printf("That's too many. The most you can buy is %d\n", 162 5 - pp->houses); 163 goto over; 164 } 165 } 166 if (mp->num_in == 3 && 167 (abs(result[0] - result[1]) > 1 || 168 abs(result[0] - result[2]) > 1 || 169 abs(result[1] - result[2]) > 1)) { 170 err: printf("That makes the spread too wide. Try again\n"); 171 goto blew_it; 172 } 173 else if (mp->num_in == 2 && abs(result[0] - result[1]) > 1) 174 goto err; 175 176 wanted_houses = 0; 177 wanted_hotels = 0; 178 total_purchase = 0; 179 180 for (i = 0; i < mp->num_in; i++) { 181 wanted_houses += input[i]; 182 total_purchase += input[i]; 183 if (result[i] == 5 && input[i] > 0) { 184 wanted_hotels++; 185 wanted_houses--; 186 } 187 } 188 if (wanted_houses > avail_houses) { 189 printf("You have asked for %d %s but only %d are available. " 190 "Try again\n", 191 wanted_houses, wanted_houses == 1 ? "house" : "houses", 192 avail_houses); 193 goto blew_it; 194 } else if (wanted_hotels > avail_hotels) { 195 printf("You have asked for %d %s but only %d are available. " 196 "Try again\n", 197 wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels", 198 avail_hotels); 199 goto blew_it; 200 } 201 202 if (total_purchase) { 203 printf("You asked for %d %s and %d %s for $%d\n", 204 wanted_houses, wanted_houses == 1 ? "house" : "houses", 205 wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels", 206 total_purchase * price); 207 if (getyn("Is that ok? ") == 0) { 208 cur_p->money -= total_purchase * price; 209 for (i = 0; i < mp->num_in; i++) 210 mp->sq[i]->desc->houses = result[i]; 211 } 212 } 213 } 214 215 /* 216 * This routine sells houses. 217 */ 218 void 219 sell_houses(void) 220 { 221 int num_mon; 222 MON *mp; 223 OWN *op; 224 bool good; 225 int p; 226 227 over: 228 num_mon = 0; 229 good = TRUE; 230 for (op = cur_p->own_list; op;) 231 if (op->sqr->type == PRPTY && op->sqr->desc->monop) { 232 mp = op->sqr->desc->mon_desc; 233 names[num_mon] = (monops[num_mon]=mp)->name; 234 num_mon++; 235 good = 0; 236 do 237 if (!good && op->sqr->desc->houses != 0) 238 good = TRUE; 239 while (op->next && op->sqr->desc->mon_desc == mp 240 && (op = op->next)); 241 if (!good) 242 --num_mon; 243 } else 244 op = op->next; 245 if (num_mon == 0) { 246 printf("You don't have any houses to sell!!\n"); 247 return; 248 } 249 if (num_mon == 1) 250 sell_h(monops[0]); 251 else { 252 names[num_mon++] = "done"; 253 names[num_mon--] = 0; 254 if ((p = getinp( 255 "Which property do you wish to sell houses from? ", 256 names)) == num_mon) 257 return; 258 sell_h(monops[p]); 259 notify(); 260 goto over; 261 } 262 } 263 264 static void 265 sell_h(MON *mnp) 266 { 267 int i; 268 MON *mp; 269 int price; 270 short input[3],temp[3]; 271 int tot; 272 PROP *pp; 273 274 mp = mnp; 275 price = mp->h_cost * 25; 276 blew_it: 277 printf("Houses will get you $%d apiece\n", price); 278 list_cur(mp); 279 printf("How many houses do you wish to sell from\n"); 280 for (i = 0; i < mp->num_in; i++) { 281 pp = mp->sq[i]->desc; 282 over: 283 if (pp->houses == 0) { 284 printf("%s (0):\n", mp->sq[i]->name); 285 input[i] = temp[i] = 0; 286 continue; 287 } 288 if (pp->houses < 5) 289 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ", 290 mp->sq[i]->name,pp->houses); 291 else 292 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (H): ", 293 mp->sq[i]->name); 294 input[i] = get_int(cur_prop); 295 temp[i] = pp->houses - input[i]; 296 if (temp[i] < 0) { 297 printf( 298 "That's too many. The most you can sell is %d\n", 299 pp->houses); 300 goto over; 301 } 302 } 303 if (mp->num_in == 3 && (abs(temp[0] - temp[1]) > 1 || 304 abs(temp[0] - temp[2]) > 1 || abs(temp[1] - temp[2]) > 1)) { 305 err: printf("That makes the spread too wide. Try again\n"); 306 goto blew_it; 307 } 308 else if (mp->num_in == 2 && abs(temp[0] - temp[1]) > 1) 309 goto err; 310 for (tot = i = 0; i < mp->num_in; i++) 311 tot += input[i]; 312 if (tot) { 313 printf("You asked to sell %d house%s for $%d\n", tot, 314 tot == 1 ? "" : "s", tot * price); 315 if (getyn("Is that ok? ") == 0) { 316 cur_p->money += tot * price; 317 for (tot = i = 0; i < mp->num_in; i++) 318 mp->sq[i]->desc->houses = temp[i]; 319 } 320 } 321 } 322 323 static void 324 list_cur(MON *mp) 325 { 326 int i; 327 SQUARE *sqp; 328 329 for (i = 0; i < mp->num_in; i++) { 330 sqp = mp->sq[i]; 331 if (sqp->desc->houses == 5) 332 printf("%s (H) ", sqp->name); 333 else 334 printf("%s (%d) ", sqp->name, sqp->desc->houses); 335 } 336 putchar('\n'); 337 } 338 339 static int 340 get_avail_houses(void) 341 { 342 int i, c; 343 SQUARE *sqp; 344 345 c = 0; 346 for (i = 0; i < N_SQRS; i++) { 347 sqp = &board[i]; 348 if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) { 349 if (sqp->desc->houses < 5 && sqp->desc->houses > 0) 350 c += sqp->desc->houses; 351 } 352 } 353 return(N_HOUSE - c); 354 } 355 356 static int 357 get_avail_hotels(void) 358 { 359 int i, c; 360 SQUARE *sqp; 361 362 c = 0; 363 for (i = 0; i < N_SQRS; i++) { 364 sqp = &board[i]; 365 if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) { 366 if (sqp->desc->houses == 5) 367 c++; 368 } 369 } 370 return(N_HOTEL - c); 371 } 372 373 /* 374 * If we can put a hotel on, we can't put any houses on, and if we can 375 * put houses on, then we can't put a hotel on yet. 376 */ 377 static bool 378 ready_for_hotels(MON *mp) 379 { 380 int i; 381 382 for (i = 0; i < mp->num_in; i++) { 383 if (mp->sq[i]->desc->houses < 4) 384 return(FALSE); 385 } 386 return(TRUE); 387 } 388