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