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