]> git.pond.sub.org Git - empserver/blob - src/lib/commands/cons.c
Import of Empire 4.2.12
[empserver] / src / lib / commands / cons.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  cons.c: Consider a loan or treaty
29  * 
30  *  Known contributors to this file:
31  *     
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "loan.h"
37 #include "nat.h"
38 #include "treaty.h"
39 #include "news.h"
40 #include "xy.h"
41 #include "nsc.h"
42 #include "file.h"
43 #include "commands.h"
44 #include "optlist.h"
45
46 /*
47  * Things common to a loan or treaty.
48  */
49 struct ltcomstr {
50         int     type;                   /* EF_LOAN or EF_TREATY */
51         int     num;                    /* number */
52         s_char  *name;                  /* "loan" or "treaty" */
53         s_char  *Name;                  /* "Loan" or "Treaty" */
54         natid   proposer;               /* country offering */
55         natid   proposee;               /* country offered to */
56         natid   mailee;                 /* who gets mail about it */
57         s_char  op;                     /* 'a', 'd', or 'p' */
58         union {
59                 struct  lonstr l;       /* the loan */
60                 struct  trtstr t;       /* the treaty */
61         } u;
62 };
63
64 static int cons_choose(struct ltcomstr *ltcp);
65 static int treaty_accept(struct ltcomstr *ltcp);
66 static int treaty_decline(struct ltcomstr *ltcp);
67 static int loan_accept(struct ltcomstr *ltcp);
68 static int loan_decline(struct ltcomstr *ltcp);
69 static int postpone(struct ltcomstr *ltcp);
70 static void accpt(struct ltcomstr *ltcp);
71 static void decline(struct ltcomstr *ltcp);
72 static void late(struct ltcomstr *ltcp);
73 static void prev_signed(struct ltcomstr *ltcp);
74
75 int
76 cons(void)
77 {
78         int     rv;
79         struct  ltcomstr ltc;
80
81         rv = cons_choose(&ltc);
82         if (rv != RET_OK)
83                 return rv;
84
85         switch (ltc.op) {
86         case 'a':
87                 rv = (ltc.type == EF_TREATY) ? treaty_accept(&ltc)
88                                              : loan_accept(&ltc);
89                 break;
90         case 'd':
91                 rv = (ltc.type == EF_TREATY) ? treaty_decline(&ltc)
92                                              : loan_decline(&ltc);
93                 break;
94         case 'p':
95                 rv = postpone(&ltc);
96                 break;
97         default:
98                 pr("Bad operation %c from cons_choose; get help!\n",
99                         ltc.op);
100                 break;
101         };
102
103         return rv;
104 }
105
106 /*
107  * Choose whether we want to accept, decline, or postpone a
108  * loan or treaty.  Put all the goodies in ltcp, and return
109  * RET_OK if all goes well, and anything else on error.
110  */
111 static int
112 cons_choose(struct ltcomstr *ltcp)
113 {
114         s_char  *p;
115         extern  int disloan();
116         extern  int distrea();
117         int     (*dis)();
118         struct  lonstr *lp;
119         struct  trtstr *tp;
120         s_char  prompt[128];
121         s_char  buf[1024];
122
123         bzero((s_char *)ltcp, sizeof (*ltcp));
124         if (getstarg(player->argp[1], "loan or treaty? ", buf) == 0)
125                 return RET_SYN;
126         ltcp->type = ef_byname(buf);
127         switch (ltcp->type) {
128         case EF_TREATY:
129                 if (!opt_TREATIES) {
130                     pr("Treaties are not enabled.\n");
131                     return RET_FAIL;
132                 }
133                 ltcp->name = "treaty";
134                 ltcp->Name = "Treaty";
135                 dis = distrea;
136                 break;
137         case EF_LOAN:
138                 if (!opt_LOANS) {
139                     pr("Loans are not enabled.\n");
140                     return RET_FAIL;
141                 }
142                 ltcp->name = "loan";
143                 ltcp->Name = "Loan";
144                 dis = disloan;
145                 break;
146         default:
147                 pr("You must specify \"loan\" or \"treaty\".\n");
148                 return RET_SYN;
149         }
150         sprintf(prompt, "%s number? ", ltcp->Name);
151         if ((ltcp->num = onearg(player->argp[2], prompt)) < 0)
152                 return RET_SYN;
153         if (!ef_read(ltcp->type, ltcp->num, (caddr_t)&ltcp->u) ||
154             !(*dis)(ltcp->num, &ltcp->u)) {
155                 pr("%s #%d is not being offered to you!\n",
156                         ltcp->Name, ltcp->num);
157                 return RET_SYN;
158         }
159         switch (ltcp->type) {
160         case EF_LOAN:
161                 lp = &ltcp->u.l;
162                 if (lp->l_status == LS_SIGNED) {
163                         pr("That loan has already been accepted!\n");
164                         return RET_FAIL;
165                 }
166                 ltcp->proposer = lp->l_loner;
167                 ltcp->proposee = lp->l_lonee;
168                 break;
169         case EF_TREATY:
170                 tp = &ltcp->u.t;
171                 if (tp->trt_status == TS_SIGNED) {
172                         pr("That treaty has already been accepted!\n");
173                         return RET_FAIL;
174                 }
175                 ltcp->proposer = tp->trt_cna;
176                 ltcp->proposee = tp->trt_cnb;
177                 break;
178         }
179         ltcp->mailee = (ltcp->proposer == player->cnum)
180                 ? ltcp->proposee : ltcp->proposer;
181         while ((p = getstarg(player->argp[3], "Accept, decline or postpone? ", buf)) && *p) 
182 {
183                 if (*p == 'a' || *p == 'd' || *p == 'p')
184                         break;
185                 player->argp[3] = 0;
186         }
187         if (p == 0 || *p == 0)
188                 return RET_SYN;
189         ltcp->op = *p;
190         return RET_OK;
191 }
192
193 /*
194  * Accept a loan.  If the offering country has too little money,
195  * leave him $100 left and offer the rest.  Return RET_OK on
196  * success, anything else on error.
197  */
198 static int
199 loan_accept(struct ltcomstr *ltcp)
200 {
201         struct  lonstr *lp;
202         struct  natstr *lender;
203         struct  nstr_item nstr;
204         struct  lonstr loan;
205
206         lp = &ltcp->u.l;
207         if (ltcp->proposee != player->cnum) {
208                 pr("%s %d is still pending.\n", ltcp->Name, ltcp->num);
209                 return RET_OK;
210         }
211         if (!getloan(ltcp->num, (caddr_t)lp)) {
212                 pr("loan_accept: can't read loan; get help!\n");
213                 return RET_SYS;
214         }
215         if (lp->l_status == LS_FREE) {  /* other guy retratcted already */
216                 late(ltcp);
217                 return RET_OK;
218         }
219         if (lp->l_status == LS_SIGNED) { /* already signed somehow */
220                 prev_signed(ltcp);
221                 return RET_OK;
222         }
223         /* check to see if a loan already exists */
224         snxtitem_all(&nstr, EF_LOAN);
225         while (nxtitem(&nstr, (s_char *) &loan)) {
226                 if (loan.l_status == LS_SIGNED && loan.l_lonee == lp->l_loner
227                                         && (loan.l_loner == lp->l_lonee)) {
228                   pr("He already owes you money - make him repay his loan!\n");
229                         return RET_OK;
230                 }
231         }
232         lender = getnatp(ltcp->proposer);
233         if (lender->nat_money < lp->l_amtdue) { /* other guy is poor */
234                 lp->l_amtdue = lender->nat_money - 100;
235                 pr("%s no longer has the funds.\n", cname(ltcp->proposer));
236                 if (lp->l_amtdue <= 0)
237                         return RET_FAIL;
238                 pr("You may borrow $%d at the same terms.\n",
239                         lp->l_amtdue);
240         }
241         lender->nat_money -= lp->l_amtdue;
242         putnat(lender);
243         player->dolcost -= lp->l_amtdue;
244         lp->l_amtpaid = 0;
245         (void) time(&lp->l_lastpay);
246         lp->l_duedate = lp->l_ldur * 86400 + lp->l_lastpay;
247         lp->l_status = LS_SIGNED;
248         if (!putloan(ltcp->num, (s_char *)lp)) {
249                 pr("Problem writing lp->to disk; get help!\n");
250                 return RET_FAIL;
251         }
252         accpt(ltcp);
253         pr("You are now $%d richer (sort of).\n", lp->l_amtdue);
254         return RET_OK;
255 }
256
257 /*
258  * Declne a loan.  Return RET_OK on success, anything else on error.
259  */
260 static int
261 loan_decline(struct ltcomstr *ltcp)
262 {
263         struct  lonstr *lp;
264
265         lp = &ltcp->u.l;
266         if (!getloan(ltcp->num, lp)) {
267                 pr("Decline: can't read loan; get help!\n");
268                 return RET_SYS;
269         }
270         /* loan got accepted somehow between now and last time we checked */
271         if (lp->l_status == LS_SIGNED) {
272                 late(ltcp);
273                 return RET_OK;
274         }
275         lp->l_status = LS_FREE;
276         if (!putloan(ltcp->num, lp)) {
277                 pr("loan_decline: can't write loan; get help!\n");
278                 return RET_SYS;
279         }
280         decline(ltcp);
281         return RET_OK;
282 }
283
284 /*
285  * Accept a treaty.  Return RET_OK on success, anything else on error.
286  */
287 static int
288 treaty_accept(struct ltcomstr *ltcp)
289 {
290         struct  trtstr *tp;
291
292         tp = &ltcp->u.t;
293         if (ltcp->proposee != player->cnum) {
294                 pr("%s %d is still pending.\n", ltcp->Name, ltcp->num);
295                 return RET_OK;
296         }
297         if (!gettre(ltcp->num, tp)) {
298                 pr("Accept: can't read treaty; get help!\n");
299                 return RET_SYS;
300         }
301         if (tp->trt_status == TS_FREE) {        /* treaty offer withdrawn */
302                 late(ltcp);
303                 return RET_OK;
304         }
305         if (tp->trt_status == TS_SIGNED) {      /* somehow got accepted */
306                 prev_signed(ltcp);
307                 return RET_OK;
308         }
309         tp->trt_status = TS_SIGNED;
310         if (!puttre(ltcp->num, tp)) {
311                 pr("Problem saving treaty; get help!\n");
312                 return RET_SYS;
313         }
314         accpt(ltcp);
315         pr("Treaty in effect until %s", ctime(&tp->trt_exp));
316         return RET_OK;
317 }
318
319 /*
320  * Decline a treaty.  Return RET_OK on success, anything else on error.
321  */
322 static int
323 treaty_decline(struct ltcomstr *ltcp)
324 {
325         struct  trtstr *tp;
326
327         tp = &ltcp->u.t;
328         if (!gettre(ltcp->num, tp)) {
329                 pr("Decline: can't read treaty; get help!\n");
330                 return RET_SYS;
331         }
332         /* treaty got signed somehow between now and last time we read it */
333         if (tp->trt_status == TS_SIGNED) {
334                 late(ltcp);
335                 return RET_OK;
336         }
337         tp->trt_status = TS_FREE;
338         if (!puttre(ltcp->num, tp)) {
339                 pr("Problem saving treaty; get help!\n");
340                 return RET_SYS;
341         }
342         decline(ltcp);
343         return RET_OK;
344 }
345
346 /*
347  * Postpone a treaty; always succeeds.
348  */
349 static int
350 postpone(struct ltcomstr *ltcp)
351 {
352         pr("%s %d is still pending.\n", ltcp->Name, ltcp->num);
353         if (ltcp->proposee == player->cnum)
354                 wu(0, ltcp->proposer, "%s %d considered by %s\n",
355                         ltcp->name, ltcp->num, cname(player->cnum));
356         return RET_OK;
357 }
358
359 /*
360  * Somebody tried to accept a loan/treaty that was retracted,
361  * or to decline a loan/treaty they already signed.
362  */
363 static void
364 late(struct ltcomstr *ltcp)
365 {
366         pr("Too late; that %s %s!\n", ltcp->name,
367                 (ltcp->op == 'a') ? "is no longer being offered"
368                                   : "has already been accepted");
369 }
370
371 /*
372  * Loan or treaty was previously signed.
373  */
374 static void
375 prev_signed(struct ltcomstr *ltcp)
376 {
377         pr("%s #%d is already in effect.\n", ltcp->Name, ltcp->num);
378 }
379
380 /*
381  * Post-processing after successful declination of loan or treaty.
382  * Notify the folks involved.
383  */
384 static void
385 decline(struct ltcomstr *ltcp)
386 {
387         if (ltcp->proposee == player->cnum) {
388                 wu(0, ltcp->proposer, "%s %d refused by %s\n",
389                         ltcp->Name, ltcp->num, cname(player->cnum));
390                 pr("%s %d refused.\n", ltcp->Name, ltcp->num);
391         } else {
392                 wu(0, ltcp->proposee,
393                         "%s offer %d retracted by %s\n",
394                         ltcp->Name, ltcp->num, cname(player->cnum));
395                 pr("%s offer %d retracted.\n",
396                         ltcp->Name, ltcp->num);
397         }
398 }
399
400 /*
401  * Post-processing after successful acceptance of loan or treaty.
402  * Notify the press, and the folks involved.
403  * (Weird spelling is to avoid accept(2)).
404  */
405 static void
406 accpt(struct ltcomstr *ltcp)
407 {
408         if (ltcp->type == EF_LOAN)
409                 nreport(ltcp->proposer, N_MAKE_LOAN, player->cnum, 1);
410         else
411                 nreport(player->cnum, N_SIGN_TRE, ltcp->mailee, 1);
412         wu(0, ltcp->mailee, "%s #%d accepted by %s\n",
413                 ltcp->Name, ltcp->num, cname(player->cnum));
414 }