src/lib/commands/powe.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  powe.c: Do a power report
00029  * 
00030  *  Known contributors to this file:
00031  *     Dave Pare
00032  *     Ken Stevens, 1995
00033  *     Steve McClure, 1998-2000
00034  *     Markus Armbruster, 2006
00035  */
00036 
00037 #include <config.h>
00038 #include <unistd.h>
00039 #include <math.h>
00040 
00041 #include "commands.h"
00042 #include "item.h"
00043 #include "land.h"
00044 #include "optlist.h"
00045 #include "plane.h"
00046 #include "power.h"
00047 #include "ship.h"
00048 
00049 static void prpower(char *, struct powstr *, int);
00050 static void out5(double, int, int);
00051 static void gen_power(struct powstr *, int);
00052 static int powcmp(const void *, const void *);
00053 static void addtopow(short *, struct powstr *);
00054 
00055 int
00056 powe(void)
00057 {
00058     struct natstr *natp;
00059     int i;
00060     time_t pow_time;
00061     struct nstr_item ni;
00062     int save = 1;
00063     int num = MAXNOC;
00064     int power_generated = 0;
00065     struct natstr nat;
00066     struct powstr powbuf[MAXNOC];
00067     int targets[MAXNOC];
00068     int use_targets = 0;
00069     int no_numbers = 0;
00070 
00071     memset(targets, 0, sizeof(targets));
00072 
00073     i = 1;
00074     if (player->argp[1]) {
00075         switch (player->argp[1][0]) {
00076         case 'u':
00077             if (player->god)
00078                 save = 0;
00079             /* fall through */
00080         case 'n':
00081             i++;
00082             natp = getnatp(player->cnum);
00083             if (natp->nat_btu < 1)
00084                 pr("\n  Insufficient BTUs, using the last report.\n\n");
00085             else if (opt_AUTO_POWER && save)
00086                 pr("\n  power new is disabled, using the last report.\n\n");
00087             else {
00088                 gen_power(powbuf, save);
00089                 pow_time = time(NULL);
00090                 power_generated = 1;
00091             }
00092         }
00093     }
00094 
00095     if (player->argp[i]) {
00096         if (player->argp[i][0] == 'c') {
00097             snxtitem(&ni, EF_NATION, player->argp[i + 1]);
00098             while (nxtitem(&ni, &nat)) {
00099                 if (nat.nat_stat != STAT_ACTIVE)
00100                     continue;
00101                 targets[nat.nat_cnum] = 1;
00102             }
00103             use_targets = 1;
00104         } else
00105             num = atoi(player->argp[i]);
00106     }
00107 
00108     if (num < 0) {
00109         if (!player->god)
00110             return RET_SYN;
00111         num = -num;
00112         no_numbers = 1;
00113     }
00114 
00115     if (!power_generated) {
00116         pow_time = ef_mtime(EF_POWER);
00117         snxtitem_all(&ni, EF_POWER);
00118         if (!nxtitem(&ni, &powbuf[0])) {
00119             pr("Power for this game has not been built yet.%s\n",
00120                opt_AUTO_POWER ? "" : "  Type 'power new' to build it.");
00121             return RET_FAIL;
00122         }
00123         for (i = 1; i < MAXNOC; i++) {
00124             if (!nxtitem(&ni, &powbuf[i])) {
00125                 CANT_REACH();
00126                 memset(&powbuf[i], 0, sizeof(powbuf[i]));
00127             }
00128         }
00129     }
00130 
00131     pr("     - = [   Empire Power Report   ] = -\n");
00132     pr("      as of %s\n         sects  eff civ", ctime(&pow_time));
00133     pr("  mil  shell gun pet  iron dust oil  pln ship unit money\n");
00134     for (i = 1; i < MAXNOC && num > 0; i++) {
00135         if (opt_HIDDEN) {
00136             if (!player->god && powbuf[i].p_nation != player->cnum)
00137                 continue;
00138         }
00139         if (use_targets && !targets[powbuf[i].p_nation])
00140             continue;
00141         if (!use_targets && powbuf[i].p_power <= 0.0)
00142             continue;
00143         prpower(cname(powbuf[i].p_nation), &powbuf[i],
00144                 powbuf[i].p_nation != player->cnum && !player->god);
00145         if (player->god && !no_numbers)
00146             pr("%9.2f\n", powbuf[i].p_power);
00147         num--;
00148     }
00149     if (!opt_HIDDEN || player->god) {
00150         pr("          ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n");
00151         prpower("worldwide", &powbuf[0], !player->god);
00152         pr("\n");
00153     }
00154     return RET_OK;
00155 }
00156 
00157 static void
00158 prpower(char *name, struct powstr *pow, int round_flag)
00159 {
00160     pr("%9.9s", name);
00161     out5(pow->p_sects, 5, round_flag);
00162     if (pow->p_sects)
00163         pr("%4.0f%%", pow->p_effic / pow->p_sects);
00164     else
00165         pr("   0%%");
00166     out5(pow->p_civil, 50, round_flag);
00167     out5(pow->p_milit, 50, round_flag);
00168     out5(pow->p_shell, 25, round_flag);
00169     out5(pow->p_guns, 5, round_flag);
00170     out5(pow->p_petrol, 50, round_flag);
00171     out5(pow->p_iron, 50, round_flag);
00172     out5(pow->p_dust, 50, round_flag);
00173     out5(pow->p_oil, 50, round_flag);
00174     out5(pow->p_planes, 10, round_flag);
00175     out5(pow->p_ships, 10, round_flag);
00176     out5(pow->p_units, 10, round_flag);
00177     out5(pow->p_money, 5000, round_flag);
00178     pr("\n");
00179 }
00180 
00181 static void
00182 out5(double value, int round_val, int round_flag)
00183 {
00184     double aval;
00185 
00186     if (value > round_val && round_flag)
00187         value = (int)(value / round_val + 0.5) * round_val;
00188     aval = fabs(value);
00189     if (aval < 1000.)
00190         pr("%4.0f ", value);
00191     else if (aval < 9.95e3)
00192         pr("%4.1fK", value / 1e3);
00193     else if (aval < 999.5e3)
00194         pr("%4.0fK", value / 1e3);
00195     else if (aval < 9.95e6)
00196         pr("%4.1fM", value / 1e6);
00197     else if (aval < 999.5e6)
00198         pr("%4.0fM", value / 1e6);
00199     else
00200         pr("%4.0fG", value / 1e9);
00201 }
00202 
00203 void
00204 update_power(void)
00205 {
00206     struct powstr powbuf[MAXNOC];
00207 
00208     gen_power(powbuf, 1);
00209 }
00210 
00211 static void
00212 gen_power(struct powstr *powbuf, int save)
00213 {
00214     float *f_ptr;
00215     float *f_pt2;
00216     struct powstr *pow;
00217     int i;
00218     struct sctstr sect;
00219     struct plnstr plane;
00220     struct shpstr ship;
00221     struct lndstr land;
00222     struct nstr_item ni;
00223     struct nstr_sect ns;
00224     struct natstr *natp;
00225     float f;
00226 
00227     player->btused += 10;
00228     memset(powbuf, 0, MAXNOC * sizeof(*powbuf));
00229     snxtsct_all(&ns);
00230     while (nxtsct(&ns, &sect)) {
00231         if (sect.sct_own == 0)
00232             continue;
00233         pow = &powbuf[sect.sct_own];
00234         pow->p_sects += 1.0;
00235         pow->p_effic += sect.sct_effic;
00236         addtopow(sect.sct_item, pow);
00237     }
00238     snxtitem_all(&ni, EF_LAND);
00239     while (nxtitem(&ni, &land)) {
00240         if (land.lnd_own == 0)
00241             continue;
00242         pow = &powbuf[land.lnd_own];
00243         addtopow(land.lnd_item, pow);
00244         f = (lchr[(int)land.lnd_type].l_lcm / 10.0) * (land.lnd_effic / 100.0);
00245         f += (lchr[(int)land.lnd_type].l_hcm / 10.0) * (land.lnd_effic / 100.0);
00246         pow->p_power += f * 2;
00247         if (!(lchr[(int)land.lnd_type].l_flags & L_SPY))
00248             pow->p_units += 1.0;
00249     }
00250     snxtitem_all(&ni, EF_SHIP);
00251     while (nxtitem(&ni, &ship)) {
00252         if (ship.shp_own == 0)
00253             continue;
00254         pow = &powbuf[ship.shp_own];
00255         addtopow(ship.shp_item, pow);
00256         f = (mchr[(int)ship.shp_type].m_lcm / 10.0) * (ship.shp_effic / 100.0);
00257         f += (mchr[(int)ship.shp_type].m_hcm / 10.0) * (ship.shp_effic / 100.0);
00258         pow->p_power += f * 2;
00259         pow->p_ships += 1.0;
00260     }
00261     snxtitem_all(&ni, EF_PLANE);
00262     while (nxtitem(&ni, &plane)) {
00263         if (plane.pln_own == 0)
00264             continue;
00265         pow = &powbuf[plane.pln_own];
00266         pow->p_planes += 1.0;
00267         natp = getnatp(plane.pln_own);
00268         pow->p_power += 20 * (plane.pln_effic / 100.0) *
00269             (natp->nat_level[NAT_TLEV] / 500.0);
00270     }
00271     for (i = 1; NULL != (natp = getnatp(i)); i++) {
00272         pow = &powbuf[i];
00273         pow->p_nation = i;
00274         if (natp->nat_stat != STAT_ACTIVE) {
00275             pow->p_power = 0.;
00276             continue;
00277         }
00278         pow->p_money = natp->nat_money;
00279         pow->p_power += pow->p_money / 100.;
00280 
00281         pow->p_power += pow->p_petrol / 500.0;
00282 
00283         pow->p_power += (pow->p_civil + pow->p_milit) / 10.0;
00284         pow->p_power += pow->p_shell / 12.5;
00285         pow->p_power += pow->p_iron / 100.0;
00286         pow->p_power += pow->p_dust / 5 + pow->p_oil / 10 + pow->p_bars;
00287         pow->p_power += pow->p_guns / 2.5;
00288         if (pow->p_sects > 0)
00289             pow->p_power += pow->p_sects
00290                 * (pow->p_effic / pow->p_sects / 100.0)
00291                 * 10.0;
00292         pow->p_power *= MAX(1.0, natp->nat_level[NAT_TLEV]) / 500.0;
00293         /* ack.  add this vec to the "world power" element */
00294         f_pt2 = &powbuf[0].p_sects;
00295         f_ptr = &pow->p_sects;
00296         while (f_ptr <= &pow->p_power) {
00297             *f_pt2 += *f_ptr;
00298             f_pt2++;
00299             f_ptr++;
00300         }
00301     }
00302     for (i = 1; i < MAXNOC; i++) {
00303         struct natstr *np;
00304         int maxpop;
00305 
00306         if (opt_RES_POP) {
00307             np = getnatp(i);
00308             maxpop = max_population(np->nat_level[NAT_RLEV], SCT_MINE, 0);
00309             powbuf[i].p_power *= 1.0 + maxpop / 10000.0;
00310         }
00311     }
00312     qsort(&powbuf[1], MAXNOC - 1, sizeof(*powbuf), powcmp);
00313     if (!save)
00314         return;
00315     for (i = 0; i < MAXNOC; i++)
00316         putpower(i, &powbuf[i]);
00317 #ifdef _WIN32
00318     /*
00319      * At least some versions of Windows fail to update mtime on
00320      * write(), they delay it until the write actually hits the disk.
00321      * Bad, because `power' displays that time.  Force it.
00322      */
00323     fsync(empfile[EF_POWER].fd);
00324 #endif
00325 }
00326 
00327 static int
00328 powcmp(const void *a, const void *b)
00329 {
00330     const struct powstr *p1 = a;
00331     const struct powstr *p2 = b;
00332 
00333     if (p1->p_power > p2->p_power)
00334         return -1;
00335     if (p1->p_power < p2->p_power)
00336         return 1;
00337     return 0;
00338 }
00339 
00340 static void
00341 addtopow(short *vec, struct powstr *pow)
00342 {
00343     pow->p_civil += vec[I_CIVIL];
00344     pow->p_milit += vec[I_MILIT];
00345     pow->p_shell += vec[I_SHELL];
00346     pow->p_guns += vec[I_GUN];
00347     pow->p_petrol += vec[I_PETROL];
00348     pow->p_iron += vec[I_IRON];
00349     pow->p_dust += vec[I_DUST];
00350     pow->p_food += vec[I_FOOD];
00351     pow->p_oil += vec[I_OIL];
00352     pow->p_bars += vec[I_BAR];
00353     pow->p_power += vec[I_LCM] / 10.0;
00354     pow->p_power += vec[I_HCM] / 5.0;
00355 }

Generated on Fri Mar 28 11:01:12 2008 for empserver by  doxygen 1.5.2