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