]> git.pond.sub.org Git - empserver/blob - src/lib/common/vlist.c
Indented with src/scripts/indent-emp.
[empserver] / src / lib / common / vlist.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  *  vlist.c: manage variable lists
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1989
32  */
33
34 #include "misc.h"
35 #include "var.h"
36 #include "sect.h"
37 #include "ship.h"
38 #include "land.h"
39 #include "product.h"
40 #include "optlist.h"
41 #include "common.h"
42 #include "gen.h"
43
44 static int freeslot(u_char *vec, register u_char *end);
45
46 int
47 vl_find(register int vtype, u_char *typevec, u_short *amtvec, int nelem)
48 {
49     register u_char *vp;
50     register u_short *ap;
51     register u_char *endp;
52
53     if (vtype < 0 || vtype > V_MAX)
54         return -1;
55     vp = typevec;
56     ap = amtvec;
57     endp = vp + nelem;
58     for (; vp < endp; vp++, ap++) {
59         if (*vp == vtype)
60             return (int)*ap;
61     }
62     return 0;
63 }
64
65 int
66 vl_set(register int vtype, u_int amt, u_char *typevec, u_short *amtvec,
67        u_char *nvp, int max)
68 {
69     register u_char *vp;
70     register u_char *endp;
71     register u_short *ap;
72     int n;
73
74     if (vtype < 0 || vtype > V_MAX)
75         return 0;
76     if (amt > 65536) {
77         logerror("vl_set: bad amt %d (%x), vtype %d\n", (int)amt, amt,
78                  vtype);
79         return 0;
80     }
81     vp = typevec;
82     ap = amtvec;
83     endp = vp + *nvp;
84     for (; vp < endp; vp++, ap++) {
85         if (*vp == vtype)
86             break;
87     }
88     if (vp == endp) {
89         if (amt == 0) {
90             /* deleting, but not present */
91             return 0;
92         }
93         if (*nvp == max) {
94             if (isdel(vtype) || isdist(vtype))
95                 return -1;
96             /* replace any del or dst entries */
97             if ((n = freeslot(typevec, endp)) < 0)
98                 return -1;
99             vp = &typevec[n];
100             ap = &amtvec[n];
101         } else {
102             /* add at end */
103             (*nvp)++;
104         }
105         *vp = vtype;
106         *ap = amt;
107     } else {
108         if (amt != 0) {
109             /* altering; just change value */
110             *ap = amt;
111             return 1;
112         }
113         (*nvp)--;
114         if (vp < endp - 1) {
115             /* if not last element, copy last to current */
116             *ap = amtvec[*nvp];
117             *vp = typevec[*nvp];
118         }
119     }
120     return 1;
121 }
122
123 int
124 vl_damage(register int pct, register u_char *typevec,
125           register u_short *amtvec, register int nelem)
126 {
127     register int i;
128     register int lose;
129     extern double people_damage;
130
131     if (pct >= 100)
132         return 0;
133     if (pct <= 0)
134         return nelem;
135     for (i = 0; i < nelem; i++) {
136         if (!isitem(typevec[i]))
137             continue;
138         if (opt_SUPER_BARS && typevec[i] == V_BAR)
139             continue;
140         lose = roundavg((double)amtvec[i] * pct * 0.01);
141         if (typevec[i] == V_CIVIL ||
142             typevec[i] == V_MILIT || typevec[i] == V_UW)
143             lose = ldround(people_damage * lose, 1);
144         if ((amtvec[i] -= lose) + 1 == 0) {
145             nelem--;
146             if (i == nelem)
147                 break;
148             typevec[i] = typevec[nelem];
149             amtvec[i] = amtvec[nelem];
150             i--;
151         }
152     }
153     return nelem;
154 }
155
156 /*
157  * extract all "mask" items from the variable list
158  * caller must pass a pointer to an aray of I_MAX+1,
159  * or else bad things will happen.
160  */
161 int
162 vl_getvec(register u_char *src_type, register u_short *src_amt,
163           register int src_nv, register int class, register int *dst_amt)
164 {
165     register int n;
166     int count;
167     int item;
168
169     for (n = 0; n < I_MAX + 1; n++)
170         dst_amt[n] = 0;
171     for (count = 0, n = 0; n < src_nv; n++) {
172         if ((src_type[n] & VT_TYPE) != class)
173             continue;
174         item = src_type[n] & ~VT_TYPE;
175         if (item > I_MAX) {
176             logerror("vl_getvec: bad I-type %d (vtype %d)\n",
177                      item, src_type[n]);
178             continue;
179         }
180         dst_amt[item] = src_amt[n];
181         count++;
182     }
183     return count;
184 }
185
186 /*
187  * Copy the vec into the variable list.  All items zero in
188  * the vec will be deleted from the vlist, and all items
189  * present in the vec will be added to the vlist.
190  */
191 int
192 vl_setvec(register u_char *type, register u_short *amt, u_char *nvp,
193           int max, register int class, register int *vec)
194 {
195     register int nv;
196     register int n;
197     register int vec_n;
198
199     nv = *nvp;
200     vec_n = 1;
201     n = 0;
202     while (n < nv) {
203         if ((type[n] & VT_TYPE) != class) {
204             n++;
205             continue;
206         }
207         /* find non-zero vec entry to overwrite current slot */
208         for (; vec_n <= I_MAX; vec_n++)
209             if (vec[vec_n] != 0)
210                 break;
211         if (vec_n > I_MAX) {
212             /* no more elements left; delete */
213             nv--;
214             if (n < nv) {
215                 /* copy last entry over current entry */
216                 type[n] = type[nv];
217                 amt[n] = amt[nv];
218             }
219         } else {
220             /* use new (unused) entry */
221             type[n] = vec_n | class;
222             amt[n] = vec[vec_n];
223             vec_n++;
224             n++;
225         }
226     }
227     *nvp = nv;
228     if (n >= nv && vec_n > I_MAX)
229         return 1;
230     /* free slots at end; copy rest of vec into the vlist */
231     for (; vec_n <= I_MAX && nv < max; vec_n++) {
232         if (vec[vec_n] == 0)
233             continue;
234         type[nv] = vec_n | class;
235         amt[nv] = vec[vec_n];
236         nv++;
237     }
238     *nvp = nv;
239     if (vec_n <= I_MAX && (class == VT_ITEM || class == VT_COND)) {
240         /*
241          * still stuff left; make free slots out of deliveries
242          * and distributes and stuff 'em in (only for item or cond)
243          */
244         for (; vec_n <= I_MAX; vec_n++) {
245             if (vec[vec_n] == 0)
246                 continue;
247             if ((n = freeslot(type, &type[max])) < 0) {
248                 logerror("vl_setvec: no free slots left\n");
249                 return 0;
250             }
251             logerror("vl_setvec: replacing type %d amt %d\n",
252                      type[n], amt[n]);
253             type[n] = vec_n | class;
254             amt[n] = vec[vec_n];
255         }
256     }
257     if (nv == max) {
258         /* checking for overflow */
259         while (vec_n <= I_MAX) {
260             if (vec[vec_n])
261                 break;
262         }
263         if (vec_n <= I_MAX) {
264             logerror("vl_setvec: no space for i-type #%d (%d)\n",
265                      vec_n, vec[vec_n]);
266             return 0;
267         }
268     }
269     return 1;
270 }
271
272 /*
273  * make a free slot; deliveries and distributions
274  * are fair game for us.
275  */
276 static
277     int
278 freeslot(u_char *vec, register u_char *end)
279 {
280     register u_char *vp;
281
282     for (vp = vec; vp < end; vp++) {
283         if (isdel(*vp) || isdist(*vp))
284             return vp - vec;
285     }
286     return -1;
287 }