]> git.pond.sub.org Git - empserver/blob - src/lib/subs/show.c
(show_bridge, show_tower, show_ship_stats): Simplify, no functional
[empserver] / src / lib / subs / show.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  *  show.c: General show routines
29  * 
30  *  Known contributors to this file:
31  *     Julian Onions, 1988
32  *     Jeff Bailey, 1990
33  *     Steve McClure, 1996
34  *     Ron Koenderink, 2005
35  *     Markus Armbruster, 2006-2007
36  */
37
38 #include <config.h>
39
40 #if defined(_WIN32)
41 #include <Windows.h>
42 #endif
43
44 #include <math.h>
45 #include "file.h"
46 #include "game.h"
47 #include "item.h"
48 #include "land.h"
49 #include "nat.h"
50 #include "news.h"
51 #include "nuke.h"
52 #include "optlist.h"
53 #include "plane.h"
54 #include "player.h"
55 #include "product.h"
56 #include "prototypes.h"
57 #include "sect.h"
58 #include "server.h"
59 #include "ship.h"
60
61 static char *fmttime2822(time_t);
62
63 struct look_list {
64     union {
65         struct lchrstr *lp;
66         struct plchrstr *pp;
67         struct mchrstr *mp;
68     } l_u;
69     int tech;
70 };
71
72 /*
73  * Change this if there are ever more than 200 ships, plane or land
74  * unit types.
75  */
76 static struct look_list lookup_list[200];
77 static int lookup_list_cnt = 0;
78
79 static void
80 sort_lookup_list(void)
81 {
82     struct natstr *np = getnatp(player->cnum);
83     struct look_list tmp;
84     int i;
85     int j;
86
87     if (!(np->nat_flags & NF_TECHLISTS))
88         return;
89     for (i = 0; i < lookup_list_cnt; i++) {
90         for (j = i; j < lookup_list_cnt; j++) {
91             if (lookup_list[j].tech < lookup_list[i].tech) {
92                 tmp = lookup_list[j];
93                 lookup_list[j] = lookup_list[i];
94                 lookup_list[i] = tmp;
95             }
96         }
97     }
98 }
99
100 static void
101 make_new_list(int tlev, int type)
102 {
103     struct plchrstr *pp;
104     struct lchrstr *lp;
105     struct mchrstr *mp;
106
107     lookup_list_cnt = 0;
108     if (type == EF_PLANE) {
109         for (pp = plchr; pp->pl_name; pp++) {
110             if (pp->pl_tech > tlev)
111                 continue;
112             lookup_list[lookup_list_cnt].l_u.pp = pp;
113             lookup_list[lookup_list_cnt].tech = pp->pl_tech;
114             lookup_list_cnt++;
115         }
116     } else if (type == EF_SHIP) {
117         for (mp = mchr; mp->m_name; mp++) {
118             if (mp->m_tech > tlev)
119                 continue;
120             lookup_list[lookup_list_cnt].l_u.mp = mp;
121             lookup_list[lookup_list_cnt].tech = mp->m_tech;
122             lookup_list_cnt++;
123         }
124     } else if (type == EF_LAND) {
125         for (lp = lchr; lp->l_name; lp++) {
126             if (lp->l_tech > tlev)
127                 continue;
128             lookup_list[lookup_list_cnt].l_u.lp = lp;
129             lookup_list[lookup_list_cnt].tech = lp->l_tech;
130             lookup_list_cnt++;
131         }
132     } else
133         return;
134
135     sort_lookup_list();
136 }
137
138 void
139 show_bridge(int tlev)
140 {
141     if (tlev < buil_bt)
142         return;
143     pr("Bridges require %g tech, %d hcm, 0 workers,\n",
144        buil_bt, buil_bh);
145     pr("%d available workforce, and cost $%g\n",
146        (SCT_BLD_WORK(0, buil_bh) * SCT_MINEFF + 99) / 100,
147        buil_bc);
148 }
149
150 void
151 show_tower(int tlev)
152 {
153     if (tlev < buil_tower_bt)
154         return;
155     pr("Bridge Towers require %g tech, %d hcm, 0 workers,\n",
156        buil_tower_bt, buil_tower_bh);
157     pr("%d available workforce, and cost $%g\n",
158        (SCT_BLD_WORK(0, buil_tower_bh) * SCT_MINEFF + 99) / 100,
159        buil_tower_bc);
160 }
161
162 void
163 show_nuke_stats(int tlev)
164 {
165     show_nuke_capab(tlev);
166 }
167
168 void
169 show_nuke_build(int tlev)
170 {
171     struct nchrstr *np;
172     int avail;
173
174     pr("%13s lcm hcm  oil  rad avail tech res $\n", "");
175
176     for (np = nchr; np->n_name; np++) {
177         avail = NUK_BLD_WORK(np->n_lcm, np->n_hcm, np->n_oil, np->n_rad);
178         if (np->n_tech > tlev)
179             continue;
180         pr("%-13.13s %3d %3d %4d %4d %5d %4d %3.0f $%6d\n",
181            np->n_name, np->n_lcm, np->n_hcm, np->n_oil,
182            np->n_rad, avail, np->n_tech,
183            drnuke_const > MIN_DRNUKE_CONST ?
184                 ceil(np->n_tech * drnuke_const) : 0.0,
185            np->n_cost);
186     }
187 }
188
189 void
190 show_nuke_capab(int tlev)
191 {
192     struct nchrstr *np;
193     int i, j;
194     char *p;
195
196     pr("%13s blst dam lbs tech res $%7s abilities\n", "", "");
197
198     for (np = nchr; np->n_name; np++) {
199         if (np->n_tech > tlev)
200             continue;
201         pr("%-13.13s %4d %3d %3d %4d %3.0f $%7d ",
202            np->n_name, np->n_blast, np->n_dam,
203            np->n_weight, np->n_tech,
204            drnuke_const > MIN_DRNUKE_CONST ?
205                 ceil(np->n_tech * drnuke_const) : 0.0,
206            np->n_cost);
207         for (i = j = 0; i < 32; i++) {
208             if (!(np->n_flags & bit(i)))
209                 continue;
210             if (NULL != (p = symbol_by_value(bit(i), nuke_chr_flags))) {
211                 if (j++ > 0)
212                     pr(" ");
213                 pr("%s", p);
214             }
215         }
216         pr("\n");
217     }
218 }
219
220 void
221 show_ship_build(int tlev)
222 {
223     struct mchrstr *mp;
224     int n;
225
226     pr("%25s lcm hcm avail tech $\n", "");
227     make_new_list(tlev, EF_SHIP);
228     for (n = 0; n < lookup_list_cnt; n++) {
229         mp = (struct mchrstr *)lookup_list[n].l_u.mp;
230         /* Can't show trade ships unless it's turned on */
231         if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS)
232             continue;
233
234         pr("%-25.25s %3d %3d %5d %4d $%d\n",
235            mp->m_name, mp->m_lcm, mp->m_hcm,
236            SHP_BLD_WORK(mp->m_lcm, mp->m_hcm), mp->m_tech, mp->m_cost);
237     }
238 }
239
240 void
241 show_ship_stats(int tlev)
242 {
243     struct mchrstr *mp;
244     int scount;
245     int techdiff;
246
247     pr("%25s      s  v  s  r  f  l  p  h  x", "");
248     if (opt_FUEL)
249         pr("  fuel");
250     pr("\n");
251
252     pr("%25s      p  i  p  n  i  n  l  e  p", "");
253     if (opt_FUEL)
254         pr("   c/u");
255     pr("\n");
256
257     pr("%25s def  d  s  y  g  r  d  n  l  l", "");
258     if (opt_FUEL)
259         pr("      ");
260     pr("\n");
261
262
263     make_new_list(tlev, EF_SHIP);
264     for (scount = 0; scount < lookup_list_cnt; scount++) {
265         mp = (struct mchrstr *)lookup_list[scount].l_u.mp;
266         /* Can't show trade ships unless it's turned on */
267         if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS)
268             continue;
269
270         techdiff = (int)(tlev - mp->m_tech);
271         pr("%-25.25s %3d %2d %2d %2d %2d %2d ",
272            mp->m_name,
273            (short)SHP_DEF(mp->m_armor, techdiff),
274            (short)SHP_SPD(mp->m_speed, techdiff),
275            (short)SHP_VIS(mp->m_visib, techdiff),
276            mp->m_vrnge,
277            (short)SHP_RNG(mp->m_frnge, techdiff),
278            (short)SHP_FIR(mp->m_glim, techdiff));
279
280         pr("%2d ", mp->m_nland);
281         pr("%2d ", mp->m_nplanes);
282         pr("%2d ", mp->m_nchoppers);
283         pr("%2d ", mp->m_nxlight);
284         if (opt_FUEL)
285             pr("%3d/%1d ", mp->m_fuelc, mp->m_fuelu);
286         pr("\n");
287     }
288 }
289
290 void
291 show_ship_capab(int tlev)
292 {
293     struct mchrstr *mp;
294     i_type i;
295     int j;
296     int scount;
297     int n;
298     char *p;
299
300     pr("%25s cargos & capabilities\n", "");
301
302     make_new_list(tlev, EF_SHIP);
303     for (scount = 0; scount < lookup_list_cnt; scount++) {
304         mp = (struct mchrstr *)lookup_list[scount].l_u.mp;
305         /* Can't show trade ships unless it's turned on */
306         if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS)
307             continue;
308
309         pr("%-25.25s ", mp->m_name);
310
311         for (i = I_NONE + 1; i <= I_MAX; ++i)
312             if (mp->m_item[i])
313                 pr(" %d%c", mp->m_item[i], ichr[i].i_mnem);
314         pr(" ");
315         for (j = n = 0; j < 32; j++) {
316             if (!(mp->m_flags & bit(j)))
317                 continue;
318             if (NULL != (p = symbol_by_value(bit(j), ship_chr_flags))) {
319                 if (n++ > 0)
320                     pr(" ");
321                 pr("%s", p);
322             }
323         }
324         pr("\n");
325     }
326 }
327
328 void
329 show_plane_stats(int tlev)
330 {
331     struct plchrstr *pp;
332     int pcount;
333
334     pr("%25s acc load att def ran fuel stlth\n", "");
335     make_new_list(tlev, EF_PLANE);
336     for (pcount = 0; pcount < lookup_list_cnt; pcount++) {
337         pp = (struct plchrstr *)lookup_list[pcount].l_u.pp;
338         pr("%-25.25s %3d %4d %3d %3d %3d %4d ",
339            pp->pl_name,
340            (int)PLN_ACC(pp->pl_acc, (int)(tlev - pp->pl_tech)),
341            (int)PLN_LOAD(pp->pl_load, (int)(tlev - pp->pl_tech)),
342            (int)PLN_ATTDEF(pp->pl_att, (int)(tlev - pp->pl_tech)),
343            (int)PLN_ATTDEF(pp->pl_def, (int)(tlev - pp->pl_tech)),
344            (int)PLN_RAN(pp->pl_range, (int)(tlev - pp->pl_tech)),
345            pp->pl_fuel);
346         pr("%4d%% ", pp->pl_stealth);
347         pr("\n");
348     }
349 }
350
351 void
352 show_plane_capab(int tlev)
353 {
354     struct plchrstr *pp;
355     int i;
356     int pcount;
357     int n;
358     char *p;
359
360     pr("%25s capabilities\n", "");
361     make_new_list(tlev, EF_PLANE);
362     for (pcount = 0; pcount < lookup_list_cnt; pcount++) {
363         pp = (struct plchrstr *)lookup_list[pcount].l_u.pp;
364         pr("%-25.25s  ", pp->pl_name);
365
366         for (i = n = 0; i < 32; i++) {
367             if (!(pp->pl_flags & bit(i)))
368                 continue;
369             if (NULL != (p = symbol_by_value(bit(i), plane_chr_flags))) {
370                 if (n++ > 0)
371                     pr(" ");
372                 pr("%s", p);
373             }
374         }
375         pr("\n");
376     }
377 }
378
379 void
380 show_plane_build(int tlev)
381 {
382     struct plchrstr *pp;
383     int pcount;
384
385     pr("%25s lcm hcm crew avail tech $\n", "");
386     make_new_list(tlev, EF_PLANE);
387     for (pcount = 0; pcount < lookup_list_cnt; pcount++) {
388         pp = (struct plchrstr *)lookup_list[pcount].l_u.pp;
389         pr("%-25.25s %3d %3d %4d %5d %4d $%d\n",
390            pp->pl_name, pp->pl_lcm,
391            pp->pl_hcm, pp->pl_crew,
392            PLN_BLD_WORK(pp->pl_lcm, pp->pl_hcm), pp->pl_tech, pp->pl_cost);
393     }
394 }
395
396 void
397 show_land_build(int tlev)
398 {
399     struct lchrstr *lp;
400     int n;
401
402     pr("%25s lcm hcm guns avail tech $\n", "");
403     make_new_list(tlev, EF_LAND);
404     for (n = 0; n < lookup_list_cnt; n++) {
405         lp = (struct lchrstr *)lookup_list[n].l_u.lp;
406         if ((lp->l_flags & L_SPY) && !opt_LANDSPIES)
407             continue;
408         pr("%-25.25s %3d %3d %4d %5d %4d $%d\n",
409            lp->l_name, lp->l_lcm,
410            lp->l_hcm,
411            lp->l_gun,
412            LND_BLD_WORK(lp->l_lcm, lp->l_hcm), lp->l_tech, lp->l_cost);
413     }
414 }
415
416 void
417 show_land_capab(int tlev)
418 {
419     struct lchrstr *lcp;
420     int lcount;
421     i_type i;
422     int j, n;
423     char *p;
424
425     pr("%25s capabilities\n", "");
426
427     make_new_list(tlev, EF_LAND);
428     for (lcount = 0; lcount < lookup_list_cnt; lcount++) {
429         lcp = (struct lchrstr *)lookup_list[lcount].l_u.lp;
430         if ((lcp->l_flags & L_SPY) && !opt_LANDSPIES)
431             continue;
432
433         pr("%-25s ", lcp->l_name);
434
435         for (i = I_NONE + 1; i <= I_MAX; ++i)
436             if (lcp->l_item[i])
437                 pr(" %d%c", lcp->l_item[i], ichr[i].i_mnem);
438         pr(" ");
439         for (j = n = 0; j < 32; j++) {
440             if (!(lcp->l_flags & bit(j)))
441                 continue;
442             if (NULL != (p = symbol_by_value(bit(j), land_chr_flags))) {
443                 if (n++ > 0)
444                     pr(" ");
445                 pr("%s", p);
446             }
447         }
448         pr("\n");
449     }
450 }
451
452 void
453 show_land_stats(int tlev)
454 {
455     struct lchrstr *lcp;
456     int lcount;
457     int ourtlev;
458
459     pr("%25s              s  v  s  r  r  a  f  a  a        x  l\n", "");
460     pr("%25s              p  i  p  a  n  c  i  m  a  f  f  p  n\n", "");
461     pr("%25s att def vul  d  s  y  d  g  c  r  m  f  c  u  l  d\n", "");
462
463     make_new_list(tlev, EF_LAND);
464     for (lcount = 0; lcount < lookup_list_cnt; lcount++) {
465         lcp = (struct lchrstr *)lookup_list[lcount].l_u.lp;
466         if ((lcp->l_flags & L_SPY) && !opt_LANDSPIES)
467             continue;
468
469         ourtlev = (int)(tlev - lcp->l_tech);
470         pr("%-25s %1.1f %1.1f %3d ",
471            lcp->l_name,
472            LND_ATTDEF(lcp->l_att, ourtlev),
473            LND_ATTDEF(lcp->l_def, ourtlev),
474            (int)LND_VUL(lcp->l_vul, ourtlev));
475         pr("%2d %2d %2d %2d ",
476            (int)LND_SPD(lcp->l_spd, ourtlev),
477            (int)LND_VIS(lcp->l_vis, ourtlev),
478            (int)LND_SPY(lcp->l_spy, ourtlev),
479            (int)LND_RAD(lcp->l_rad, ourtlev));
480         pr("%2d %2d %2d %2d %2d ",
481            (int)LND_FRG(lcp->l_frg, ourtlev),
482            (int)LND_ACC(lcp->l_acc, ourtlev),
483            (int)LND_DAM(lcp->l_dam, ourtlev),
484            (int)LND_AMM(lcp->l_ammo, ourtlev),
485            (int)LND_AAF(lcp->l_aaf, ourtlev));
486         pr("%2d %2d %2d %2d ",
487            (int)LND_FC(lcp->l_fuelc, ourtlev),
488            (int)LND_FU(lcp->l_fuelu, ourtlev),
489            (int)LND_XPL(lcp->l_nxlight, ourtlev),
490            (int)LND_MXL(lcp->l_nland, ourtlev));
491
492         pr("\n");
493     }
494 }
495
496 void
497 show_sect_build(int foo)
498 {
499     int x, first;
500
501     first = 1;
502     for (x = 0; dchr[x].d_name; x++) {
503         if (dchr[x].d_mnem == 0)
504             continue;
505         if (dchr[x].d_cost < 0)
506             continue;
507         if ((dchr[x].d_cost > 0) || (dchr[x].d_build != 1) ||
508             (dchr[x].d_lcms > 0) || (dchr[x].d_hcms > 0)) {
509             if (first) {
510                 pr("sector type    cost to des    cost for 1%% eff   lcms for 1%%    hcms for 1%%\n");
511                 first = 0;
512             }
513             pr("%-14c %-14d %-17d %-14d %d\n",
514                dchr[x].d_mnem, dchr[x].d_cost, dchr[x].d_build,
515                dchr[x].d_lcms, dchr[x].d_hcms);
516         }
517     }
518
519     first = 1;
520     for (x = 0; intrchr[x].in_name; x++) {
521         if (!intrchr[x].in_enable)
522             continue;
523         if (first)
524             pr("\nInfrastructure building - adding 1 point of efficiency costs:\n"
525                "       type          lcms    hcms    mobility    $$$$\n");
526         pr("%-20s %4d    %4d    %8d    %4d\n",
527            intrchr[x].in_name, intrchr[x].in_lcms, intrchr[x].in_hcms,
528            intrchr[x].in_mcost, intrchr[x].in_dcost);
529         first = 0;
530     }
531 }
532
533 void
534 show_sect_stats(int foo)
535 {
536     int x, first = 1;
537     struct natstr *natp;
538
539     natp = getnatp(player->cnum);
540     for (x = 0; dchr[x].d_name; x++) {
541         if (dchr[x].d_mnem == 0)
542             continue;
543         if (first) {
544             pr("                        mob cost   max   max   --  packing bonus  --   max\n");
545             pr("  sector type            0%% 100%%   off   def   mil  uw civ bar other   pop\n");
546             first = 0;
547         }
548         pr("%c %-21.21s", dchr[x].d_mnem, dchr[x].d_name);
549         if (dchr[x].d_mob0 < 0)
550             pr("  no way ");
551         else
552             pr(" %3.1f  %3.1f", dchr[x].d_mob0, dchr[x].d_mob1);
553         pr("  %5.2f %5.2f   %3d %3d %3d %3d %5d %5d\n",
554            dchr[x].d_ostr, dchr[x].d_dstr,
555            ichr[I_MILIT].i_pkg[dchr[x].d_pkg],
556            ichr[I_UW].i_pkg[dchr[x].d_pkg],
557            ichr[I_CIVIL].i_pkg[dchr[x].d_pkg],
558            ichr[I_BAR].i_pkg[dchr[x].d_pkg],
559            ichr[I_LCM].i_pkg[dchr[x].d_pkg],
560            max_population(natp->nat_level[NAT_RLEV], x, 100));
561     }
562 }
563
564 void
565 show_sect_capab(int foo)
566 {
567     int x, first = 1, i, j;
568     char *tmpstr;
569
570     for (x = 0; dchr[x].d_name; x++) {
571         if (dchr[x].d_mnem == 0 || dchr[x].d_prd < 0)
572             continue;
573         if (first) {
574             pr("                                                 --- level ---          reso \n");
575             pr("  sector type             product use1 use2 use3 level min lag eff%% $$$ dep c\n");
576             first = 0;
577         }
578
579         j = dchr[x].d_prd;
580
581         pr("%c %-23s %-7s ",
582            dchr[x].d_mnem, dchr[x].d_name, pchr[j].p_sname);
583         (void)CANT_HAPPEN(MAXPRCON > 3); /* output has only three columns */
584         for (i = 0; i < 3; i++) {
585             if (i < MAXPRCON
586                 && pchr[j].p_camt[i]
587                 && pchr[j].p_ctype[i] > I_NONE
588                 && pchr[j].p_ctype[i] <= I_MAX) {
589                 pr("%2d %c ", pchr[j].p_camt[i],
590                    ichr[pchr[j].p_ctype[i]].i_name[0]);
591             } else {
592                 pr("     ");
593             }
594         }
595         switch (pchr[j].p_nlndx) {
596         case NAT_TLEV:
597             tmpstr = "tech";
598             break;
599         case NAT_ELEV:
600             tmpstr = "edu";
601             break;
602         case NAT_RLEV:
603             tmpstr = "res";
604             break;
605         case NAT_HLEV:
606             tmpstr = "hap";
607             break;
608         default:
609             tmpstr = " ";
610             break;
611         }
612         pr("%-5s %3d %3d %4d %3d %3d %c",
613            tmpstr,
614            pchr[j].p_nlmin,
615            pchr[j].p_nllag,
616            dchr[x].d_peffic, pchr[j].p_cost, pchr[j].p_nrdep,
617            pchr[j].p_type != I_NONE ? ichr[pchr[j].p_type].i_mnem : ' ');
618
619         pr("\n");
620     }
621 }
622
623 void
624 show_item(int tlev)
625 {
626     struct ichrstr *ip;
627
628     pr("item value sell lbs    packing     melt  item\n");
629     pr("mnem                in rg wh ur bk deno  name\n");
630
631     for (ip = ichr; ip->i_name; ip++) {
632         pr("   %c %5d %4s %3d %2d %2d %2d %2d %2d %4d  %s\n",
633            ip->i_mnem, ip->i_value, ip->i_sell ? "yes" : "no", ip->i_lbs,
634            ip->i_pkg[IPKG], ip->i_pkg[NPKG], ip->i_pkg[WPKG],
635            ip->i_pkg[UPKG], ip->i_pkg[BPKG],
636            ip->i_melt_denom, ip->i_name);
637     }
638 }
639
640 void
641 show_news(int tlev)
642 {
643     int i, j;
644     
645     pr("id category           good will\n");
646     pr("    messsages\n");
647
648     for (i = 1; i < N_MAX_VERB + 1; i++) {
649         if (rpt[i].r_newspage == N_NOTUSED)
650             continue;
651         pr("%-2d %-20.20s %4d\n", rpt[i].r_uid,
652             page_headings[rpt[i].r_newspage].name, rpt[i].r_good_will);
653         for (j = 0; j < NUM_RPTS; j++)
654             pr("    %s\n", rpt[i].r_newstory[j]);
655     }
656 }
657
658 /*
659  * Show update policy and up to N scheduled updates.
660  */
661 void
662 show_updates(int n)
663 {
664     struct gamestr *game = game_tick_tick();
665     int demand = 0;
666     int i;
667
668     pr("%s, Turn %d, ETU %d\n", fmttime2822(time(NULL)),
669        game->game_turn, game->game_tick);
670
671     if (update_time[0]) {
672         if (update_demand == UPD_DEMAND_SCHED) {
673             pr("Demand updates occur according to schedule:\n");
674             demand = 1;
675         } else
676             pr("Updates occur according to schedule:\n");
677         for (i = 0; i < n && update_time[i]; i++)
678             pr("%3d.  %s\n", game->game_turn + i,
679                fmttime2822(update_time[i]));
680         if (update_window) {
681             pr("Updates occur within %d seconds after the scheduled time\n",
682                update_window);
683         }
684     } else
685         pr("There are no updates scheduled.\n");
686
687     if (update_demand == UPD_DEMAND_ASYNC) {
688         pr("Demand updates occur right after the demand is set.\n");
689         if (*update_demandtimes != 0) {
690             pr("Demand updates are allowed during: %s\n",
691                update_demandtimes);
692         }
693         demand = 1;
694     }
695
696     if (demand) {
697         pr("Demand updates require %d country(s) to want one.\n",
698            update_wantmin);
699     }
700
701     if (updates_disabled())
702         pr("\nUPDATES ARE DISABLED!\n");
703 }
704
705 /*
706  * Return T formatted according to RFC 2822.
707  * The return value is statically allocated and overwritten on
708  * subsequent calls.
709  */
710 static char *
711 fmttime2822(time_t t)
712 {
713     static char buf[32];
714 #if defined(_WIN32)
715     size_t n;
716     int nn;
717     TIME_ZONE_INFORMATION tzi;
718     long time_offset;
719     struct tm *time;
720     
721     time = localtime(&t);
722
723     n = strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S", time);
724     if (CANT_HAPPEN(n == 0)) {
725         buf[0] = 0;
726         return buf;
727     }
728     GetTimeZoneInformation(&tzi);
729     time_offset = -(tzi.Bias +
730         (time->tm_isdst ? tzi.DaylightBias : tzi.StandardBias));
731
732     nn = _snprintf(buf + n, sizeof(buf) - n, " %+03d%02d",
733         time_offset/60, abs(time_offset) % 60);
734     if (CANT_HAPPEN(nn <= 0 || nn + n >= sizeof(buf)))
735         buf[0] = 0;
736 #else
737     size_t n = strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z",
738                      localtime(&t));
739     if (CANT_HAPPEN(n == 0))
740         buf[0] = 0;
741 #endif
742     return buf;
743 }