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