1 /* $NetBSD: houses.c,v 1.14 2008/02/24 03:26:26 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.14 2008/02/24 03:26:26 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() 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(mnp) 116 MON *mnp; 117 { 118 int i; 119 MON *mp; 120 int price; 121 short input[3], result[3]; 122 int wanted_houses, wanted_hotels; 123 int total_purchase; 124 PROP *pp; 125 int avail_houses, avail_hotels; 126 bool buying_hotels; 127 128 mp = mnp; 129 price = mp->h_cost * 50; 130 131 avail_houses = get_avail_houses(); 132 avail_hotels = get_avail_hotels(); 133 buying_hotels = ready_for_hotels(mnp); 134 135 if (avail_houses == 0 && !buying_hotels) { 136 printf("Building shortage: no houses available."); 137 return; 138 } 139 if (avail_hotels == 0 && buying_hotels) { 140 printf("Building shortage: no hotels available."); 141 return; 142 } 143 144 blew_it: 145 list_cur(mp); 146 printf("Houses will cost $%d\n", price); 147 printf("How many houses do you wish to buy for\n"); 148 for (i = 0; i < mp->num_in; i++) { 149 pp = mp->sq[i]->desc; 150 over: 151 if (pp->houses == 5) { 152 printf("%s (H):\n", mp->sq[i]->name); 153 input[i] = 0; 154 result[i] = 5; 155 continue; 156 } 157 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ", 158 mp->sq[i]->name, pp->houses); 159 input[i] = get_int(cur_prop); 160 result[i] = input[i] + pp->houses; 161 if (result[i] > 5 || result[i] < 0) { 162 printf("That's too many. The most you can buy is %d\n", 163 5 - pp->houses); 164 goto over; 165 } 166 } 167 if (mp->num_in == 3 && 168 (abs(result[0] - result[1]) > 1 || 169 abs(result[0] - result[2]) > 1 || 170 abs(result[1] - result[2]) > 1)) { 171 err: printf("That makes the spread too wide. Try again\n"); 172 goto blew_it; 173 } 174 else if (mp->num_in == 2 && abs(result[0] - result[1]) > 1) 175 goto err; 176 177 wanted_houses = 0; 178 wanted_hotels = 0; 179 total_purchase = 0; 180 181 for (i = 0; i < mp->num_in; i++) { 182 wanted_houses += input[i]; 183 total_purchase += input[i]; 184 if (result[i] == 5 && input[i] > 0) { 185 wanted_hotels++; 186 wanted_houses--; 187 } 188 } 189 if (wanted_houses > avail_houses) { 190 printf("You have asked for %d %s but only %d are available. " 191 "Try again\n", 192 wanted_houses, wanted_houses == 1 ? "house" : "houses", 193 avail_houses); 194 goto blew_it; 195 } else if (wanted_hotels > avail_hotels) { 196 printf("You have asked for %d %s but only %d are available. " 197 "Try again\n", 198 wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels", 199 avail_hotels); 200 goto blew_it; 201 } 202 203 if (total_purchase) { 204 printf("You asked for %d %s and %d %s for $%d\n", 205 wanted_houses, wanted_houses == 1 ? "house" : "houses", 206 wanted_hotels, wanted_hotels == 1 ? "hotel" : "hotels", 207 total_purchase * price); 208 if (getyn("Is that ok? ") == 0) { 209 cur_p->money -= total_purchase * price; 210 for (i = 0; i < mp->num_in; i++) 211 mp->sq[i]->desc->houses = result[i]; 212 } 213 } 214 } 215 216 /* 217 * This routine sells houses. 218 */ 219 void 220 sell_houses() 221 { 222 int num_mon; 223 MON *mp; 224 OWN *op; 225 bool good; 226 int p; 227 228 over: 229 num_mon = 0; 230 good = TRUE; 231 for (op = cur_p->own_list; op;) 232 if (op->sqr->type == PRPTY && op->sqr->desc->monop) { 233 mp = op->sqr->desc->mon_desc; 234 names[num_mon] = (monops[num_mon]=mp)->name; 235 num_mon++; 236 good = 0; 237 do 238 if (!good && op->sqr->desc->houses != 0) 239 good = TRUE; 240 while (op->next && op->sqr->desc->mon_desc == mp 241 && (op = op->next)); 242 if (!good) 243 --num_mon; 244 } else 245 op = op->next; 246 if (num_mon == 0) { 247 printf("You don't have any houses to sell!!\n"); 248 return; 249 } 250 if (num_mon == 1) 251 sell_h(monops[0]); 252 else { 253 names[num_mon++] = "done"; 254 names[num_mon--] = 0; 255 if ((p = getinp( 256 "Which property do you wish to sell houses from? ", 257 names)) == num_mon) 258 return; 259 sell_h(monops[p]); 260 notify(); 261 goto over; 262 } 263 } 264 265 static void 266 sell_h(mnp) 267 MON *mnp; 268 { 269 int i; 270 MON *mp; 271 int price; 272 short input[3],temp[3]; 273 int tot; 274 PROP *pp; 275 276 mp = mnp; 277 price = mp->h_cost * 25; 278 blew_it: 279 printf("Houses will get you $%d apiece\n", price); 280 list_cur(mp); 281 printf("How many houses do you wish to sell from\n"); 282 for (i = 0; i < mp->num_in; i++) { 283 pp = mp->sq[i]->desc; 284 over: 285 if (pp->houses == 0) { 286 printf("%s (0):\n", mp->sq[i]->name); 287 input[i] = temp[i] = 0; 288 continue; 289 } 290 if (pp->houses < 5) 291 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (%d): ", 292 mp->sq[i]->name,pp->houses); 293 else 294 (void)snprintf(cur_prop, sizeof(cur_prop), "%s (H): ", 295 mp->sq[i]->name); 296 input[i] = get_int(cur_prop); 297 temp[i] = pp->houses - input[i]; 298 if (temp[i] < 0) { 299 printf( 300 "That's too many. The most you can sell is %d\n", 301 pp->houses); 302 goto over; 303 } 304 } 305 if (mp->num_in == 3 && (abs(temp[0] - temp[1]) > 1 || 306 abs(temp[0] - temp[2]) > 1 || abs(temp[1] - temp[2]) > 1)) { 307 err: printf("That makes the spread too wide. Try again\n"); 308 goto blew_it; 309 } 310 else if (mp->num_in == 2 && abs(temp[0] - temp[1]) > 1) 311 goto err; 312 for (tot = i = 0; i < mp->num_in; i++) 313 tot += input[i]; 314 if (tot) { 315 printf("You asked to sell %d house%s for $%d\n", tot, 316 tot == 1 ? "" : "s", tot * price); 317 if (getyn("Is that ok? ") == 0) { 318 cur_p->money += tot * price; 319 for (tot = i = 0; i < mp->num_in; i++) 320 mp->sq[i]->desc->houses = temp[i]; 321 } 322 } 323 } 324 325 static void 326 list_cur(mp) 327 MON *mp; 328 { 329 int i; 330 SQUARE *sqp; 331 332 for (i = 0; i < mp->num_in; i++) { 333 sqp = mp->sq[i]; 334 if (sqp->desc->houses == 5) 335 printf("%s (H) ", sqp->name); 336 else 337 printf("%s (%d) ", sqp->name, sqp->desc->houses); 338 } 339 putchar('\n'); 340 } 341 342 static int 343 get_avail_houses(void) 344 { 345 int i, c; 346 SQUARE *sqp; 347 348 c = 0; 349 for (i = 0; i < N_SQRS; i++) { 350 sqp = &board[i]; 351 if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) { 352 if (sqp->desc->houses < 5 && sqp->desc->houses > 0) 353 c += sqp->desc->houses; 354 } 355 } 356 return(N_HOUSE - c); 357 } 358 359 static int 360 get_avail_hotels(void) 361 { 362 int i, c; 363 SQUARE *sqp; 364 365 c = 0; 366 for (i = 0; i < N_SQRS; i++) { 367 sqp = &board[i]; 368 if (sqp->type == PRPTY && sqp->owner >= 0 && sqp->desc->monop) { 369 if (sqp->desc->houses == 5) 370 c++; 371 } 372 } 373 return(N_HOTEL - c); 374 } 375 376 /* 377 * If we can put a hotel on, we can't put any houses on, and if we can 378 * put houses on, then we can't put a hotel on yet. 379 */ 380 static bool 381 ready_for_hotels(MON *mp) 382 { 383 int i; 384 385 for (i = 0; i < mp->num_in; i++) { 386 if (mp->sq[i]->desc->houses < 4) 387 return(FALSE); 388 } 389 return(TRUE); 390 } 391