]> git.pond.sub.org Git - empserver/blob - src/lib/commands/repo.c
Update copyright notice.
[empserver] / src / lib / commands / repo.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2004, 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  *  repo.c: Report on various levels (tech, research) of other nations
29  * 
30  *  Known contributors to this file:
31  *     Keith Muller, 1983
32  *     Dave Pare, 1986 (rewrite)
33  *     Steve McClure, 2000
34  */
35
36 #include "misc.h"
37 #include "player.h"
38 #include "var.h"
39 #include "sect.h"
40 #include "nat.h"
41 #include "file.h"
42 #include "xy.h"
43 #include "nsc.h"
44 #include <fcntl.h>
45 #include <ctype.h>
46 #include "commands.h"
47 #include "optlist.h"
48
49 struct stats {
50     double res;
51     double tech;
52     double edu;
53     double hap;
54     int stat;
55 };
56
57 static void printdiff(int mystat, double ours, struct natstr *natp,
58                       int what);
59 static void repo_header(void);
60 static void repo_list(struct stats *stat, natid cn, struct natstr *natp);
61
62 static int check(s_char *buf, double theirs, double min, double max,
63                  int shift, int tolerance);
64
65 int
66 repo(void)
67 {
68     struct natstr *natp;
69     struct stats mystat;
70     struct natstr nat;
71     struct nstr_item ni;
72     int first;
73
74     if (!snxtitem(&ni, EF_NATION, player->argp[1]))
75         return RET_SYN;
76     prdate();
77     natp = getnatp(player->cnum);
78     memset(&mystat, 0, sizeof(struct stats));
79     mystat.stat = natp->nat_stat;
80     if (mystat.stat & STAT_NORM) {
81         mystat.res = natp->nat_level[NAT_RLEV];
82         mystat.tech = natp->nat_level[NAT_TLEV];
83         mystat.edu = natp->nat_level[NAT_ELEV];
84         mystat.hap = natp->nat_level[NAT_HLEV];
85     }
86     if (opt_HIDDEN) {
87         repo_header();
88         first = 0;
89     } else {
90         first = 1;
91     }
92     while (nxtitem(&ni, (s_char *)&nat)) {
93         if (!(nat.nat_stat & STAT_INUSE))
94             continue;
95         if (opt_HIDDEN) {
96             if (!player->god && !getcontact(getnatp(player->cnum), ni.cur))
97                 continue;
98         }
99         if (first) {
100             repo_header();
101             first = 0;
102         }
103         repo_list(&mystat, (natid)ni.cur, &nat);
104     }
105     return RET_OK;
106 }
107
108 static void
109 repo_header(void)
110 {
111     pr(" #    name                tech      research   education   happiness ");
112     if (player->god)
113         pr("capital\n");
114     else {
115         if (opt_HIDDEN)
116             pr("\n");
117         else
118             pr(" status\n");
119     }
120 }
121
122 static void
123 repo_list(struct stats *stat, natid cn, struct natstr *natp)
124 {
125     struct sctstr cap;
126
127     if (player->god) {
128         pr(" %-3d   %-14.14s ", cn, natp->nat_cnam);
129         pr(" %7.2f    %7.2f      %7.2f     %7.2f",
130            natp->nat_level[NAT_TLEV],
131            natp->nat_level[NAT_RLEV],
132            natp->nat_level[NAT_ELEV], natp->nat_level[NAT_HLEV]);
133         prxy("  %4d,%-4d\n", natp->nat_xcap, natp->nat_ycap, player->cnum);
134         return;
135     }
136     switch (natp->
137             nat_stat & (STAT_NORM | STAT_GOD | STAT_NEW | STAT_SANCT)) {
138     case STAT_NORM:
139     case (STAT_NORM | STAT_SANCT):
140         pr(" %-3d   %-14.14s ", cn, natp->nat_cnam);
141         printdiff(stat->stat, stat->tech, natp, NAT_TLEV);
142         printdiff(stat->stat, stat->res, natp, NAT_RLEV);
143         printdiff(stat->stat, stat->edu, natp, NAT_ELEV);
144         printdiff(stat->stat, stat->hap, natp, NAT_HLEV);
145         getsect(natp->nat_xcap, natp->nat_ycap, &cap);
146         if (opt_HIDDEN) {
147             pr("\n");
148         } else {
149             if ((cap.sct_own != cn) ||
150                 (cap.sct_type != SCT_CAPIT &&
151                  cap.sct_type != SCT_MOUNT) ||
152                 (natp->nat_flags & NF_SACKED))
153                 pr("In flux\n");
154             else if (natp->nat_money <= 0)
155                 pr("Broke\n");
156             else
157                 pr("Active\n");
158         }
159         break;
160     case STAT_SANCT:
161         break;
162     case STAT_NEW:
163     case 0:
164         break;
165     case STAT_SANCT | STAT_NORM | STAT_GOD:
166     case STAT_NORM | STAT_GOD:
167     case STAT_GOD:
168         break;
169     default:
170         pr("????        ????        ????        ????\n");
171         break;
172     }
173 }
174
175 static void
176 printdiff(int mystat, double ours, struct natstr *natp, int what)
177 {
178     double theirs;
179     int shift;
180     int tolerance;
181     s_char buf[128];
182
183     if (natp->nat_cnum == player->cnum) {
184         pr(" %7.2f    ", ours);
185         return;
186     }
187     if (ours && mystat & STAT_NORM && natp->nat_stat & STAT_NORM) {
188         theirs = natp->nat_level[what];
189         if ((shift = min((int)theirs, (int)ours) - 100) > 0) {
190             ours -= shift;
191             theirs -= shift;
192         } else
193             shift = 0;
194         switch (what) {
195         case NAT_TLEV:
196             tolerance = 20;
197             break;
198         case NAT_RLEV:
199             tolerance = 10;
200             break;
201         default:
202             tolerance = 5;
203         }
204         if (tolerance > 2 * ours)
205             tolerance = (int)(2 * ours);
206         if (check(buf, theirs, 2 * ours, -1.0, shift, tolerance))
207           ;
208         else if (check(buf, theirs, 1.5 * ours, 2.0 * ours, shift, tolerance))
209           ;
210         else if (check(buf, theirs, 1.2 * ours, 1.5 * ours, shift, tolerance))
211           ;
212         else if (check(buf, theirs, 1.1 * ours, 1.2 * ours, shift, tolerance))
213           ;
214         else if (check(buf, theirs, ours / 1.1, 1.1 * ours, shift, tolerance))
215           ;
216         else if (check(buf, theirs, ours / 1.2, ours / 1.1, shift, tolerance))
217           ;
218         else if (check(buf, theirs, ours / 1.5, ours / 1.2, shift, tolerance))
219           ;
220         else if (check(buf, theirs, ours / 2.0, ours / 1.5, shift, tolerance))
221           ;
222         else if (check(buf, theirs, -1.0, ours / 2.0, shift, tolerance)) ;
223         else
224             sprintf(buf, "    n/a");
225     } else
226         sprintf(buf, "    n/a");
227
228     pr("%-11s ", buf);
229 }
230
231 static int
232 check(s_char *buf, double theirs, double min, double max, int shift,
233       int tolerance)
234 {
235     double shove;
236
237     if (min < 0) {
238         if (theirs <= max) {
239             if (max < tolerance)
240                 max = tolerance;
241             sprintf(buf, "   0 - %d", (int)max + shift);
242             return 1;
243         }
244     } else if (max < 0) {
245         if (theirs >= min) {
246             sprintf(buf, "    >= %d", (int)min + shift);
247             return 1;
248         }
249     } else if (theirs >= min && theirs <= max) {
250         if (max - min < tolerance) {
251             shove = (tolerance - (max - min)) / 2;
252             if (min + shift - shove >= 0) {
253                 min -= shove;
254                 max += shove;
255             } else {
256                 min = 0;
257                 max = tolerance;
258             }
259         }
260         sprintf(buf, "%4d - %d", (int)min + shift, (int)max + shift);
261         return 1;
262     }
263
264     return 0;
265 }