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 #include <config.h>
00035
00036 #include <math.h>
00037 #include "file.h"
00038 #include "land.h"
00039 #include "nat.h"
00040 #include "optlist.h"
00041 #include "player.h"
00042 #include "prototypes.h"
00043 #include "sect.h"
00044 #include "ship.h"
00045
00046 static int get_minimum(struct lndstr *, i_type);
00047 static int s_commod(int, int, int, i_type, int, int);
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 void
00065 resupply_all(struct lndstr *lp)
00066 {
00067 if (!opt_NOFOOD)
00068 resupply_commod(lp, I_FOOD);
00069 resupply_commod(lp, I_SHELL);
00070 if (opt_FUEL)
00071 resupply_commod(lp, I_PETROL);
00072 }
00073
00074
00075
00076
00077
00078
00079 void
00080 resupply_commod(struct lndstr *lp, i_type type)
00081 {
00082 int amt;
00083 struct shpstr ship;
00084
00085
00086 amt = get_minimum(lp, type) - lp->lnd_item[type];
00087 if (amt > 0) {
00088 lp->lnd_item[type] += supply_commod(lp->lnd_own,
00089 lp->lnd_x, lp->lnd_y,
00090 type, amt);
00091 amt = get_minimum(lp, type) - lp->lnd_item[type];
00092 }
00093
00094 if (amt > 0) {
00095
00096 if (lp->lnd_ship >= 0) {
00097 getship(lp->lnd_ship, &ship);
00098
00099 if (amt > ship.shp_item[type])
00100 amt = ship.shp_item[type];
00101
00102 lp->lnd_item[type] += amt;
00103 ship.shp_item[type] -= amt;
00104 putship(lp->lnd_ship, &ship);
00105 }
00106 }
00107
00108 if (opt_FUEL && type == I_PETROL) {
00109 int fuel_needed = lp->lnd_fuelu
00110 * ((float)etu_per_update * land_mob_scale) / 10.0;
00111
00112 while ((lp->lnd_fuel < fuel_needed) && lp->lnd_item[I_PETROL]) {
00113 lp->lnd_fuel += 10;
00114 if (lp->lnd_fuel > lp->lnd_fuelc)
00115 lp->lnd_fuel = lp->lnd_fuelc;
00116 lp->lnd_item[I_PETROL]--;
00117 }
00118 }
00119 }
00120
00121
00122
00123
00124 int
00125 supply_commod(int own, int x, int y, i_type type, int total_wanted)
00126 {
00127 if (total_wanted < 0)
00128 return 0;
00129 return s_commod(own, x, y, type, total_wanted, !player->simulation);
00130 }
00131
00132
00133
00134
00135 int
00136 try_supply_commod(int own, int x, int y, i_type type, int total_wanted)
00137 {
00138 if (total_wanted < 0)
00139 return 0;
00140
00141 return s_commod(own, x, y, type, total_wanted, 0);
00142 }
00143
00144
00145 static int
00146 s_commod(int own, int x, int y, i_type type, int total_wanted,
00147 int actually_doit)
00148 {
00149 int wanted = total_wanted;
00150 int gotten = 0, lookrange;
00151 struct sctstr sect, dest;
00152 struct nstr_sect ns;
00153 struct nstr_item ni;
00154 struct lchrstr *lcp;
00155 struct shpstr ship;
00156 struct lndstr land;
00157
00158 int minimum = (type == I_MILIT ? 1 : 0);
00159 int can_move;
00160 double move_cost, weight, mobcost;
00161 int packing;
00162 struct dchrstr *dp;
00163 struct ichrstr *ip;
00164 char buf[1024];
00165
00166
00167 getsect(x, y, &dest);
00168 getsect(x, y, §);
00169 if (sect.sct_own == own) {
00170 if (sect.sct_item[type] - wanted >= minimum) {
00171 sect.sct_item[type] -= wanted;
00172 if (actually_doit)
00173 putsect(§);
00174 return total_wanted;
00175 } else if (sect.sct_item[type] - minimum > 0) {
00176 gotten += sect.sct_item[type] - minimum;
00177 wanted -= sect.sct_item[type] - minimum;
00178 sect.sct_item[type] = minimum;
00179 if (actually_doit)
00180 putsect(§);
00181 }
00182 }
00183
00184 lookrange = tfact(own, 10.0);
00185 snxtsct_dist(&ns, x, y, lookrange);
00186 while (nxtsct(&ns, §) && wanted) {
00187 if (sect.sct_own != own)
00188 continue;
00189 if ((sect.sct_type != SCT_WAREH) &&
00190 (sect.sct_type != SCT_HEADQ) && (sect.sct_type != SCT_HARBR))
00191 continue;
00192 if ((sect.sct_type == SCT_HEADQ) &&
00193 (sect.sct_dist_x == sect.sct_x) &&
00194 (sect.sct_dist_y == sect.sct_y))
00195 continue;
00196 if (sect.sct_effic < 60)
00197 continue;
00198 if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
00199 continue;
00200 if (!opt_NOFOOD && type == I_FOOD)
00201 minimum = 1 + (int)ceil(food_needed(sect.sct_item,
00202 etu_per_update));
00203 if (sect.sct_item[type] <= minimum) {
00204
00205 continue;
00206 }
00207 ip = &ichr[type];
00208 dp = &dchr[sect.sct_type];
00209 packing = ip->i_pkg[dp->d_pkg];
00210 if (packing > 1 && sect.sct_effic < 60)
00211 packing = 1;
00212 weight = (double)ip->i_lbs / packing;
00213 mobcost = move_cost * weight;
00214 if (mobcost > 0)
00215 can_move = (double)sect.sct_mobil / mobcost;
00216 else
00217 can_move = sect.sct_item[type] - minimum;
00218 if (can_move > sect.sct_item[type] - minimum)
00219 can_move = sect.sct_item[type] - minimum;
00220
00221 if (can_move >= wanted) {
00222 int n;
00223
00224 sect.sct_item[type] -= wanted;
00225
00226
00227 n = roundavg(total_wanted * weight * move_cost);
00228 if (n < 0)
00229 n = 0;
00230 if (n > sect.sct_mobil)
00231 n = sect.sct_mobil;
00232 sect.sct_mobil -= n;
00233
00234 if (actually_doit)
00235 putsect(§);
00236
00237 return total_wanted;
00238 } else if (can_move > 0) {
00239 int n;
00240 gotten += can_move;
00241 wanted -= can_move;
00242 sect.sct_item[type] -= can_move;
00243
00244
00245 n = roundavg(can_move * weight * move_cost);
00246 if (n < 0)
00247 n = 0;
00248 if (n > sect.sct_mobil)
00249 n = sect.sct_mobil;
00250 sect.sct_mobil -= n;
00251
00252 if (actually_doit)
00253 putsect(§);
00254 }
00255 }
00256
00257
00258 snxtitem_dist(&ni, EF_SHIP, x, y, lookrange);
00259
00260 while (nxtitem(&ni, &ship) && wanted) {
00261 if (ship.shp_own != own)
00262 continue;
00263
00264 if (!(mchr[(int)ship.shp_type].m_flags & M_SUPPLY))
00265 continue;
00266 getsect(ship.shp_x, ship.shp_y, §);
00267 if (sect.sct_type != SCT_HARBR)
00268 continue;
00269 if (sect.sct_effic < 2)
00270 continue;
00271 if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
00272 continue;
00273 if (!opt_NOFOOD && type == I_FOOD)
00274 minimum = 1 + (int)ceil(food_needed(ship.shp_item,
00275 etu_per_update));
00276 if (ship.shp_item[type] <= minimum) {
00277
00278 continue;
00279 }
00280 ip = &ichr[type];
00281 dp = &dchr[sect.sct_type];
00282 packing = ip->i_pkg[dp->d_pkg];
00283 if (packing > 1 && sect.sct_effic < 60)
00284 packing = 1;
00285 weight = (double)ip->i_lbs / packing;
00286 mobcost = move_cost * weight;
00287 if (mobcost > 0)
00288 can_move = (double)sect.sct_mobil / mobcost;
00289 else
00290 can_move = ship.shp_item[type] - minimum;
00291 if (can_move > ship.shp_item[type] - minimum)
00292 can_move = ship.shp_item[type] - minimum;
00293 if (can_move >= wanted) {
00294 int n;
00295 ship.shp_item[type] -= wanted;
00296
00297 n = roundavg(wanted * weight * move_cost);
00298 if (n < 0)
00299 n = 0;
00300 if (n > sect.sct_mobil)
00301 n = sect.sct_mobil;
00302 sect.sct_mobil -= n;
00303 if (actually_doit) {
00304 putship(ship.shp_uid, &ship);
00305 putsect(§);
00306 }
00307 return total_wanted;
00308 } else if (can_move > 0) {
00309 int n;
00310 gotten += can_move;
00311 wanted -= can_move;
00312 ship.shp_item[type] -= can_move;
00313
00314 n = roundavg(can_move * weight * move_cost);
00315 if (n < 0)
00316 n = 0;
00317 if (n > sect.sct_mobil)
00318 n = sect.sct_mobil;
00319 sect.sct_mobil -= n;
00320
00321 if (actually_doit) {
00322 putship(ship.shp_uid, &ship);
00323 putsect(§);
00324 }
00325 }
00326 }
00327
00328
00329 snxtitem_dist(&ni, EF_LAND, x, y, lookrange);
00330
00331 while (nxtitem(&ni, &land) && wanted) {
00332 int min;
00333
00334 if (land.lnd_own != own)
00335 continue;
00336
00337 lcp = &lchr[(int)land.lnd_type];
00338 if (!(lcp->l_flags & L_SUPPLY))
00339 continue;
00340
00341 if (land.lnd_item[type] <= get_minimum(&land, type))
00342 continue;
00343
00344 getsect(land.lnd_x, land.lnd_y, §);
00345 if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
00346 continue;
00347
00348 if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR))
00349 continue;
00350
00351 if ((land.lnd_ship >= 0) && (sect.sct_effic < 2))
00352 continue;
00353
00354 if (land.lnd_item[type] - wanted < get_minimum(&land, type)) {
00355 struct lndstr save;
00356
00357
00358
00359
00360
00361 save = land;
00362 land.lnd_item[type] = 0;
00363 putland(land.lnd_uid, &land);
00364
00365 land.lnd_item[type] =
00366 save.lnd_item[type] + s_commod(own, land.lnd_x, land.lnd_y,
00367 type, wanted, actually_doit);
00368 if (actually_doit)
00369 putland(land.lnd_uid, &land);
00370 else
00371 putland(save.lnd_uid, &save);
00372 }
00373
00374 min = get_minimum(&land, type);
00375 ip = &ichr[type];
00376 weight = ip->i_lbs;
00377 mobcost = move_cost * weight;
00378 if (mobcost > 0)
00379 can_move = (double)land.lnd_mobil / mobcost;
00380 else
00381 can_move = land.lnd_item[type] - min;
00382 if (can_move > land.lnd_item[type] - min)
00383 can_move = land.lnd_item[type] - min;
00384
00385 if (can_move >= wanted) {
00386 land.lnd_item[type] -= wanted;
00387
00388
00389 resupply_commod(&land, type);
00390
00391 land.lnd_mobil -= roundavg(wanted * weight * move_cost);
00392
00393 if (actually_doit)
00394 putland(land.lnd_uid, &land);
00395 return total_wanted;
00396 } else if (can_move > 0) {
00397 gotten += can_move;
00398 wanted -= can_move;
00399 land.lnd_item[type] -= can_move;
00400
00401 land.lnd_mobil -= roundavg(can_move * weight * move_cost);
00402
00403 if (actually_doit)
00404 putland(land.lnd_uid, &land);
00405 }
00406 }
00407
00408
00409
00410 return gotten;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420 static int
00421 get_minimum(struct lndstr *lp, i_type type)
00422 {
00423 struct lchrstr *lcp;
00424 int max, want = 0;
00425
00426 lcp = &lchr[(int)lp->lnd_type];
00427 max = lcp->l_item[type];
00428
00429 switch (type) {
00430 case I_FOOD:
00431 if (opt_NOFOOD)
00432 return 0;
00433 want = (int)ceil(food_needed(lp->lnd_item, etu_per_update));
00434 break;
00435 case I_SHELL:
00436 want = lp->lnd_ammo;
00437 break;
00438
00439
00440
00441
00442
00443 case I_PETROL:
00444 if (opt_FUEL == 0)
00445 return 0;
00446 want = lp->lnd_fuelu * ((float)etu_per_update * land_mob_scale)
00447 / 10.0;
00448 want -= lp->lnd_fuel;
00449 if (want > 0) {
00450 want = want / 10;
00451 if (want == 0)
00452 want++;
00453 }
00454
00455 max = want;
00456 break;
00457 default:
00458 return 0;
00459 }
00460
00461 if (want > max)
00462 want = max;
00463
00464 return want;
00465 }
00466
00467 int
00468 has_supply(struct lndstr *lp)
00469 {
00470 int shells_needed, shells, keepshells;
00471 int food, food_needed, keepfood;
00472 int fuel_needed, fuel, petrol_needed, petrol, keeppetrol;
00473
00474 if (!opt_NOFOOD) {
00475 food_needed = get_minimum(lp, I_FOOD);
00476 food = keepfood = lp->lnd_item[I_FOOD];
00477 if (food < food_needed) {
00478 lp->lnd_item[I_FOOD] = 0;
00479 putland(lp->lnd_uid, lp);
00480 food += try_supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
00481 I_FOOD, (food_needed - food));
00482 lp->lnd_item[I_FOOD] = keepfood;
00483 putland(lp->lnd_uid, lp);
00484 }
00485 if (food < food_needed)
00486 return 0;
00487
00488 }
00489
00490 shells_needed = lp->lnd_ammo;
00491 shells = keepshells = lp->lnd_item[I_SHELL];
00492 if (shells < shells_needed) {
00493 lp->lnd_item[I_SHELL] = 0;
00494 putland(lp->lnd_uid, lp);
00495 shells += try_supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
00496 I_SHELL, (shells_needed - shells));
00497 lp->lnd_item[I_SHELL] = keepshells;
00498 putland(lp->lnd_uid, lp);
00499 }
00500
00501 if (shells < shells_needed)
00502 return 0;
00503
00504 if (opt_FUEL) {
00505 fuel_needed = lp->lnd_fuelu;
00506 fuel = lp->lnd_fuel;
00507 if (fuel < fuel_needed) {
00508 petrol_needed =
00509 ldround((fuel_needed - fuel) / 10.0, 1);
00510 petrol = keeppetrol = lp->lnd_item[I_PETROL];
00511 if (petrol < petrol_needed) {
00512 lp->lnd_item[I_PETROL] = 0;
00513 putland(lp->lnd_uid, lp);
00514 petrol += try_supply_commod(lp->lnd_own,
00515 lp->lnd_x, lp->lnd_y,
00516 I_PETROL,
00517 (petrol_needed - petrol));
00518 lp->lnd_item[I_PETROL] = keeppetrol;
00519 putland(lp->lnd_uid, lp);
00520 }
00521 fuel += petrol * 10;
00522 }
00523
00524 if (fuel < fuel_needed)
00525 return 0;
00526 }
00527
00528 return 1;
00529 }
00530
00531 int
00532 use_supply(struct lndstr *lp)
00533 {
00534 int shells_needed, shells, food, food_needed;
00535 int fuel_needed, fuel, petrol_needed, petrol;
00536
00537 shells_needed = lp->lnd_ammo;
00538 shells = lp->lnd_item[I_SHELL];
00539 if (shells < shells_needed) {
00540 lp->lnd_item[I_SHELL] = 0;
00541 putland(lp->lnd_uid, lp);
00542 shells += supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
00543 I_SHELL, shells_needed - shells);
00544 lp->lnd_item[I_SHELL] = shells;
00545 }
00546
00547 lp->lnd_item[I_SHELL] = MAX(lp->lnd_item[I_SHELL] - shells_needed, 0);
00548
00549 if (lp->lnd_frg)
00550 goto done;
00551
00552 food_needed = get_minimum(lp, I_FOOD);
00553 food = lp->lnd_item[I_SHELL];
00554
00555 if (food < food_needed) {
00556 lp->lnd_item[I_FOOD] = 0;
00557 putland(lp->lnd_uid, lp);
00558 food += supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
00559 I_FOOD, food_needed - food);
00560 lp->lnd_item[I_FOOD] = food;
00561 }
00562
00563 lp->lnd_item[I_FOOD] = MAX(lp->lnd_item[I_FOOD] - food_needed, 0);
00564
00565 if (opt_FUEL) {
00566 fuel_needed = lp->lnd_fuelu;
00567 fuel = lp->lnd_fuel;
00568
00569 petrol = petrol_needed = 0;
00570
00571 if (fuel < fuel_needed) {
00572 petrol_needed =
00573 ldround((fuel_needed - fuel) / 10.0, 1);
00574 petrol = lp->lnd_item[I_PETROL];
00575 }
00576
00577 if (petrol < petrol_needed) {
00578 lp->lnd_item[I_PETROL] = 0;
00579 putland(lp->lnd_uid, lp);
00580 petrol += supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
00581 I_PETROL, petrol_needed - petrol);
00582 lp->lnd_item[I_PETROL] = petrol;
00583 }
00584
00585 if (petrol_needed) {
00586 if (petrol >= petrol_needed) {
00587 lp->lnd_item[I_PETROL]
00588 = MAX(lp->lnd_item[I_PETROL] - petrol_needed, 0);
00589 lp->lnd_fuel += petrol_needed * 10;
00590 } else {
00591 lp->lnd_fuel += lp->lnd_item[I_PETROL] * 10;
00592 lp->lnd_item[I_PETROL] = 0;
00593 }
00594 }
00595
00596 lp->lnd_fuel = MAX(lp->lnd_fuel - fuel_needed, 0);
00597 }
00598
00599 done:
00600 putland(lp->lnd_uid, lp);
00601 return 1;
00602 }