1 /*
2 * XPilot NG, a multiplayer space war game.
3 *
4 * Copyright (C) 1991-2001 by
5 *
6 * Bj�rn Stabell <bjoern@xpilot.org>
7 * Ken Ronny Schouten <ken@xpilot.org>
8 * Bert Gijsbers <bert@xpilot.org>
9 * Dick Balaska <dick@xpilot.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include "xpserver.h"
27
28 /*
29 * Fast conversion of 'num' into 'str' starting at position 'i', returns
30 * index of character after converted number.
31 */
num2str(int num,char * str,int i)32 static int num2str(int num, char *str, int i)
33 {
34 int digits, t;
35
36 if (num < 0) {
37 str[i++] = '-';
38 num = -num;
39 }
40 if (num < 10) {
41 str[i++] = '0' + num;
42 return i;
43 }
44 for (t = num, digits = 0; t; t /= 10, digits++)
45 ;
46 for (t = i+digits-1; t >= 0; t--) {
47 str[t] = num % 10;
48 num /= 10;
49 }
50 return i + digits;
51 }
52
53
54 #define MODS_BIT0 (1<<0)
55 #define MODS_BIT1 (1<<1)
56
57 #define MODS_N_BIT0 (1<<0) /* nuclear */
58 #define MODS_N_BIT1 (1<<1) /* fullnuclear */
59 #define MODS_C_BIT (1<<2) /* cluster */
60 #define MODS_I_BIT (1<<3) /* implosion */
61 #define MODS_V_BIT0 (1<<4) /* velocity */
62 #define MODS_V_BIT1 (1<<5)
63 #define MODS_X_BIT0 (1<<6) /* mini */
64 #define MODS_X_BIT1 (1<<7)
65 #define MODS_Z_BIT0 (1<<8) /* spread */
66 #define MODS_Z_BIT1 (1<<9)
67 #define MODS_B_BIT0 (1<<10) /* power */
68 #define MODS_B_BIT1 (1<<11)
69 #define MODS_LS_BIT (1<<12) /* stun laser */
70 #define MODS_LB_BIT (1<<13) /* blinding laser */
71
Get_nuclear_modifier(modifiers_t mods)72 static inline int Get_nuclear_modifier(modifiers_t mods)
73 {
74 int n0, n1;
75
76 n0 = BIT(mods, MODS_N_BIT0) ? 1 : 0;
77 n1 = BIT(mods, MODS_N_BIT1) ? 1 : 0;
78
79 return (n1 << 1) + n0;
80 }
Set_nuclear_modifier(modifiers_t * mods,int value)81 static inline void Set_nuclear_modifier(modifiers_t *mods, int value)
82 {
83 LIMIT(value, 0, MODS_NUCLEAR_MAX);
84 if (BIT(value, MODS_BIT0))
85 SET_BIT(*mods, MODS_N_BIT0);
86 else
87 CLR_BIT(*mods, MODS_N_BIT0);
88 if (BIT(value, MODS_BIT1))
89 SET_BIT(*mods, MODS_N_BIT1);
90 else
91 CLR_BIT(*mods, MODS_N_BIT1);
92 }
93
Get_cluster_modifier(modifiers_t mods)94 static inline int Get_cluster_modifier(modifiers_t mods)
95 {
96 return (int) BIT(mods, MODS_C_BIT) ? 1 : 0;
97 }
Set_cluster_modifier(modifiers_t * mods,int value)98 static inline void Set_cluster_modifier(modifiers_t *mods, int value)
99 {
100 LIMIT(value, 0, 1);
101 if (value)
102 SET_BIT(*mods, MODS_C_BIT);
103 else
104 CLR_BIT(*mods, MODS_C_BIT);
105 }
106
Get_implosion_modifier(modifiers_t mods)107 static inline int Get_implosion_modifier(modifiers_t mods)
108 {
109 return (int) BIT(mods, MODS_I_BIT) ? 1 : 0;
110 }
Set_implosion_modifier(modifiers_t * mods,int value)111 static inline void Set_implosion_modifier(modifiers_t *mods, int value)
112 {
113 LIMIT(value, 0, 1);
114 if (value)
115 SET_BIT(*mods, MODS_I_BIT);
116 else
117 CLR_BIT(*mods, MODS_I_BIT);
118 }
119
Get_velocity_modifier(modifiers_t mods)120 static inline int Get_velocity_modifier(modifiers_t mods)
121 {
122 int v0, v1;
123
124 v0 = BIT(mods, MODS_V_BIT0) ? 1 : 0;
125 v1 = BIT(mods, MODS_V_BIT1) ? 1 : 0;
126
127 return (v1 << 1) + v0;
128 }
Set_velocity_modifier(modifiers_t * mods,int value)129 static inline void Set_velocity_modifier(modifiers_t *mods, int value)
130 {
131 LIMIT(value, 0, MODS_VELOCITY_MAX);
132 if (BIT(value, MODS_BIT0))
133 SET_BIT(*mods, MODS_V_BIT0);
134 else
135 CLR_BIT(*mods, MODS_V_BIT0);
136 if (BIT(value, MODS_BIT1))
137 SET_BIT(*mods, MODS_V_BIT1);
138 else
139 CLR_BIT(*mods, MODS_V_BIT1);
140 }
141
Get_mini_modifier(modifiers_t mods)142 static inline int Get_mini_modifier(modifiers_t mods)
143 {
144 int x0, x1;
145
146 x0 = BIT(mods, MODS_X_BIT0) ? 1 : 0;
147 x1 = BIT(mods, MODS_X_BIT1) ? 1 : 0;
148
149 return (x1 << 1) + x0;
150 }
Set_mini_modifier(modifiers_t * mods,int value)151 static inline void Set_mini_modifier(modifiers_t *mods, int value)
152 {
153 LIMIT(value, 0, MODS_MINI_MAX);
154 if (BIT(value, MODS_BIT0))
155 SET_BIT(*mods, MODS_X_BIT0);
156 else
157 CLR_BIT(*mods, MODS_X_BIT0);
158 if (BIT(value, MODS_BIT1))
159 SET_BIT(*mods, MODS_X_BIT1);
160 else
161 CLR_BIT(*mods, MODS_X_BIT1);
162 }
163
Get_spread_modifier(modifiers_t mods)164 static inline int Get_spread_modifier(modifiers_t mods)
165 {
166 int z0, z1;
167
168 z0 = BIT(mods, MODS_Z_BIT0) ? 1 : 0;
169 z1 = BIT(mods, MODS_Z_BIT1) ? 1 : 0;
170
171 return (z1 << 1) + z0;
172 }
Set_spread_modifier(modifiers_t * mods,int value)173 static inline void Set_spread_modifier(modifiers_t *mods, int value)
174 {
175 LIMIT(value, 0, MODS_SPREAD_MAX);
176 if (BIT(value, MODS_BIT0))
177 SET_BIT(*mods, MODS_Z_BIT0);
178 else
179 CLR_BIT(*mods, MODS_Z_BIT0);
180 if (BIT(value, MODS_BIT1))
181 SET_BIT(*mods, MODS_Z_BIT1);
182 else
183 CLR_BIT(*mods, MODS_Z_BIT1);
184 }
185
Get_power_modifier(modifiers_t mods)186 static inline int Get_power_modifier(modifiers_t mods)
187 {
188 int b0, b1;
189
190 b0 = BIT(mods, MODS_B_BIT0) ? 1 : 0;
191 b1 = BIT(mods, MODS_B_BIT1) ? 1 : 0;
192
193 return (b1 << 1) + b0;
194 }
Set_power_modifier(modifiers_t * mods,int value)195 static inline void Set_power_modifier(modifiers_t *mods, int value)
196 {
197 LIMIT(value, 0, MODS_POWER_MAX);
198 if (BIT(value, MODS_BIT0))
199 SET_BIT(*mods, MODS_B_BIT0);
200 else
201 CLR_BIT(*mods, MODS_B_BIT0);
202 if (BIT(value, MODS_BIT1))
203 SET_BIT(*mods, MODS_B_BIT1);
204 else
205 CLR_BIT(*mods, MODS_B_BIT1);
206 }
207
Get_laser_modifier(modifiers_t mods)208 static inline int Get_laser_modifier(modifiers_t mods)
209 {
210 int ls, lb;
211
212 ls = BIT(mods, MODS_LS_BIT) ? 1 : 0;
213 lb = BIT(mods, MODS_LB_BIT) ? 1 : 0;
214
215 return (lb << 1) + ls;
216 }
Set_laser_modifier(modifiers_t * mods,int value)217 static inline void Set_laser_modifier(modifiers_t *mods, int value)
218 {
219 LIMIT(value, 0, MODS_LASER_MAX);
220 if (BIT(value, MODS_BIT0))
221 SET_BIT(*mods, MODS_LS_BIT);
222 else
223 CLR_BIT(*mods, MODS_LS_BIT);
224 if (BIT(value, MODS_BIT1))
225 SET_BIT(*mods, MODS_LB_BIT);
226 else
227 CLR_BIT(*mods, MODS_LB_BIT);
228 }
229
230 /*
231 * Returns 0 if ok, -1 if not allowed.
232 */
Mods_set(modifiers_t * mods,modifier_t modifier,int val)233 int Mods_set(modifiers_t *mods, modifier_t modifier, int val)
234 {
235 bool allow = false;
236
237 if (val == 0)
238 allow = true;
239 else if (modifier == ModsNuclear) {
240 if (BIT(world->rules->mode, ALLOW_NUKES))
241 allow = true;
242 }
243 else if (modifier == ModsCluster) {
244 if (BIT(world->rules->mode, ALLOW_CLUSTERS))
245 allow = true;
246 }
247 else if (modifier == ModsLaser) {
248 if (BIT(world->rules->mode, ALLOW_LASER_MODIFIERS))
249 allow = true;
250 }
251 else {
252 if (BIT(world->rules->mode, ALLOW_MODIFIERS))
253 allow = true;
254 }
255
256 if (!allow)
257 return -1;
258
259 switch (modifier) {
260 case ModsNuclear:
261 Set_nuclear_modifier(mods, val);
262 break;
263 case ModsCluster:
264 Set_cluster_modifier(mods, val);
265 break;
266 case ModsImplosion:
267 Set_implosion_modifier(mods, val);
268 break;
269 case ModsVelocity:
270 Set_velocity_modifier(mods, val);
271 break;
272 case ModsMini:
273 Set_mini_modifier(mods, val);
274 break;
275 case ModsSpread:
276 Set_spread_modifier(mods, val);
277 break;
278 case ModsPower:
279 Set_power_modifier(mods, val);
280 break;
281 case ModsLaser:
282 Set_laser_modifier(mods, val);
283 break;
284 default:
285 warn("No such modifier: %d", modifier);
286 assert(0);
287 break;
288 }
289
290 return 0;
291 }
292
Mods_get(modifiers_t mods,modifier_t modifier)293 int Mods_get(modifiers_t mods, modifier_t modifier)
294 {
295 switch (modifier) {
296 case ModsNuclear:
297 return Get_nuclear_modifier(mods);
298 case ModsCluster:
299 return Get_cluster_modifier(mods);
300 case ModsImplosion:
301 return Get_implosion_modifier(mods);
302 case ModsVelocity:
303 return Get_velocity_modifier(mods);
304 case ModsMini:
305 return Get_mini_modifier(mods);
306 case ModsSpread:
307 return Get_spread_modifier(mods);
308 case ModsPower:
309 return Get_power_modifier(mods);
310 case ModsLaser:
311 return Get_laser_modifier(mods);
312 default:
313 assert(0);
314 break;
315 }
316 return 0;
317 }
318
319 /*
320 * modstr must be able to hold at least MAX_CHARS chars.
321 */
Mods_to_string(modifiers_t mods,char * modstr,size_t size)322 void Mods_to_string(modifiers_t mods, char *modstr, size_t size)
323 {
324 int i = 0, t;
325
326 if (size < MAX_CHARS)
327 return;
328 t = Get_nuclear_modifier(mods);
329 if (t & MODS_FULLNUCLEAR)
330 modstr[i++] = 'F';
331 if (t & MODS_NUCLEAR)
332 modstr[i++] = 'N';
333 if (Get_cluster_modifier(mods))
334 modstr[i++] = 'C';
335 if (Get_implosion_modifier(mods))
336 modstr[i++] = 'I';
337 t = Get_velocity_modifier(mods);
338 if (t) {
339 if (i) modstr[i++] = ' ';
340 modstr[i++] = 'V';
341 i = num2str(t, modstr, i);
342 }
343 t = Get_mini_modifier(mods);
344 if (t) {
345 if (i) modstr[i++] = ' ';
346 modstr[i++] = 'X';
347 i = num2str(t + 1, modstr, i);
348 }
349 t = Get_spread_modifier(mods);
350 if (t) {
351 if (i) modstr[i++] = ' ';
352 modstr[i++] = 'Z';
353 i = num2str(t, modstr, i);
354 }
355 t = Get_power_modifier(mods);
356 if (t) {
357 if (i) modstr[i++] = ' ';
358 modstr[i++] = 'B';
359 i = num2str(t, modstr, i);
360 }
361 t = Get_laser_modifier(mods);
362 if (t) {
363 if (i) modstr[i++] = ' ';
364 modstr[i++] = 'L';
365 if (t & MODS_LASER_STUN)
366 modstr[i++] = 'S';
367 if (t & MODS_LASER_BLIND)
368 modstr[i++] = 'B';
369 }
370 modstr[i] = '\0';
371 }
372
373
Mods_filter(modifiers_t * mods)374 void Mods_filter(modifiers_t *mods)
375 {
376 if (!BIT(world->rules->mode, ALLOW_NUKES))
377 Mods_set(mods, ModsNuclear, 0);
378
379 if (!BIT(world->rules->mode, ALLOW_CLUSTERS))
380 Mods_set(mods, ModsCluster, 0);
381
382 if (!BIT(world->rules->mode, ALLOW_MODIFIERS)) {
383 Mods_set(mods, ModsImplosion, 0);
384 Mods_set(mods, ModsVelocity, 0);
385 Mods_set(mods, ModsMini, 0);
386 Mods_set(mods, ModsSpread, 0);
387 Mods_set(mods, ModsPower, 0);
388 }
389
390 if (!BIT(world->rules->mode, ALLOW_LASER_MODIFIERS))
391 Mods_set(mods, ModsLaser, 0);
392 }
393
str2num(const char ** strp,int min,int max)394 static int str2num (const char **strp, int min, int max)
395 {
396 const char *str = *strp;
397 int num = 0;
398
399 while (isdigit(*str)) {
400 num *= 10;
401 num += *str++ - '0';
402 }
403 *strp = str;
404 LIMIT(num, min, max);
405 return num;
406 }
407
Player_set_modbank(player_t * pl,int bank,const char * str)408 void Player_set_modbank(player_t *pl, int bank, const char *str)
409 {
410 const char *cp;
411 modifiers_t mods;
412 int mini, velocity, spread, power;
413
414 if (bank >= NUM_MODBANKS)
415 return;
416
417 Mods_clear(&mods);
418
419 for (cp = str; *cp; cp++) {
420 switch (*cp) {
421 case 'F': case 'f':
422 if (*(cp+1) == 'N' || *(cp+1) == 'n')
423 Mods_set(&mods, ModsNuclear,
424 MODS_NUCLEAR|MODS_FULLNUCLEAR);
425 break;
426 case 'N': case 'n':
427 if (Mods_get(mods, ModsNuclear) == 0)
428 Mods_set(&mods, ModsNuclear, MODS_NUCLEAR);
429 break;
430 case 'C': case 'c':
431 Mods_set(&mods, ModsCluster, 1);
432 break;
433 case 'I': case 'i':
434 Mods_set(&mods, ModsImplosion, 1);
435 break;
436 case 'V': case 'v':
437 cp++;
438 velocity = str2num (&cp, 0, MODS_VELOCITY_MAX);
439 Mods_set(&mods, ModsVelocity, velocity);
440 cp--;
441 break;
442 case 'X': case 'x':
443 cp++;
444 mini = str2num (&cp, 1, MODS_MINI_MAX+1) - 1;
445 Mods_set(&mods, ModsMini, mini);
446 cp--;
447 break;
448 case 'Z': case 'z':
449 cp++;
450 spread = str2num (&cp, 0, MODS_SPREAD_MAX);
451 Mods_set(&mods, ModsSpread, spread);
452 cp--;
453 break;
454 case 'B': case 'b':
455 cp++;
456 power = str2num (&cp, 0, MODS_POWER_MAX);
457 Mods_set(&mods, ModsPower, power);
458 cp--;
459 break;
460 case 'L': case 'l':
461 cp++;
462 if (*cp == 'S' || *cp == 's')
463 Mods_set(&mods, ModsLaser, MODS_LASER_STUN);
464 if (*cp == 'B' || *cp == 'b')
465 Mods_set(&mods, ModsLaser, MODS_LASER_BLIND);
466 break;
467 default:
468 /* Ignore unknown modifiers. */
469 break;
470 }
471 }
472 pl->modbank[bank] = mods;
473 }
474