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
00039 #include <math.h>
00040 #include "budg.h"
00041 #include "land.h"
00042 #include "lost.h"
00043 #include "news.h"
00044 #include "plague.h"
00045 #include "player.h"
00046 #include "product.h"
00047 #include "ship.h"
00048 #include "update.h"
00049
00050 static void shiprepair(struct shpstr *, struct natstr *, struct bp *, int);
00051 static void upd_ship(struct shpstr *, int, struct natstr *, struct bp *, int);
00052 static int feed_ship(struct shpstr *, int);
00053
00054 int
00055 prod_ship(int etus, int natnum, struct bp *bp, int build)
00056
00057 {
00058 struct shpstr *sp;
00059 struct natstr *np;
00060 int n, k = 0;
00061 int start_money;
00062 int lastx = 9999, lasty = 9999;
00063
00064 bp_enable_cachepath();
00065 for (n = 0; NULL != (sp = getshipp(n)); n++) {
00066 if (sp->shp_own == 0)
00067 continue;
00068 if (sp->shp_own != natnum)
00069 continue;
00070 if (sp->shp_effic < SHIP_MINEFF) {
00071 makelost(EF_SHIP, sp->shp_own, sp->shp_uid,
00072 sp->shp_x, sp->shp_y);
00073 sp->shp_own = 0;
00074 continue;
00075 }
00076
00077 np = getnatp(sp->shp_own);
00078 if (lastx == 9999 || lasty == 9999) {
00079 lastx = sp->shp_x;
00080 lasty = sp->shp_y;
00081 }
00082 if (lastx != sp->shp_x || lasty != sp->shp_y) {
00083
00084 bp_disable_cachepath();
00085 bp_clear_cachepath();
00086 bp_enable_cachepath();
00087 }
00088 start_money = np->nat_money;
00089 upd_ship(sp, etus, np, bp, build);
00090 if (build && !player->simulation)
00091 nav_ship(sp);
00092 sea_money[sp->shp_own] += np->nat_money - start_money;
00093 if (!build || np->nat_money != start_money)
00094 k++;
00095 if (player->simulation)
00096 np->nat_money = start_money;
00097 }
00098 bp_disable_cachepath();
00099 bp_clear_cachepath();
00100
00101 if (opt_SAIL) {
00102 if (build && !player->simulation)
00103 sail_ship(natnum);
00104 }
00105 return k;
00106 }
00107
00108 static void
00109 upd_ship(struct shpstr *sp, int etus,
00110 struct natstr *np, struct bp *bp, int build)
00111
00112 {
00113 struct sctstr *sectp;
00114 struct mchrstr *mp;
00115 int pstage, ptime;
00116 int oil_gained;
00117 int max_oil;
00118 int max_food;
00119 struct pchrstr *product;
00120 unsigned char *resource;
00121 int dep;
00122 int n;
00123 int mult;
00124 int cost;
00125 int eff;
00126
00127 mp = &mchr[(int)sp->shp_type];
00128 if (build == 1) {
00129 if (!sp->shp_off && np->nat_money >= 0)
00130 shiprepair(sp, np, bp, etus);
00131 if (!player->simulation)
00132 sp->shp_off = 0;
00133 } else {
00134 mult = 1;
00135 if (np->nat_level[NAT_TLEV] < sp->shp_tech * 0.85)
00136 mult = 2;
00137 cost = -(mult * etus * MIN(0.0, money_ship * mp->m_cost));
00138 if (np->nat_money < cost && !player->simulation) {
00139 if ((eff = sp->shp_effic - etus / 5) < SHIP_MINEFF) {
00140 wu(0, sp->shp_own,
00141 "%s lost to lack of maintenance\n", prship(sp));
00142 makelost(EF_SHIP, sp->shp_own, sp->shp_uid,
00143 sp->shp_x, sp->shp_y);
00144 sp->shp_own = 0;
00145 return;
00146 }
00147 wu(0, sp->shp_own,
00148 "%s lost %d%% to lack of maintenance\n",
00149 prship(sp), sp->shp_effic - eff);
00150 sp->shp_effic = eff;
00151 } else {
00152 np->nat_money -= cost;
00153 }
00154
00155 if (!player->simulation) {
00156 sectp = getsectp(sp->shp_x, sp->shp_y);
00157
00158
00159 if (np->nat_money >= 0
00160 && (mp->m_flags & M_OIL) && sectp->sct_type == SCT_WATER) {
00161 product = &pchr[dchr[SCT_OIL].d_prd];
00162 oil_gained = roundavg(total_work(100, etus,
00163 sp->shp_item[I_CIVIL],
00164 sp->shp_item[I_MILIT],
00165 sp->shp_item[I_UW],
00166 ITEM_MAX)
00167 * sp->shp_effic / 100.0
00168 * sectp->sct_oil / 100.0
00169 * prod_eff(SCT_OIL, sp->shp_tech));
00170 max_oil = mp->m_item[I_OIL];
00171 if (sp->shp_item[I_OIL] + oil_gained > max_oil)
00172 oil_gained = max_oil - sp->shp_item[I_OIL];
00173 if (product->p_nrdep != 0 && oil_gained > 0) {
00174 resource = (unsigned char *)sectp + product->p_nrndx;
00175 if (*resource * 100 < product->p_nrdep * oil_gained)
00176 oil_gained = *resource * 100 / product->p_nrdep;
00177 dep = roundavg(oil_gained * product->p_nrdep / 100.0);
00178 if (CANT_HAPPEN(dep > *resource))
00179 dep = *resource;
00180 *resource -= dep;
00181 }
00182 sp->shp_item[I_OIL] += oil_gained;
00183 }
00184
00185 if (np->nat_money >= 0
00186 && (mp->m_flags & M_FOOD) && sectp->sct_type == SCT_WATER) {
00187 sp->shp_item[I_FOOD]
00188 += roundavg(total_work(100, etus,
00189 sp->shp_item[I_CIVIL],
00190 sp->shp_item[I_MILIT],
00191 sp->shp_item[I_UW],
00192 ITEM_MAX)
00193 * sp->shp_effic / 100.0
00194 * sectp->sct_fertil / 100.0
00195 * prod_eff(SCT_AGRI, sp->shp_tech));
00196 }
00197
00198 if ((n = feed_ship(sp, etus)) > 0) {
00199 wu(0, sp->shp_own, "%d starved on %s\n", n, prship(sp));
00200 if (n > 10)
00201 nreport(sp->shp_own, N_DIE_FAMINE, 0, 1);
00202 }
00203 max_food = mp->m_item[I_FOOD];
00204 if (sp->shp_item[I_FOOD] > max_food)
00205 sp->shp_item[I_FOOD] = max_food;
00206
00207
00208
00209
00210 pstage = sp->shp_pstage;
00211 ptime = sp->shp_ptime;
00212 if (pstage != PLG_HEALTHY) {
00213 n = plague_people(np, sp->shp_item, &pstage, &ptime, etus);
00214 switch (n) {
00215 case PLG_DYING:
00216 wu(0, sp->shp_own,
00217 "PLAGUE deaths reported on %s\n", prship(sp));
00218 nreport(sp->shp_own, N_DIE_PLAGUE, 0, 1);
00219 break;
00220 case PLG_INFECT:
00221 wu(0, sp->shp_own, "%s battling PLAGUE\n", prship(sp));
00222 break;
00223 case PLG_INCUBATE:
00224
00225 if (n == pstage) {
00226
00227 if (ptime <= etus) {
00228
00229 wu(0, sp->shp_own,
00230 "Outbreak of PLAGUE on %s!\n", prship(sp));
00231 nreport(sp->shp_own, N_OUT_PLAGUE, 0, 1);
00232 }
00233 } else {
00234
00235 wu(0, sp->shp_own,
00236 "%s battling PLAGUE\n", prship(sp));
00237 }
00238 break;
00239 case PLG_EXPOSED:
00240
00241 if (n != pstage) {
00242
00243 if (ptime <= etus) {
00244
00245 wu(0, sp->shp_own,
00246 "Outbreak of PLAGUE on %s!\n", prship(sp));
00247 nreport(sp->shp_own, N_OUT_PLAGUE, 0, 1);
00248 }
00249 }
00250 break;
00251 default:
00252 break;
00253 }
00254
00255 sp->shp_pstage = pstage;
00256 sp->shp_ptime = ptime;
00257 }
00258 pops[sp->shp_own] += sp->shp_item[I_CIVIL];
00259 }
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268 static void
00269 shiprepair(struct shpstr *ship, struct natstr *np, struct bp *bp, int etus)
00270 {
00271 int delta;
00272 struct sctstr *sp;
00273 struct mchrstr *mp;
00274 int build;
00275 int wf;
00276 int avail;
00277 int w_p_eff;
00278 int mult;
00279 int mvec[I_MAX + 1];
00280 int rel;
00281
00282 mp = &mchr[(int)ship->shp_type];
00283 sp = getsectp(ship->shp_x, ship->shp_y);
00284
00285 if ((sp->sct_own != ship->shp_own) && (sp->sct_own != 0)) {
00286 rel = getrel(getnatp(sp->sct_own), ship->shp_own);
00287
00288 if (rel < FRIENDLY)
00289 return;
00290 }
00291
00292 wf = 0;
00293
00294 if (ship->shp_glim > 0)
00295 wf = etus * ship->shp_item[I_MILIT] / 2;
00296 else
00297 wf = etus * (ship->shp_item[I_CIVIL] / 2 + ship->shp_item[I_MILIT] / 5);
00298
00299 if (sp->sct_type != SCT_HARBR) {
00300 wf /= 3;
00301 avail = wf;
00302 } else {
00303 if (!player->simulation)
00304 avail = wf + sp->sct_avail * 100;
00305 else
00306 avail = wf + bp_get_avail(bp, sp) * 100;
00307 }
00308
00309 w_p_eff = SHP_BLD_WORK(mp->m_lcm, mp->m_hcm);
00310
00311 if ((sp->sct_off) && (sp->sct_own == ship->shp_own))
00312 return;
00313
00314 mult = 1;
00315 if (np->nat_level[NAT_TLEV] < ship->shp_tech * 0.85)
00316 mult = 2;
00317
00318 if (ship->shp_effic == 100) {
00319
00320 return;
00321 }
00322
00323 delta = roundavg((double)avail / w_p_eff);
00324 if (delta <= 0)
00325 return;
00326 if (delta > (int)((float)etus * ship_grow_scale))
00327 delta = (int)((float)etus * ship_grow_scale);
00328 if (delta > 100 - ship->shp_effic)
00329 delta = 100 - ship->shp_effic;
00330
00331 memset(mvec, 0, sizeof(mvec));
00332 mvec[I_LCM] = mp->m_lcm;
00333 mvec[I_HCM] = mp->m_hcm;
00334 build = get_materials(sp, bp, mvec, delta);
00335
00336 if (sp->sct_type != SCT_HARBR)
00337 build = delta;
00338
00339 wf -= build * w_p_eff;
00340 if (wf < 0) {
00341
00342
00343
00344
00345 if (!player->simulation)
00346 avail = (sp->sct_avail * 100 + wf) / 100;
00347 else
00348 avail = (bp_get_avail(bp, sp) * 100 + wf) / 100;
00349 if (avail < 0)
00350 avail = 0;
00351 if (!player->simulation)
00352 sp->sct_avail = avail;
00353 else
00354 bp_put_avail(bp, sp, avail);
00355 }
00356 if (sp->sct_type != SCT_HARBR)
00357 if ((build + ship->shp_effic) > 80) {
00358 build = 80 - ship->shp_effic;
00359 if (build < 0)
00360 build = 0;
00361 }
00362
00363 np->nat_money -= mult * mp->m_cost * build / 100.0;
00364 if (!player->simulation)
00365 ship->shp_effic += (signed char)build;
00366 }
00367
00368
00369
00370
00371 static int
00372 feed_ship(struct shpstr *sp, int etus)
00373 {
00374 int needed, take;
00375 double give;
00376 struct nstr_item ni;
00377 struct lndstr *lp;
00378
00379 if (opt_NOFOOD)
00380 return 0;
00381
00382 needed = (int)ceil(food_needed(sp->shp_item, etus));
00383
00384
00385 if (needed > sp->shp_item[I_FOOD])
00386 sp->shp_item[I_FOOD] += supply_commod(sp->shp_own,
00387 sp->shp_x, sp->shp_y, I_FOOD,
00388 needed - sp->shp_item[I_FOOD]);
00389 if (needed > sp->shp_item[I_FOOD]) {
00390
00391 snxtitem_all(&ni, EF_LAND);
00392 while ((lp = nxtitemp(&ni)) && needed > sp->shp_item[I_FOOD]) {
00393 if (lp->lnd_ship != sp->shp_uid)
00394 continue;
00395 give = lp->lnd_item[I_FOOD] - food_needed(lp->lnd_item, etus);
00396 if (give < 1.0)
00397 continue;
00398 take = MIN((int)give, needed - sp->shp_item[I_FOOD]);
00399 sp->shp_item[I_FOOD] += take;
00400 lp->lnd_item[I_FOOD] -= take;
00401 }
00402 }
00403
00404 return feed_people(sp->shp_item, etus);
00405 }