1 /*        $NetBSD: trade.c,v 1.16 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[] = "@(#)trade.c     8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: trade.c,v 1.16 2012/06/19 05:35:32 dholland Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include "monop.h"
42 
43 struct trd_st {                         /* how much to give to other player     */
44           int       trader;                       /* trader number              */
45           int       cash;                         /* amount of cash             */
46           int       gojf;                         /* # get-out-of-jail-free cards         */
47           OWN       *prop_list;                   /* property list              */
48 };
49 
50 typedef   struct trd_st       TRADE;
51 
52 static const char   *plist[MAX_PRP+2];
53 
54 static int          used[MAX_PRP];
55 
56 static TRADE        trades[2];
57 
58 static void get_list(int, int );
59 static int set_list(OWN *);
60 static void summate(void);
61 static void do_trade(void);
62 static void move_em(TRADE *, TRADE *);
63 
64 void
trade(void)65 trade(void)
66 {
67           int tradee, i;
68 
69           trading = TRUE;
70           for (i = 0; i < 2; i++) {
71                     trades[i].cash = 0;
72                     trades[i].gojf = FALSE;
73                     trades[i].prop_list = NULL;
74           }
75 over:
76           if (num_play == 1) {
77                     printf("There ain't no-one around to trade WITH!!\n");
78                     return;
79           }
80           if (num_play > 2) {
81                     tradee = getinp("Which player do you wish to trade with? ",
82                         name_list);
83                     if (tradee == num_play)
84                               return;
85                     if (tradee == player) {
86                               printf("You can't trade with yourself!\n");
87                               goto over;
88                     }
89           }
90           else
91                     tradee = 1 - player;
92           get_list(0, player);
93           get_list(1, tradee);
94           if (getyn("Do you wish a summary? ") == 0)
95                     summate();
96           if (getyn("Is the trade ok? ") == 0)
97                     do_trade();
98 }
99 
100 /*
101  *        This routine gets the list of things to be trader for the
102  * player, and puts in the structure given.
103  */
104 static void
get_list(int struct_no,int play_no)105 get_list(int struct_no, int play_no)
106 {
107           int sn, pn;
108           PLAY *pp;
109           int numin, propnum, num_prp;
110           OWN *op;
111           TRADE *tp;
112 
113           for (numin = 0; numin < MAX_PRP; numin++)
114                     used[numin] = FALSE;
115           sn = struct_no, pn = play_no;
116           pp = &play[pn];
117           tp = &trades[sn];
118           tp->trader = pn;
119           printf("player %s (%d):\n", pp->name, pn+1);
120           if (pp->own_list) {
121                     numin = set_list(pp->own_list);
122                     for (num_prp = numin; num_prp; ) {
123                               propnum=getinp("Which property do you wish to trade? ",
124                                   plist);
125                               if (propnum == numin)
126                                         break;
127                               else if (used[propnum])
128                                         printf("You've already allocated that.\n");
129                               else {
130                                         num_prp--;
131                                         used[propnum] = TRUE;
132                                         for (op = pp->own_list; propnum--; op = op->next)
133                                                   continue;
134                                         add_list(pn, &(tp->prop_list), sqnum(op->sqr));
135                               }
136                     }
137           }
138           if (pp->money > 0) {
139                     printf("You have $%d.  ", pp->money);
140                     tp->cash = get_int("How much are you trading? ");
141           }
142           if (pp->num_gojf > 0) {
143 once_more:
144                     printf("You have %d get-out-of-jail-free cards. ",pp->num_gojf);
145                     tp->gojf = get_int("How many are you trading? ");
146                     if (tp->gojf > pp->num_gojf) {
147                               printf("You don't have that many.  Try again.\n");
148                               goto once_more;
149                     }
150           }
151 }
152 
153 /*
154  *        This routine sets up the list of tradable property.
155  */
156 static int
set_list(OWN * the_list)157 set_list(OWN *the_list)
158 {
159           int i;
160           OWN *op;
161 
162           i = 0;
163           for (op = the_list; op; op = op->next)
164                     if (!used[i])
165                               plist[i++] = op->sqr->name;
166           plist[i++] = "done";
167           plist[i--] = 0;
168           return i;
169 }
170 
171 /*
172  *        This routine summates the trade.
173  */
174 static void
summate(void)175 summate(void)
176 {
177           bool some;
178           int i;
179           TRADE *tp;
180           OWN *op;
181 
182           for (i = 0; i < 2; i++) {
183                     tp = &trades[i];
184                     some = FALSE;
185                     printf("Player %s (%d) gives:\n", play[tp->trader].name,
186                               tp->trader+1);
187                     if (tp->cash > 0)
188                               printf("\t$%d\n", tp->cash), some++;
189                     if (tp->gojf > 0)
190                               printf("\t%d get-out-of-jail-free card(s)\n", tp->gojf),
191                               some++;
192                     if (tp->prop_list) {
193                               for (op = tp->prop_list; op; op = op->next)
194                                         putchar('\t'), printsq(sqnum(op->sqr), TRUE);
195                               some++;
196                     }
197                     if (!some)
198                               printf("\t-- Nothing --\n");
199           }
200 }
201 
202 /*
203  *        This routine actually executes the trade.
204  */
205 static void
do_trade(void)206 do_trade(void)
207 {
208           move_em(&trades[0], &trades[1]);
209           move_em(&trades[1], &trades[0]);
210 }
211 
212 /*
213  *        This routine does a switch from one player to another
214  */
215 static void
move_em(TRADE * from,TRADE * to)216 move_em(TRADE *from, TRADE *to)
217 {
218           PLAY *pl_fr, *pl_to;
219           OWN *op;
220 
221           pl_fr = &play[from->trader];
222           pl_to = &play[to->trader];
223 
224           pl_fr->money -= from->cash;
225           pl_to->money += from->cash;
226           pl_fr->num_gojf -= from->gojf;
227           pl_to->num_gojf += from->gojf;
228           for (op = from->prop_list; op; op = op->next) {
229                     add_list(to->trader, &(pl_to->own_list), sqnum(op->sqr));
230                     op->sqr->owner = to->trader;
231                     del_list(from->trader, &(pl_fr->own_list), sqnum(op->sqr));
232           }
233           set_ownlist(to->trader);
234 }
235 
236 /*
237  *        This routine lets a player resign
238  */
239 void
resign(void)240 resign(void)
241 {
242           int i, new_own;
243           OWN *op;
244           SQUARE *sqp;
245 
246           if (cur_p->money <= 0) {
247                     switch (board[cur_p->loc].type) {
248                       case UTIL:
249                       case RR:
250                       case PRPTY:
251                               new_own = board[cur_p->loc].owner;
252                               /* If you ran out of money by buying current location */
253                               if (new_own == player)
254                                         new_own = num_play;
255                               break;
256                       default:                    /* Chance, taxes, etc */
257                               new_own = num_play;
258                               break;
259                     }
260                     if (new_own == num_play)
261                               printf("You would resign to the bank\n");
262                     else
263                               printf("You would resign to %s\n", name_list[new_own]);
264           }
265           else if (num_play == 1) {
266                     new_own = num_play;
267                     printf("You would resign to the bank\n");
268           }
269           else {
270                     name_list[num_play] = "bank";
271                     do {
272                               new_own = getinp("Who do you wish to resign to? ",
273                                   name_list);
274                               if (new_own == player)
275                                         printf("You can't resign to yourself!!\n");
276                     } while (new_own == player);
277                     name_list[num_play] = "done";
278           }
279           if (getyn("Do you really want to resign? ") != 0)
280                     return;
281           if (num_play == 1) {
282                     printf("Then NOBODY wins (not even YOU!)\n");
283                     exit(0);
284           }
285           if (new_own < num_play) {     /* resign to player           */
286                     printf("resigning to player\n");
287                     trades[0].trader = new_own;
288                     trades[0].cash = trades[0].gojf = 0;
289                     trades[0].prop_list = NULL;
290                     trades[1].trader = player;
291                     trades[1].cash = cur_p->money > 0 ? cur_p->money : 0;
292                     trades[1].gojf = cur_p->num_gojf;
293                     trades[1].prop_list = cur_p->own_list;
294                     do_trade();
295           }
296           else {                                  /* resign to bank             */
297                     printf("resigning to bank\n");
298                     for (op = cur_p->own_list; op; op = op->next) {
299                               sqp = op->sqr;
300                               sqp->owner = -1;
301                               sqp->desc->morg = FALSE;
302                               if (sqp->type == PRPTY) {
303                                         is_not_monop(sqp->desc->mon_desc);
304                                         sqp->desc->houses = 0;
305                               }
306                     }
307                     if (cur_p->num_gojf)
308                               ret_card(cur_p);
309           }
310           free(play[player].name);
311           for (i = player; i < num_play; i++) {
312                     name_list[i] = name_list[i+1];
313                     if (i + 1 < num_play)
314                               play[i] = play[i+1];
315           }
316           name_list[num_play--] = NULL;
317           for (i = 0; i < N_SQRS; i++)
318                     if (board[i].owner > player)
319                               --board[i].owner;
320           player = player == 0 ? num_play - 1 : player - 1;
321           next_play();
322           if (num_play < 2) {
323                     printf("\nThen %s WINS!!!!!\n", play[0].name);
324                     printhold(0);
325                     printf("That's a grand worth of $%d.\n",
326                               play[0].money+prop_worth(&play[0]));
327                     exit(0);
328           }
329 }
330