2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * supply.c: Supply subroutines
30 * Known contributors to this file:
51 #include "prototypes.h"
54 * We want to get enough guns to be maxed out, enough shells to
55 * fire once, one update's worth of food, enough fuel for
58 * Firts, try to forage in the sector
59 * Second look for a warehouse or headquarters to leech
60 * Third, look for a ship we own in a harbor
61 * Fourth, look for supplies in a supply unit we own
62 * (one good reason to do this last is that the supply
63 * unit will then call resupply, taking more time)
65 * May want to put code to resupply with SAMs here, later --ts
70 resupply_all(struct lndstr *lp)
73 resupply_commod(lp,I_FOOD);
74 resupply_commod(lp,I_SHELL);
76 resupply_commod(lp,I_PETROL);
80 * If the unit has less than it's minimum level of a
81 * certain commodity, fill it, to the best of our abilities.
85 resupply_commod(struct lndstr *lp, int type)
93 lcp = &lchr[(int)lp->lnd_type];
95 getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
96 /* Ok, do we now have enough? */
97 if (vec[type] < get_minimum(lp,type)) {
98 vec[type] += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,type,
99 get_minimum(lp,type)-vec[type]);
100 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
102 /* Now, check again to see if we have enough. */
103 if (vec[type] < get_minimum(lp,type)) {
104 /* Nope. How much do we need? */
105 amt = (get_minimum(lp, type) - vec[type]);
106 /* Are we on a ship? if so, try to get it from the ship first. */
107 if (lp->lnd_ship >= 0) {
108 getship(lp->lnd_ship, &ship);
109 getvec(VT_ITEM, svec, (s_char *)&ship, EF_SHIP);
110 /* Now, determine how much we can get */
111 amt = (amt < svec[type]) ? amt : svec[type];
112 /* Now, add and subtract */
115 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
116 putvec(VT_ITEM, svec, (s_char *)&ship, EF_SHIP);
117 putship(lp->lnd_ship, &ship);
121 if (opt_FUEL && type == I_PETROL) {
122 extern float land_mob_scale;
123 extern int etu_per_update;
124 int fuel_needed = (lp->lnd_fuelu * (((float)etu_per_update
125 * land_mob_scale))/10.0);
127 while((lp->lnd_fuel < fuel_needed) && vec[I_PETROL]){
129 if (lp->lnd_fuel > lp->lnd_fuelc)
130 lp->lnd_fuel = lp->lnd_fuelc;
132 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
138 * Actually get the commod
141 supply_commod(int own, int x, int y, int type, int total_wanted)
143 if (total_wanted < 0)
145 return s_commod(own, x, y, type,total_wanted,!player->simulation);
149 * Just return the number you COULD get, without doing it
152 try_supply_commod(int own, int x, int y, int type, int total_wanted)
154 if (total_wanted < 0)
157 return s_commod(own, x, y, type,total_wanted,0);
160 /* Get supplies of a certain type */
162 s_commod(int own, int x, int y, int type, int total_wanted, int actually_doit)
164 int wanted=total_wanted;
165 int gotten=0, lookrange;
166 struct sctstr sect, dest;
173 /* leave at least 1 military in sectors/ships */
174 int minimum=(type == I_MILIT ? 1 : 0);
176 double move_cost, weight, mobcost;
178 extern double eatrate;
179 extern int etu_per_update;
184 /* try to get it from sector we're in */
187 if (sect.sct_own == own){
188 getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR);
189 if ((vec[type]-minimum) >= wanted){
192 putvec(VT_ITEM,vec,(s_char *)§,EF_SECTOR);
196 }else if ((vec[type]-minimum) > 0){
197 gotten += (vec[type]-minimum);
198 wanted -= (vec[type]-minimum);
201 putvec(VT_ITEM,vec,(s_char *)§,EF_SECTOR);
206 /* look for a headquarters or warehouse */
207 lookrange = tfact(own,(double)10.0);
208 snxtsct_dist(&ns, x, y, lookrange);
209 while (nxtsct(&ns, §) && wanted){
210 if (sect.sct_own != own)
212 if ((sect.sct_type != SCT_WAREH) &&
213 (sect.sct_type != SCT_HEADQ) &&
214 (sect.sct_type != SCT_HARBR))
216 if ((sect.sct_type == SCT_HEADQ) &&
217 (sect.sct_dist_x == sect.sct_x) &&
218 (sect.sct_dist_y == sect.sct_y))
220 if (sect.sct_effic < 60)
222 if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0)
224 getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR);
225 if (!opt_NOFOOD && type == I_FOOD) {
226 minimum=(((double)etu_per_update * eatrate) *
227 (double)(vec[I_CIVIL]+vec[I_MILIT]+vec[I_UW]))
230 if (vec[type] <= minimum) {
231 /* Don't bother... */
235 dp = &dchr[sect.sct_type];
236 packing = ip->i_pkg[dp->d_pkg];
237 if (packing > 1 && sect.sct_effic < 60)
239 weight = ((double)ip->i_lbs / (double)packing);
240 mobcost = move_cost * weight;
242 can_move = ((double)sect.sct_mobil / mobcost);
244 can_move = vec[type]-minimum;
245 if (can_move > (vec[type]-minimum))
246 can_move = (vec[type]-minimum);
248 if (can_move >= wanted){
253 /* take off mobility for delivering sect */
254 n = roundavg(total_wanted*weight*move_cost);
257 if (n > sect.sct_mobil)
259 sect.sct_mobil -= (u_char)n;
262 putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR);
267 }else if (can_move > 0){
271 vec[type] -= can_move;
273 /* take off mobility for delivering sect */
274 n = roundavg(can_move*weight*move_cost);
277 if (n > sect.sct_mobil)
279 sect.sct_mobil -= (u_char)n;
282 putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR);
288 /* look for an owned ship in a harbor */
289 snxtitem_dist(&ni, EF_SHIP, x, y, lookrange);
291 while (nxtitem(&ni, (s_char *)&ship) && wanted){
292 if (ship.shp_own != own)
295 if (!(mchr[(int)ship.shp_type].m_flags & M_SUPPLY))
297 getsect(ship.shp_x,ship.shp_y,§);
298 if (sect.sct_type != SCT_HARBR)
300 if (sect.sct_effic < 2)
302 if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0)
304 getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP);
305 if (!opt_NOFOOD && type == I_FOOD)
306 minimum=(((double)etu_per_update * eatrate) *
307 (double)(vec[I_CIVIL]+vec[I_MILIT]+vec[I_UW]))
309 if (vec[type] <= minimum) {
310 /* Don't bother... */
314 dp = &dchr[sect.sct_type];
315 packing = ip->i_pkg[dp->d_pkg];
316 if (packing > 1 && sect.sct_effic < 60)
318 weight = ((double)ip->i_lbs / (double)packing);
319 mobcost = move_cost * weight;
321 can_move = ((double)sect.sct_mobil / mobcost);
323 can_move = vec[type]-minimum;
324 if (can_move > (vec[type]-minimum))
325 can_move = (vec[type]-minimum);
326 if (can_move >= wanted){
330 n = roundavg(wanted*weight*move_cost);
333 if (n > sect.sct_mobil)
335 sect.sct_mobil -= (u_char)n;
337 putvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP);
338 putship(ship.shp_uid,&ship);
342 }else if (can_move > 0){
346 vec[type] -= can_move;
348 n = roundavg(can_move*weight*move_cost);
351 if (n > sect.sct_mobil)
353 sect.sct_mobil -= (u_char)n;
356 putvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP);
357 putship(ship.shp_uid,&ship);
363 /* look for an owned supply unit */
364 snxtitem_dist(&ni, EF_LAND, x, y, lookrange);
366 while (nxtitem(&ni, (s_char *)&land) && wanted){
369 if (land.lnd_own != own)
372 lcp = &lchr[(int)land.lnd_type];
373 if (!(lcp->l_flags & L_SUPPLY))
376 getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
377 if (vec[type] <= get_minimum(&land,type))
380 getsect(land.lnd_x,land.lnd_y,§);
381 if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0)
384 if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR))
387 if ((land.lnd_ship >= 0) && (sect.sct_effic < 2))
390 if ((vec[type]-wanted) < get_minimum(&land,type)){
394 bcopy((s_char *)&land,(s_char *)&l2,sizeof(struct lndstr));
397 putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
399 putland(land.lnd_uid,&land);
400 hold += s_commod(own,land.lnd_x,land.lnd_y,type,wanted, actually_doit);
402 putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
403 putland(land.lnd_uid,&land);
405 putland(l2.lnd_uid,&l2);
408 getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
410 weight = ((double)ip->i_lbs);
411 mobcost = move_cost * weight;
413 can_move = ((double)land.lnd_mobil / mobcost);
415 can_move = vec[type]-min;
416 min = get_minimum(&land,type);
417 if (can_move > (vec[type]-min))
418 can_move = (vec[type]-min);
420 if (can_move >= wanted){
423 /* resupply the supply unit */
424 resupply_commod(&land, type);
426 land.lnd_mobil -= roundavg(wanted*weight*move_cost);
429 putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
430 putland(land.lnd_uid,&land);
433 }else if (can_move > 0){
436 vec[type] -= can_move;
438 land.lnd_mobil -= roundavg(can_move*weight*move_cost);
441 putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND);
442 putland(land.lnd_uid,&land);
447 /* We've done the best we could */
448 /* return the number gotten */
457 register struct ichrstr *ip;
460 for (ip = &ichr[1]; ip->i_mnem != 0; ip++) {
461 if (t == ip->i_vtype)
468 at_minimum(struct lndstr *lp, int type)
472 getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
473 if (vec[type] <= get_minimum(lp,type))
480 * We want to get enough shells to fire once,
481 * one update's worth of food, enough fuel for
486 get_minimum(struct lndstr *lp, int type)
490 extern double eatrate;
491 extern int etu_per_update;
492 extern float land_mob_scale;
494 lcp = &lchr[(int)lp->lnd_type];
495 max = vl_find(V_ITEM(type), lcp->l_vtype, lcp->l_vamt, (int) lcp->l_nv);
500 return 0; /* no food reqd, get out */
501 want = (((double)etu_per_update * eatrate) *
502 (double)total_mil(lp))+1;
509 * return the amount of pet we'd need to get to
510 * enough fuel for 1 update
514 if (opt_FUEL == 0) return 0;
515 want = (lp->lnd_fuelu * (((float)etu_per_update *
516 land_mob_scale))/10.0);
517 want -= lp->lnd_fuel;
520 d = (double)want/10.0;
538 has_supply(struct lndstr *lp)
541 int vec[I_MAX+1], shells_needed, shells, keepshells;
542 int food, food_needed, keepfood;
543 int fuel_needed, fuel, petrol_needed, petrol, keeppetrol;
545 lcp = &lchr[(int)lp->lnd_type];
546 getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
549 food_needed = get_minimum(lp,I_FOOD);
550 food = keepfood = vec[I_FOOD];
551 if (food < food_needed){
553 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
554 food += try_supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,
555 I_FOOD,(food_needed-food));
556 vec[I_FOOD]=keepfood;
557 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
559 if (food < food_needed)
564 shells_needed = lp->lnd_ammo;
565 shells = keepshells = vec[I_SHELL];
566 if (shells < shells_needed){
568 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
569 shells += try_supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,
570 I_SHELL,(shells_needed-shells));
571 vec[I_SHELL]=keepshells;
572 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
575 if (shells < shells_needed)
579 fuel_needed = lp->lnd_fuelu;
583 petrol=petrol_needed = 0;
585 if (fuel < fuel_needed){
587 ldround(((double)(fuel_needed-fuel)/10.0),1);
588 petrol = keeppetrol = vec[I_PETROL];
591 if (petrol < petrol_needed){
593 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
594 petrol += try_supply_commod(lp->lnd_own,
596 I_PETROL,(petrol_needed-petrol));
597 vec[I_PETROL]=keeppetrol;
598 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
602 if (fuel < fuel_needed)
610 use_supply(struct lndstr *lp)
613 int vec[I_MAX+1], shells_needed, shells, food, food_needed;
614 int fuel_needed, fuel, petrol_needed, petrol;
616 lcp = &lchr[(int)lp->lnd_type];
617 getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
619 shells_needed = lp->lnd_ammo;
620 shells = vec[I_SHELL];
621 if (shells < shells_needed){
623 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
624 shells += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,I_SHELL,
625 (shells_needed-shells));
626 vec[I_SHELL] = shells;
629 vec[I_SHELL] = max(vec[I_SHELL] - shells_needed, 0);
631 if (lp->lnd_frg) /* artillery */
634 food_needed = get_minimum(lp,I_FOOD);
637 if (food < food_needed){
639 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
640 food += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,I_FOOD,
645 vec[I_FOOD] = max(vec[I_FOOD]-food_needed,0);
648 fuel_needed = lp->lnd_fuelu;
651 petrol=petrol_needed = 0;
653 if (fuel < fuel_needed){
655 ldround(((double)(fuel_needed-fuel)/10.0),1);
656 petrol = vec[I_PETROL];
659 if (petrol < petrol_needed){
661 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
662 petrol += supply_commod(lp->lnd_own,
664 I_PETROL,(petrol_needed-petrol));
665 vec[I_PETROL]=petrol;
669 if (petrol>=petrol_needed){
671 max(vec[I_PETROL]-petrol_needed,0);
672 lp->lnd_fuel += petrol_needed * 10;
675 lp->lnd_fuel += vec[I_PETROL]*10;
680 lp->lnd_fuel = max(lp->lnd_fuel - fuel_needed, 0);
684 putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND);
685 putland(lp->lnd_uid,lp);