src/lib/commands/prod.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  *  prod.c: Calculate production levels
00029  * 
00030  *  Known contributors to this file:
00031  *     David Muir Sharnoff, 1987
00032  *     Steve McClure, 1997-2000
00033  *     Markus Armbruster, 2004-2006
00034  */
00035 
00036 #include <config.h>
00037 
00038 #include "commands.h"
00039 #include "item.h"
00040 #include "optlist.h"
00041 #include "product.h"
00042 
00043 static void prprod(coord, coord, int, double, double, int, char,
00044                    double, double, double, char[], int[], int[], int);
00045 
00046 int
00047 count_pop(int n)
00048 {
00049     int i;
00050     int pop = 0;
00051     struct sctstr *sp;
00052 
00053     for (i = 0; NULL != (sp = getsectid(i)); i++) {
00054         if (sp->sct_own != n)
00055             continue;
00056         if (sp->sct_oldown != n)
00057             continue;
00058         pop += sp->sct_item[I_CIVIL];
00059     }
00060     return pop;
00061 }
00062 
00063 int
00064 prod(void)
00065 {
00066     struct natstr *natp;
00067     struct sctstr sect;
00068     struct nstr_sect nstr;
00069     struct pchrstr *pp;
00070     double p_e;
00071     double maxr;                /* floating version of max */
00072     double prodeff;
00073     double real;                /* floating pt version of act */
00074     int work;
00075     int totpop;
00076     int act;                    /* actual production */
00077     double cost;
00078     int i;
00079     int max;                    /* production w/infinite materials */
00080     int nsect;
00081     double take;
00082     double mtake;
00083     int there;
00084     int unit_work;              /* sum of component amounts */
00085     int used;                   /* production w/infinite workforce */
00086     i_type it;
00087     i_type vtype;
00088     unsigned char *resource;
00089     char cmnem[MAXPRCON];
00090     int cuse[MAXPRCON], cmax[MAXPRCON];
00091     int lcms, hcms;
00092     int civs;
00093     int uws;
00094     int bwork;
00095     int twork;
00096     int type;
00097     int eff;
00098     int maxpop;
00099     int otype;
00100     char mnem;
00101 
00102     if (!snxtsct(&nstr, player->argp[1]))
00103         return RET_SYN;
00104     player->simulation = 1;
00105     prdate();
00106     nsect = 0;
00107     while (nxtsct(&nstr, &sect)) {
00108         if (!player->owner)
00109             continue;
00110 
00111         civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL];
00112         uws = (1.0 + uwbrate * etu_per_update) * sect.sct_item[I_UW];
00113         natp = getnatp(sect.sct_own);
00114         maxpop = max_pop(natp->nat_level[NAT_RLEV], &sect);
00115 
00116         work = new_work(&sect,
00117                         total_work(sect.sct_work, etu_per_update,
00118                                    civs, sect.sct_item[I_MILIT], uws,
00119                                    maxpop));
00120         bwork = work / 2;
00121 
00122         if (sect.sct_off)
00123             continue;
00124         type = sect.sct_type;
00125         eff = sect.sct_effic;
00126         if (sect.sct_newtype != type) {
00127             twork = (eff + 3) / 4;
00128             if (twork > bwork) {
00129                 twork = bwork;
00130             }
00131             bwork -= twork;
00132             eff -= twork * 4;
00133             otype = type;
00134             if (eff <= 0) {
00135                 type = sect.sct_newtype;
00136                 eff = 0;
00137             }
00138             if (!eff && IS_BIG_CITY(otype) && !IS_BIG_CITY(type)) {
00139                 natp = getnatp(sect.sct_own);
00140                 maxpop = max_population(natp->nat_level[NAT_RLEV],
00141                                         type, eff);
00142                 work = new_work(&sect,
00143                                 total_work(sect.sct_work, etu_per_update,
00144                                            civs, sect.sct_item[I_MILIT],
00145                                            uws, maxpop));
00146                 bwork = MIN(work / 2, bwork);
00147             }
00148             twork = 100 - eff;
00149             if (twork > bwork) {
00150                 twork = bwork;
00151             }
00152             if (dchr[type].d_lcms > 0) {
00153                 lcms = sect.sct_item[I_LCM];
00154                 lcms /= dchr[type].d_lcms;
00155                 if (twork > lcms)
00156                     twork = lcms;
00157             }
00158             if (dchr[type].d_hcms > 0) {
00159                 hcms = sect.sct_item[I_HCM];
00160                 hcms /= dchr[type].d_hcms;
00161                 if (twork > hcms)
00162                     twork = hcms;
00163             }
00164             bwork -= twork;
00165             eff += twork;
00166         } else if (eff < 100) {
00167             twork = 100 - eff;
00168             if (twork > bwork) {
00169                 twork = bwork;
00170             }
00171             bwork -= twork;
00172             eff += twork;
00173         }
00174         work = (work + 1) / 2 + bwork;
00175         if (eff < 60)
00176             continue;
00177 
00178         p_e = eff / 100.0;
00179         if (p_e > 1.0)
00180             p_e = 1.0;
00181 
00182         if (type == SCT_ENLIST) {
00183             int maxmil;
00184             int enlisted;
00185 
00186             if (sect.sct_own != sect.sct_oldown)
00187                 continue;
00188             civs = (1.0 + obrate * etu_per_update) * sect.sct_item[I_CIVIL];
00189             natp = getnatp(sect.sct_own);
00190             maxpop = max_pop(natp->nat_level[NAT_RLEV], &sect);
00191             civs = MIN(civs, maxpop);
00192             enlisted = 0;
00193             maxmil = (civs / 2) - sect.sct_item[I_MILIT];
00194             if (maxmil > 0) {
00195                 enlisted = (etu_per_update
00196                             * (10 + sect.sct_item[I_MILIT])
00197                             * 0.05);
00198                 if (enlisted > maxmil)
00199                     enlisted = maxmil;
00200             }
00201             if (enlisted < 0)
00202                 enlisted = 0;
00203             prprod(sect.sct_x, sect.sct_y, type, p_e, 1.0, work,
00204                    ichr[I_MILIT].i_mnem, enlisted, maxmil, enlisted * 3,
00205                    "c\0\0", &enlisted, &enlisted, nsect++);
00206             continue;
00207         }
00208 
00209         if (dchr[type].d_prd < 0)
00210             continue;
00211         unit_work = 0;
00212         pp = &pchr[dchr[type].d_prd];
00213         vtype = pp->p_type;
00214         natp = getnatp(sect.sct_own);
00215         /*
00216          * sect p_e  (inc improvements)
00217          */
00218         if (pp->p_nrndx != 0) {
00219             unit_work++;
00220             resource = (unsigned char *)&sect + pp->p_nrndx;
00221             p_e = (*resource * p_e) / 100.0;
00222         }
00223         /*
00224          * production effic.
00225          */
00226         prodeff = prod_eff(type, natp->nat_level[pp->p_nlndx]);
00227         /*
00228          * raw material limit
00229          */
00230         used = 9999;
00231         for (i = 0; i < MAXPRCON; ++i) {
00232             it = pp->p_ctype[i];
00233             if (!pp->p_camt[i])
00234                 continue;
00235             if (CANT_HAPPEN(it <= I_NONE || I_MAX < it))
00236                 continue;
00237             used = MIN(used, sect.sct_item[it] / pp->p_camt[i]);
00238             unit_work += pp->p_camt[i];
00239         }
00240         if (unit_work == 0)
00241             unit_work = 1;
00242         /*
00243          * is production limited by resources or
00244          * workforce?
00245          */
00246         max = (int)(work * p_e / (double)unit_work + 0.5);
00247         if (pp->p_nrdep != 0 && vtype != I_NONE) {
00248             if (*resource * 100 < pp->p_nrdep * max)
00249                 max = *resource * 100 / pp->p_nrdep;
00250         }
00251         act = MIN(used, max);
00252 
00253         real = MIN(999.0, (double)act * prodeff);
00254         maxr = MIN(999.0, (double)max * prodeff);
00255 
00256         if (vtype != I_NONE) {
00257             if (real < 0.0)
00258                 real = 0.0;
00259             /* production backlog? */
00260             there = MIN(ITEM_MAX, sect.sct_item[vtype]);
00261             real = MIN(real, ITEM_MAX - there);
00262         }
00263 
00264         if (prodeff != 0) {
00265             take = real / prodeff;
00266             mtake = maxr / prodeff;
00267         } else
00268             mtake = take = 0.0;
00269 
00270         cost = take * pp->p_cost;
00271         if (opt_TECH_POP) {
00272             if (pp->p_level == NAT_TLEV) {
00273                 totpop = count_pop(sect.sct_own);
00274                 if (totpop > 50000)
00275                     cost *= totpop / 50000.0;
00276             }
00277         }
00278 
00279         for (i = 0; i < MAXPRCON; ++i) {
00280             cmnem[i] = cuse[i] = cmax[i] = 0;
00281             if (!pp->p_camt[i])
00282                 continue;
00283             it = pp->p_ctype[i];
00284             if (CANT_HAPPEN(it <= I_NONE || I_MAX < it))
00285                 continue;
00286             cmnem[i] = ichr[it].i_mnem;
00287             cuse[i] = (int)(take * pp->p_camt[i] + 0.5);
00288             cmax[i] = (int)(mtake * pp->p_camt[i] + 0.5);
00289         }
00290 
00291         if (pp->p_type != I_NONE)
00292             mnem = ichr[vtype].i_mnem;
00293         else if (pp->p_level == NAT_TLEV || pp->p_level == NAT_RLEV)
00294             mnem = '.';
00295         else
00296             mnem = 0;
00297         prprod(sect.sct_x, sect.sct_y, type, p_e, prodeff, work,
00298                mnem, real, maxr, cost,
00299                cmnem, cuse, cmax, nsect++);
00300     }
00301     player->simulation = 0;
00302     if (nsect == 0) {
00303         if (player->argp[1])
00304             pr("%s: No sector(s)\n", player->argp[1]);
00305         else
00306             pr("%s: No sector(s)\n", "");
00307         return RET_FAIL;
00308     } else
00309         pr("%d sector%s\n", nsect, splur(nsect));
00310     return RET_OK;
00311 }
00312 
00313 static void
00314 prprod(coord x, coord y, int type, double p_e, double prodeff, int work,
00315        char mnem, double make, double max, double cost,
00316        char cmnem[], int cuse[], int cmax[], int nsect)
00317 {
00318     int i;
00319 
00320     if (nsect == 0) {
00321         pr("PRODUCTION SIMULATION\n");
00322         pr("   sect  des eff avail  make p.e. cost   use1 use2 use3  max1 max2 max3   max\n");
00323     }
00324 
00325     prxy("%4d,%-4d", x, y, player->cnum);
00326     pr(" %c %3.0f%% %5d", dchr[type].d_mnem, p_e * 100.0, work);
00327     if (mnem == '.')
00328         pr(" %5.2f", make);
00329     else
00330         pr(" %4.0f%c", make, mnem ? mnem : ' ');
00331     pr(" %.2f $%-5.0f", prodeff, cost);
00332     for (i = 0; i < 3; i++) {
00333         if (i < MAXPRCON && cmnem[i])
00334             pr("%4d%c", cuse[i], cmnem[i]);
00335         else
00336             pr("     ");
00337     }
00338     pr(" ");
00339     for (i = 0; i < 3; i++) {
00340         if (i < MAXPRCON && cmnem[i])
00341             pr("%4d%c", cmax[i], cmnem[i]);
00342         else
00343             pr("     ");
00344     }
00345     if (mnem == '.')
00346         pr(" %5.2f\n", max);
00347     else
00348         pr(" %5.0f\n", max);
00349 }

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