00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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, §)) {
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
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
00320
00321
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 }