]> git.pond.sub.org Git - empserver/blob - src/lib/update/distribute.c
Sectors need space for items, deliveries and distribution thresholds.
[empserver] / src / lib / update / distribute.c
1 /*
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
5  *
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.
10  *
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.
15  *
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
19  *
20  *  ---
21  *
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.
25  *
26  *  ---
27  *
28  *  distribute.c: Do distribution to sectors
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  *     Steve McClure, 1998
33  */
34
35 #include <stdlib.h>
36 #include "misc.h"
37 #include "var.h"
38 #include "nat.h"
39 #include "sect.h"
40 #include "item.h"
41 #include "xy.h"
42 #include "path.h"
43 #include "file.h"
44 #include "distribute.h"
45 #include "update.h"
46 #include "subs.h"
47 #include "common.h"
48 #include "prototypes.h"
49
50 int
51 dodistribute(struct sctstr *sp, int imex, s_char *path, double dist_i_cost,
52              double dist_e_cost)
53           /* import or export? */
54 {
55     struct ichrstr *ip;
56     struct sctstr *dist;
57     int amt;
58     int thresh;
59     int amt_dist;
60     int amt_sect;
61     int packing;
62     float imcost;
63     float excost;
64     int dist_packing;
65     int diff;
66     int item;
67     int remote[I_MAX + 1];
68     int local[I_MAX + 1];
69     int changed;
70     int rplague;
71     int lplague;
72
73     getvec(VT_ITEM, local, (s_char *)sp, EF_SECTOR);
74     if ((sp->sct_dist_x == sp->sct_x) && (sp->sct_dist_y == sp->sct_y))
75         return 0;
76
77     if (path == (s_char *)0) {
78         if (sp->sct_own != 0) {
79             if (imex == EXPORT) /* only want this once */
80                 wu(0, sp->sct_own, "No path to dist sector for %s\n",
81                    ownxy(sp));
82         }
83         return 0;
84     }
85
86     dist = getsectp(sp->sct_dist_x, sp->sct_dist_y);
87     if (dist->sct_effic >= 60)
88         dist_packing = dchr[dist->sct_type].d_pkg;
89     else
90         dist_packing = NPKG;    /* No packing */
91
92     if (sp->sct_effic >= 60)
93         packing = dchr[sp->sct_type].d_pkg;
94     else
95         packing = NPKG;         /* No packing */
96
97     if ((dist->sct_effic >= 60) && dchr[dist->sct_type].d_pkg == WPKG)
98         packing = dchr[dist->sct_type].d_pkg;
99
100     getvec(VT_ITEM, remote, (s_char *)dist, EF_SECTOR);
101     lplague = rplague = changed = 0;
102     for (item = 1; item < I_MAX + 1; item++) {
103         if (sp->sct_dist[item] == 0)
104             continue;
105         ip = &ichr[item];
106         thresh = sp->sct_dist[item];
107         /*
108          * calculate costs for importing and exporting.
109          * the div 10.0 is because delivering straight through
110          * to the dist sect is cheaper than stopping at each
111          * sector along the way (processor-timewise)
112          */
113         excost = (dist_e_cost / ip->i_pkg[packing] * ip->i_lbs) / 10.0;
114         imcost =
115             (dist_i_cost / ip->i_pkg[dist_packing] * ip->i_lbs) / 10.0;
116         amt_sect = local[item];
117         amt_dist = remote[item];
118         diff = amt_sect - thresh;
119         if (item == I_CIVIL)
120             if (sp->sct_own != sp->sct_oldown)
121                 continue;
122         if (item == I_CIVIL)
123             if (dist->sct_own != dist->sct_oldown)
124                 continue;
125         if (diff < 0) {
126             if (imex != IMPORT)
127                 continue;
128
129             if (!military_control(dist))
130                 continue;
131
132             diff = -diff;
133             /*
134              * import.
135              * don't import if no mobility.
136              * check to make sure have enough mobility in the
137              * dist sector to import what we need.
138              */
139             if (dist->sct_mobil <= 0) {
140                 /*logerror("  dist mobil < 0"); */
141                 continue;
142             }
143             amt = diff;
144             if (item == I_CIVIL)
145                 amt_dist--;     /* Don't send your last civ */
146
147             if (amt_dist < amt) {
148                 amt = amt_dist;
149                 if (amt_dist == 0)
150                     continue;
151             }
152             if (dist->sct_mobil < imcost * amt)
153                 amt = dist->sct_mobil / imcost;
154
155             lplague++;
156             /* XXX replace with vector assign and putvec() */
157             remote[item] -= amt;
158             changed++;
159             dist->sct_mobil -= (int)(imcost * amt);
160             local[item] += amt;
161         } else {
162             if (imex != EXPORT)
163                 continue;
164             if (!military_control(sp))
165                 continue;
166             if ((item == I_CIVIL) && (sp->sct_work < 100))
167                 continue;
168             if ((item == I_CIVIL) && (sp->sct_own != sp->sct_oldown))
169                 continue;
170             /*
171              * export.
172              * don't export if no mobility. check to make sure we
173              * have mobility enough to do the right thing.
174              * also make sure that there's enough space in the
175              * target sector to hold the required amt.
176              */
177             if (sp->sct_mobil <= 0) {
178                 /*logerror("  sp mob is zero"); */
179                 continue;
180             }
181             amt = diff;
182             if (amt > amt_sect)
183                 amt = amt_sect;
184             if (sp->sct_mobil < excost * amt)
185                 amt = sp->sct_mobil / excost;
186             if (amt + amt_dist > 9999)
187                 amt = 9999 - amt_dist;
188             if (amt == 0)
189                 continue;
190             /* XXX replace with vector assign and putvec() */
191
192             rplague++;
193             local[item] -= amt;
194             changed++;
195             sp->sct_mobil -= (int)(excost * amt);
196             remote[item] += amt;
197         }
198     }
199     putvec(VT_ITEM, remote, (s_char *)dist, EF_SECTOR);
200     putvec(VT_ITEM, local, (s_char *)sp, EF_SECTOR);
201
202     if (lplague) {
203         lplague = dist->sct_pstage;
204         if (lplague == PLG_INFECT && sp->sct_pstage == PLG_HEALTHY)
205             sp->sct_pstage = PLG_EXPOSED;
206     }
207
208     if (rplague) {
209         rplague = sp->sct_pstage;
210         if (rplague == PLG_INFECT && dist->sct_pstage == PLG_HEALTHY)
211             dist->sct_pstage = PLG_EXPOSED;
212     }
213
214     return changed;
215 }