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