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