Mercurial > ~darius > hgwebdir.cgi > paradise_client
comparison macros.c @ 3:5a977ccbc7a9 default tip
Empty changelog
author | darius |
---|---|
date | Sat, 06 Dec 1997 05:41:29 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:fba0b6e6cdc7 | 3:5a977ccbc7a9 |
---|---|
1 /* $Id: macros.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $ */ | |
2 | |
3 /* here's pretty much all the macro code. */ | |
4 /* This bears little resemblance to the */ | |
5 /* BRM code, i.e. it's somewhat organized :)*/ | |
6 /* Bill Dyess 10/05/93 [BDyess]*/ | |
7 | |
8 #ifdef MACROS | |
9 #include"copyright.h" | |
10 #include<stdio.h> | |
11 #if !defined(SVR4) && !defined(sparc) | |
12 #include<strings.h> | |
13 #else | |
14 #include<string.h> | |
15 #endif /* !SVR4 && !sparc */ | |
16 #include<ctype.h> | |
17 #include<fcntl.h> | |
18 #include<sys/types.h> | |
19 #include"Wlib.h" | |
20 #include"data.h" | |
21 #include"defs.h" | |
22 #include"struct.h" | |
23 #include"gameconf.h" | |
24 #include"proto.h" | |
25 | |
26 #define MAXMACRO 4096 | |
27 #if defined(__STDC__) || defined(RS6K) || defined(sgi) | |
28 typedef signed char s_char; | |
29 #else | |
30 typedef char s_char; | |
31 #endif | |
32 | |
33 /* prototypes */ | |
34 void doMacro2 P((struct macro * m, W_Event * data)); | |
35 void handle_dollar P((char **locpntr, char **destpntr, W_Event * data)); | |
36 void handle_special P((char **locpntr, char **destpntr, W_Event * data)); | |
37 char *strtoupper P((char *buf)); | |
38 char *strtolower P((char *buf)); | |
39 void handle_test P((char **locpntr, char **destpntr, W_Event * data)); | |
40 void handle_conditional P((char **locpntr, char **destpntr, W_Event * data)); | |
41 void getTestString P((char *buf, char **locpntr, char **destpntr, W_Event * data)); | |
42 void getConditionalString P((char **locpntr, char **destpntr, W_Event * data)); | |
43 void ignoreConditionalString P((char **locpntr)); | |
44 | |
45 int abortflag = 0; | |
46 | |
47 void | |
48 initMacros() | |
49 { | |
50 struct stringlist *s; | |
51 char *loc; | |
52 unsigned char ch; | |
53 struct macro *m; | |
54 int i; | |
55 struct dmacro_list *dm; | |
56 struct dmacro_list *dm_def; | |
57 int notdone; | |
58 unsigned char c; | |
59 char *str; | |
60 | |
61 /* initialize macro lookup tables */ | |
62 bzero(macrotable, sizeof(struct macro *) * 256); | |
63 | |
64 #ifdef RC_DISTRESS | |
65 /* sizeof doesn't work if it isn't in the same source file, shoot me */ | |
66 MCOPY(dist_defaults, dist_prefered, sizedist); | |
67 #endif | |
68 | |
69 for (s = defaults; s; s = s->next) { | |
70 #ifdef RC_DISTRESS | |
71 if (strncmpi(s->string, "dist.", 5) == 0) { | |
72 str = (s->string) + 5; | |
73 if (*str == '^') { | |
74 str++; | |
75 if (*str == '^') | |
76 c = '^'; | |
77 else | |
78 c = *str + 128; | |
79 } else | |
80 c = *str; | |
81 str++; | |
82 if (*str != '.') { | |
83 str = (s->string) + 4; | |
84 c = '\0'; | |
85 } | |
86 str++; | |
87 | |
88 notdone = 1; | |
89 for (dm = &dist_prefered[take], dm_def = &dist_defaults[take], i = take; | |
90 dm->name && notdone; dm++, dm_def++, i++) { | |
91 if (strcmpi(str, dm->name) == 0) { | |
92 dm->macro = strdup(s->value); | |
93 if (c) { | |
94 if (!macrotable[c]) { | |
95 macrotable[c] = (struct macro *) malloc(sizeof(struct macro)); | |
96 bzero(macrotable[c], sizeof(struct macro)); | |
97 } | |
98 macrotable[c]->flags |= MACRCD; | |
99 macrotable[c]->to = i; | |
100 /* printf("dist.%c.%s: %s\n",c,dm->name,dm->macro);*/ | |
101 dm->c = c; | |
102 dm_def->c = c; | |
103 } | |
104 notdone = 0; | |
105 } | |
106 } | |
107 } | |
108 #endif /* RC_DISTRESS */ | |
109 #ifdef BEEPLITE | |
110 | |
111 else if (strncmpi(s->string, "lite.", 5) == 0) { | |
112 int offset = 5; | |
113 char **lt; | |
114 | |
115 if (s->string[6] == '.') | |
116 offset = 7; | |
117 | |
118 notdone = 1; | |
119 | |
120 for (lt = &distlite[take], dm = &dist_prefered[take]; | |
121 dm->name && notdone; dm++, lt++) { | |
122 if (strcmpi(s->string + offset, dm->name) == 0) { | |
123 *lt = strdup(s->value); | |
124 /* printf("lite.%s: %s\n",dm->name,*lt);*/ | |
125 | |
126 notdone = 0; | |
127 } | |
128 } | |
129 if (notdone) | |
130 fprintf(stderr, "Unknown lite %s\n", s->string + offset); | |
131 } | |
132 #endif /* BEEPLITE */ | |
133 if (!strncmpi("mac", s->string, 3)) { | |
134 if (s->string[3] == '.') | |
135 loc = s->string + 4; | |
136 else if (strncmpi("ro.", s->string + 3, 3)) | |
137 continue; | |
138 else | |
139 loc = s->string + 6; | |
140 if (*loc == '^') { /* possible control char */ | |
141 loc++; | |
142 if (*loc == '^' && *loc) | |
143 ch = '^'; | |
144 else | |
145 ch = *loc + 128; | |
146 } else | |
147 ch = *loc; | |
148 loc++; | |
149 if (!macrotable[ch]) { | |
150 /* | |
151 make sure it doesn't already exist. I've allowed people | |
152 to have singlemacro: before the macro.*.* statements, so | |
153 it is possible | |
154 */ | |
155 /* | |
156 modified to allow multline macros by creating a linked | |
157 list of macro structures. -JR | |
158 */ | |
159 if (ch == '?') { | |
160 printf("Can't use '?' as a macro. It is reserved for the macro window. Ignoring.\n"); | |
161 continue; | |
162 } | |
163 macrotable[ch] = m = (struct macro *) malloc(sizeof(struct macro)); | |
164 bzero(m, sizeof(struct macro)); | |
165 } else { | |
166 #ifdef RC_DISTRESS | |
167 if (macrotable[ch]->flags & MACRCD) { | |
168 m = macrotable[ch]; | |
169 m->flags &= ~(MACRCD); /* in case singleMacro was | |
170 set */ | |
171 m->next = 0; | |
172 } else | |
173 #endif | |
174 { | |
175 m = (struct macro *) malloc(sizeof(struct macro)); | |
176 m->next = macrotable[ch]; | |
177 macrotable[ch] = m; | |
178 m->next->flags |= MACMULTI; | |
179 m->flags = m->next->flags; | |
180 } | |
181 } | |
182 if (*(loc++) != '.') | |
183 m->to = -2; /* no destination given */ | |
184 else { | |
185 ch = *loc; | |
186 if (ch == '%') { | |
187 m->specialto = toupper(*(loc + 1)); | |
188 m->to = -1; | |
189 } else { | |
190 m->to = ch; | |
191 } | |
192 } | |
193 m->string = strdup(s->value); | |
194 } else if (!strncmpi("singlemacro", s->string, 11)) { | |
195 loc = s->value; | |
196 while (*loc) { | |
197 ch = *(loc++); | |
198 if (ch == '^') {/* for control chars */ | |
199 if (*loc != '^' && *loc) | |
200 ch = *loc + 128; | |
201 loc++; | |
202 } | |
203 if (!macrotable[ch]) { | |
204 m = macrotable[ch] = (struct macro *) malloc(sizeof(struct macro)); | |
205 bzero(m, sizeof(struct macro)); | |
206 m->flags = MACSINGLE; | |
207 } else { | |
208 for (m = macrotable[ch]; m; m = m->next) | |
209 m->flags |= MACSINGLE; | |
210 } | |
211 } | |
212 } | |
213 } | |
214 for (i = 0; i < 256; i++) { | |
215 /* eliminate any macros that have (null) macro strings */ | |
216 if (macrotable[i] && !(macrotable[i]->flags & MACRCD)) { | |
217 struct macro *tmp, **scan; | |
218 | |
219 scan=¯otable[i]; | |
220 while (*scan) { | |
221 if ( (*scan)->string ) { | |
222 scan = &(*scan)->next; | |
223 } else { | |
224 tmp = (*scan); | |
225 *scan = tmp->next; | |
226 free(tmp); | |
227 } | |
228 } | |
229 } | |
230 } | |
231 #ifdef RC_DISTRESS | |
232 /* | |
233 make macro entries for the default RCD keys, if those keys don't have | |
234 macros defined | |
235 */ | |
236 for (dm = &dist_prefered[take], i = take; dm->name; dm++, i++) { | |
237 if (!macrotable[dm->c]) { | |
238 macrotable[dm->c] = (struct macro *) malloc(sizeof(struct macro)); | |
239 bzero(macrotable[dm->c], sizeof(struct macro)); | |
240 macrotable[dm->c]->flags = MACRCD; | |
241 macrotable[dm->c]->to = i; | |
242 } | |
243 } | |
244 #endif | |
245 } | |
246 | |
247 void | |
248 doMacro(data) | |
249 W_Event *data; | |
250 /* takes a key as input and creates a string that is then sent to smessage*/ | |
251 { | |
252 static struct macro *m; | |
253 int key = data->key; | |
254 | |
255 if (key == '?') { | |
256 showMacroWin(); | |
257 macroState = 0; | |
258 return; | |
259 } | |
260 if (macroState != 2) | |
261 m = macrotable[key]; | |
262 if (!m) { | |
263 W_Beep(); | |
264 warning("No such macro"); | |
265 macroState = 0; | |
266 return; /* no macro */ | |
267 } | |
268 #ifdef RC_DISTRESS | |
269 if (m->flags & MACRCD) { | |
270 rcd(m->to, data); | |
271 macroState = 0; | |
272 return; | |
273 } | |
274 #endif | |
275 while (m) { | |
276 if (macroState == 2) { | |
277 m->to = key; | |
278 doMacro2(m, data); | |
279 m->to = -2; | |
280 } else { | |
281 doMacro2(m, data); | |
282 if (macroState == 2) | |
283 return; | |
284 } | |
285 m = m->next; | |
286 } | |
287 macroState = 0; | |
288 warning(" "); | |
289 } | |
290 | |
291 void | |
292 doMacro2(m, data) | |
293 struct macro *m; | |
294 W_Event *data; | |
295 { | |
296 int group = -1, recip = 0; | |
297 char buf[MAXMACRO], sourcebuf[MAXMACRO]; | |
298 char *loc, *dest; | |
299 struct obtype *target; | |
300 | |
301 /* first figure out who I'm going to send it to */ | |
302 if ((s_char)m->to == -1) { /* special recipient */ | |
303 switch (m->specialto) { | |
304 case 'I': /* send a message to myself */ | |
305 case 'C': | |
306 group = MINDIV; | |
307 recip = me->p_no; | |
308 break; | |
309 case 'U': /* send message to player nearest mouse */ | |
310 case 'P': | |
311 group = MINDIV; | |
312 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER); | |
313 recip = target->o_num; | |
314 break; | |
315 case 'T': /* send message to team of the player nearest | |
316 mouse */ | |
317 case 'Z': | |
318 group = MTEAM; | |
319 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER); | |
320 recip = idx_to_mask(players[target->o_num].p_teami); | |
321 break; | |
322 case 'G': /* send message to nearest friendly player to | |
323 my ship */ | |
324 group = MINDIV; | |
325 target = gettarget((W_Window) 0, me->p_x, me->p_y, | |
326 TARG_PLAYER | TARG_FRIENDLY); | |
327 recip = target->o_num; | |
328 break; | |
329 case 'H': /* send message to nearest enemy player to my | |
330 ship */ | |
331 group = MINDIV; | |
332 target = gettarget((W_Window) 0, me->p_x, me->p_y, | |
333 TARG_PLAYER | TARG_ENEMY); | |
334 recip = target->o_num; | |
335 break; | |
336 default: | |
337 warning("Bad macro - incorrect 'to' field"); | |
338 break; | |
339 } | |
340 } else if ((s_char)m->to == -2) { /* get recipient not provided, so change | |
341 state to get one */ | |
342 macroState = 2; | |
343 warning("Send macro to who?"); | |
344 return; | |
345 } else | |
346 recip = m->to; | |
347 /* now parse the macro itself. */ | |
348 strcpy(sourcebuf, m->string); | |
349 loc = sourcebuf; | |
350 dest = buf; | |
351 while (*loc) { | |
352 if (*loc == '$') { | |
353 loc++; | |
354 handle_dollar(&loc, &dest, data); /* handle the special escape */ | |
355 } else if (*loc == '%') { | |
356 loc++; | |
357 if (*loc == '*') | |
358 return; /* %* means exit macro NOW */ | |
359 handle_special(&loc, &dest, data); /* handle the special escape */ | |
360 } else { | |
361 *(dest++) = *(loc++); | |
362 } | |
363 } | |
364 *dest = 0; | |
365 if (buf[0] == 0 || abortflag) { /* abortflag means somewhere there | |
366 was a %* */ | |
367 abortflag = 0; | |
368 macroState = 0; | |
369 return; /* null message. If you *really* want to | |
370 print a null message, use <space> */ | |
371 } | |
372 if (group == -1) | |
373 group = getgroup(recip, &recip); | |
374 if (group <= 0) | |
375 return; | |
376 if ((m->flags & MACMULTI) && (F_multiline_enabled || paradise)) | |
377 group |= MMACRO; | |
378 pmessage(buf, recip, group); | |
379 } | |
380 | |
381 void | |
382 handle_special(locpntr, destpntr, data) | |
383 char **locpntr, **destpntr; | |
384 W_Event *data; | |
385 { | |
386 char ch = **locpntr; | |
387 char *buf = *destpntr; | |
388 struct obtype *target; | |
389 struct macro *m; | |
390 int targettype = 0; | |
391 struct id *id; | |
392 /* for pingstats */ | |
393 #if 0 | |
394 extern int ping_iloss_sc; /* inc % loss 0--100, server to client */ | |
395 extern int ping_iloss_cs; /* inc % loss 0--100, client to server */ | |
396 #endif /* 0 */ | |
397 extern int ping_tloss_sc; /* total % loss 0--100, server to client */ | |
398 extern int ping_tloss_cs; /* total % loss 0--100, client to server */ | |
399 #if 0 | |
400 extern int ping_lag; /* delay in ms of last ping */ | |
401 #endif /* 0 */ | |
402 extern int ping_av; /* average rt */ | |
403 extern int ping_sd; /* standard deviation */ | |
404 | |
405 switch (ch) { | |
406 case 'a': /* armies carried by sender */ | |
407 sprintf(buf, "%d", me->p_armies); | |
408 break; | |
409 case 'd': /* sender damage percentage */ | |
410 sprintf(buf, "%d", 100 * me->p_damage / me->p_ship->s_maxdamage); | |
411 break; | |
412 case 's': /* sender shield percentage */ | |
413 sprintf(buf, "%d", 100 * me->p_shield / me->p_ship->s_maxshield); | |
414 break; | |
415 case 'f': /* sender fuel percentage */ | |
416 sprintf(buf, "%d", 100 * me->p_fuel / me->p_ship->s_maxfuel); | |
417 break; | |
418 case 'w': /* sender wtemp percentage */ | |
419 sprintf(buf, "%d", 100 * me->p_wtemp / me->p_ship->s_maxwpntemp); | |
420 break; | |
421 case 'e': /* sender etemp percentage */ | |
422 sprintf(buf, "%d", 100 * me->p_etemp / me->p_ship->s_maxegntemp); | |
423 break; | |
424 case 'r': /* team id character of target player */ | |
425 target = gettarget(data->Window, data->x, data->y, TARG_PLAYER); | |
426 buf[0] = teaminfo[players[target->o_num].p_teami].letter; | |
427 buf[1] = 0; | |
428 break; | |
429 case 't': /* team id character of target planet */ | |
430 target = gettarget(data->Window, data->x, data->y, TARG_PLANET); | |
431 buf[0] = teaminfo[mask_to_idx(planets[target->o_num].pl_owner)].letter; | |
432 buf[1] = 0; | |
433 break; | |
434 case 'p': /* id character of target player */ | |
435 targettype = TARG_PLAYER; | |
436 case 'g': /* id character of target friendly player */ | |
437 if (!targettype) | |
438 targettype = TARG_PLAYER | TARG_FRIENDLY; | |
439 case 'h': /* id char of target enemy player */ | |
440 if (!targettype) | |
441 targettype = TARG_PLAYER | TARG_ENEMY; | |
442 id = getTargetID(data->Window, data->x, data->y, targettype); | |
443 buf[0] = id->mapstring[1]; | |
444 buf[1] = 0; | |
445 break; | |
446 case 'P': /* id character of player nearest sender */ | |
447 id = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLAYER); | |
448 buf[0] = id->mapstring[1]; | |
449 buf[1] = 0; | |
450 break; | |
451 case 'T': /* team id character of sender team */ | |
452 buf[0] = me->p_mapchars[0]; | |
453 buf[1] = 0; | |
454 break; | |
455 case 'c': /* sender id character */ | |
456 buf[0] = me->p_mapchars[1]; | |
457 buf[1] = 0; | |
458 break; | |
459 case 'C': /* 1 if cloaked, 0 if not [BDyess] */ | |
460 if (me->p_flags & PFCLOAK) | |
461 buf[0] = '1'; | |
462 else | |
463 buf[0] = '0'; | |
464 buf[1] = 0; | |
465 break; | |
466 case 'n': /* armies on target planet */ | |
467 target = gettarget(data->Window, data->x, data->y, TARG_PLANET); | |
468 sprintf(buf, "%d", planets[target->o_num].pl_info ? | |
469 planets[target->o_num].pl_armies : | |
470 -1); | |
471 break; | |
472 case 'E': /* 1 if etemped, 0 if not */ | |
473 if (me->p_flags & PFENG) | |
474 buf[0] = '1'; | |
475 else | |
476 buf[0] = '0'; | |
477 buf[1] = 0; | |
478 break; | |
479 case 'W': /* 1 if wtemped, 0 if not */ | |
480 if (me->p_flags & PFWEP) | |
481 buf[0] = '1'; | |
482 else | |
483 buf[0] = '0'; | |
484 buf[1] = 0; | |
485 break; | |
486 case 'S': /* sender two character ship type */ | |
487 strncpy(buf, me->p_ship->s_desig, 2); | |
488 buf[2] = 0; | |
489 break; | |
490 case 'G': /* id char of friendly player nearest sender */ | |
491 targettype = TARG_FRIENDLY; | |
492 case 'H': /* id char of enemy player nearest sender */ | |
493 if (!targettype) | |
494 targettype = TARG_ENEMY; | |
495 id = getTargetID((W_Window) 0, me->p_x, me->p_y, | |
496 TARG_PLAYER | targettype); | |
497 buf[0] = id->mapstring[1]; | |
498 buf[1] = 0; | |
499 break; | |
500 case 'l': /* three character name of target planet */ | |
501 case 'L': | |
502 id = getTargetID(data->Window, data->x, data->y, TARG_PLANET); | |
503 strcpy(buf, id->mapstring); | |
504 buf[0] = tolower(buf[0]); | |
505 break; | |
506 case 'i': /* sender full player name (16 character max) */ | |
507 case 'I': | |
508 strncpy(buf, me->p_name, 16); | |
509 buf[16] = 0; | |
510 break; | |
511 case 'u': /* full name of target player (16 character | |
512 max) */ | |
513 case 'U': | |
514 id = getTargetID(data->Window, data->x, data->y, TARG_PLAYER); | |
515 strncpy(buf, id->name, 16); | |
516 buf[16] = 0; | |
517 break; | |
518 case 'z': /* 3 letter team id of target planet */ | |
519 case 'Z': | |
520 id = getTargetID(data->Window, data->x, data->y, TARG_PLANET); | |
521 strcpy(buf, teaminfo[id->team].shortname); | |
522 strtolower(buf); | |
523 break; | |
524 case 'b': /* nearest planet to sender */ | |
525 case 'B': | |
526 id = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLANET); | |
527 strcpy(buf, id->mapstring); | |
528 buf[0] = tolower(buf[0]); | |
529 break; | |
530 case 'v': /* average ping round trip time */ | |
531 sprintf(buf, "%d", ping_av); | |
532 break; | |
533 case 'V': /* ping stdev */ | |
534 sprintf(buf, "%d", ping_sd); | |
535 break; | |
536 case 'y': /* packet loss */ | |
537 sprintf(buf, "%d", (2 * ping_tloss_sc + ping_tloss_cs) / 3); | |
538 break; | |
539 case 'm': /* last message */ | |
540 case 'M': | |
541 strcpy(buf, lastMessage); | |
542 break; | |
543 case 'o': /* insert three letter team name */ | |
544 case 'O': | |
545 strcpy(buf, teaminfo[me->p_teami].shortname); | |
546 break; | |
547 case ' ': /* nothing. This is so you can start a macro | |
548 with spaces */ | |
549 buf[0] = ' '; | |
550 buf[1] = 0; | |
551 break; | |
552 case '%': /* insert % */ | |
553 buf[0] = '%'; | |
554 buf[1] = 0; | |
555 break; | |
556 case '?': /* start test */ | |
557 (*locpntr)++; | |
558 handle_test(locpntr, destpntr, data); | |
559 return; | |
560 case '{': /* conditional */ | |
561 handle_conditional(locpntr, destpntr, data); | |
562 return; | |
563 case '*': /* abort! */ | |
564 abortflag = 1; | |
565 return; | |
566 case '2': /* is paradise? sorry, ran out of good | |
567 letters. '2' means, 'is Netrek II?'. */ | |
568 buf[0] = paradise + '0'; | |
569 buf[1] = 0; | |
570 break; | |
571 case '_': /* call another macro. Added 1/24/94 [BDyess] */ | |
572 (*locpntr)++; | |
573 if (**locpntr == '^') { /* control char */ | |
574 (*locpntr)++; | |
575 m = macrotable[**locpntr + (**locpntr == '^') ? 0 : 128]; | |
576 } else { | |
577 m = macrotable[(int) **locpntr]; | |
578 } | |
579 if (m) { /* does the macro exist? */ | |
580 char temp[MAXMACRO]; | |
581 strcpy(temp, m->string); | |
582 strcat(temp, *locpntr + 1); | |
583 strcpy(*locpntr + 1, temp); | |
584 } else { /* somebody screwed up */ | |
585 printf("Error: called macro "); | |
586 if (&m - macrotable >= 128) | |
587 putchar('^'); | |
588 printf("%c doesn't exist.\n", **locpntr); | |
589 } | |
590 buf[0] = 0; | |
591 break; | |
592 default: | |
593 sprintf(buf, "Unknown %% escape: %%%c", ch); | |
594 warning(buf); | |
595 buf[0] = 0; | |
596 break; | |
597 } | |
598 if (isupper(ch)) | |
599 strtoupper(buf); | |
600 (*locpntr)++; | |
601 while (**destpntr) | |
602 (*destpntr)++; | |
603 return; | |
604 } | |
605 | |
606 void | |
607 handle_test(locpntr, destpntr, data) | |
608 char **locpntr, **destpntr; | |
609 W_Event *data; | |
610 { | |
611 char l[MAXMACRO], r[MAXMACRO], condition = 0; | |
612 short trueflag = 0; | |
613 | |
614 getTestString(l, locpntr, destpntr, data); | |
615 if (**locpntr != '%') { | |
616 condition = *((*locpntr)++); | |
617 getTestString(r, locpntr, destpntr, data); | |
618 } | |
619 switch (condition) { | |
620 case '=': | |
621 if (!strcmp(l, r)) | |
622 trueflag = 1; | |
623 break; | |
624 case '>': | |
625 if (atoi(l) > atoi(r)) | |
626 trueflag = 1; | |
627 break; | |
628 case '<': | |
629 if (atoi(l) < atoi(r)) | |
630 trueflag = 1; | |
631 break; | |
632 default: | |
633 if (atoi(l)) | |
634 trueflag = 1; | |
635 } | |
636 **destpntr = '0' + trueflag; | |
637 *(*destpntr + 1) = 0; | |
638 (*destpntr)++; | |
639 return; | |
640 } | |
641 | |
642 void | |
643 handle_conditional(locpntr, destpntr, data) | |
644 char **locpntr, **destpntr; | |
645 W_Event *data; | |
646 { | |
647 (*locpntr)++; | |
648 **destpntr = 0; | |
649 (*destpntr)--; | |
650 if (**destpntr == '0') { | |
651 ignoreConditionalString(locpntr); | |
652 getConditionalString(locpntr, destpntr, data); | |
653 } else { | |
654 getConditionalString(locpntr, destpntr, data); | |
655 ignoreConditionalString(locpntr); | |
656 } | |
657 (*locpntr) += 2; | |
658 while (**destpntr) | |
659 (*destpntr)++; | |
660 return; | |
661 } | |
662 | |
663 void | |
664 ignoreConditionalString(locpntr) | |
665 char **locpntr; | |
666 { | |
667 int depth = 0, breakflag = 0; | |
668 | |
669 while (**locpntr) { | |
670 if (**locpntr == '%') { | |
671 switch (*(*locpntr + 1)) { | |
672 case '!': | |
673 if (!depth) | |
674 breakflag = 1; | |
675 (*locpntr) += 2; | |
676 break; | |
677 case '}': | |
678 if (depth) { | |
679 depth--; | |
680 (*locpntr) += 2; | |
681 } else | |
682 breakflag = 1; | |
683 break; | |
684 case '{': | |
685 depth++; | |
686 (*locpntr) += 2; | |
687 break; | |
688 case '*': | |
689 abortflag = 1; | |
690 return; | |
691 default: | |
692 (*locpntr)++; | |
693 } | |
694 if (breakflag) | |
695 break; | |
696 } else | |
697 (*locpntr)++; | |
698 } | |
699 } | |
700 | |
701 void | |
702 getConditionalString(locpntr, destpntr, data) | |
703 char **locpntr, **destpntr; | |
704 W_Event *data; | |
705 { | |
706 char *dest = *destpntr; | |
707 | |
708 while (**locpntr) { | |
709 if (**locpntr != '%' && **locpntr != '$' && **locpntr) | |
710 *(dest++) = *((*locpntr)++); | |
711 else if (*(*locpntr + 1) == '!') { | |
712 (*locpntr) += 2; | |
713 break; | |
714 } else if (*(*locpntr + 1) == '}') | |
715 break; | |
716 else if (**locpntr == '%') { | |
717 (*locpntr)++; | |
718 handle_special(locpntr, &dest, data); | |
719 while (*(dest++)); | |
720 dest--; | |
721 } else { /* **locpntr must equal '$' */ | |
722 (*locpntr)++; | |
723 handle_dollar(locpntr, &dest, data); | |
724 while (*(dest++)); | |
725 dest--; | |
726 } | |
727 } | |
728 *dest = 0; | |
729 return; | |
730 } | |
731 | |
732 void | |
733 getTestString(buf, locpntr, destpntr, data) | |
734 char *buf, **locpntr, **destpntr; | |
735 W_Event *data; | |
736 { | |
737 char *dest = buf; | |
738 | |
739 if (**locpntr == '%') { | |
740 (*locpntr)++; | |
741 handle_special(locpntr, &buf, data); | |
742 } else if (**locpntr == '$') { | |
743 (*locpntr)++; | |
744 handle_dollar(locpntr, &buf, data); | |
745 } else { | |
746 while (**locpntr != '%' && **locpntr != '$' && **locpntr != '<' && | |
747 **locpntr != '>' && **locpntr != '=' && | |
748 **locpntr) | |
749 *(dest++) = *((*locpntr)++); | |
750 *dest = 0; | |
751 } | |
752 return; | |
753 } | |
754 | |
755 char * | |
756 strtoupper(buf) | |
757 char *buf; | |
758 { | |
759 char *s; | |
760 for (s = buf; *s; s++) | |
761 *s = toupper(*s); | |
762 return buf; | |
763 } | |
764 | |
765 char * | |
766 strtolower(buf) | |
767 char *buf; | |
768 { | |
769 char *s; | |
770 for (s = buf; *s; s++) | |
771 *s = tolower(*s); | |
772 return buf; | |
773 } | |
774 | |
775 /**********************************************************************/ | |
776 | |
777 /* | |
778 start with a $ | |
779 | |
780 field 1: | |
781 (n)earest | |
782 (t)arget | |
783 (s)elf (doesn't have fields 2 and 3) | |
784 (_) ego (has no other fields) | |
785 | |
786 field 2: | |
787 (a)ny | |
788 (t)eammate | |
789 (f)riendly | |
790 (h)ostile | |
791 | |
792 field 3: | |
793 (a)ny | |
794 (u)ser | |
795 (p)lanet (includes asteroids) | |
796 (s)tar | |
797 (n)ebula | |
798 (b)lack hole | |
799 (^) non-planet | |
800 (*) any stellar object | |
801 | |
802 field 4: (optional) NYI | |
803 (U)ppercase | |
804 (C)apitalize | |
805 (L)owercase | |
806 | |
807 field 5: | |
808 full (n)ame (Hammor, Thought) | |
809 (i)dentifier (e.g. R5, Ka, Can, Sco) | |
810 (#) number (0-9a-z for players, %d for planets) | |
811 (t)eam name (Romulan) | |
812 (s)hort team id (ROM) | |
813 (l)etter of team (R) | |
814 (a)rmies | |
815 (@) sector | |
816 (A)rable, 0=not arable, 1=arable but not AGRI, 2=AGRI | |
817 (M)etal, 0, 1, 2(repair), or 3(sy) | |
818 (D)ilithium, 0, 1 or 2(fuel) | |
819 | |
820 Any implementation of the paradise $ codes (subset or superset) | |
821 must implement and document the $_ code. -- Robert Forsman | |
822 */ | |
823 | |
824 void | |
825 handle_dollar(locpntr, destpntr, data) | |
826 char **locpntr, **destpntr; | |
827 W_Event *data; | |
828 { | |
829 char *buf = *destpntr; | |
830 struct id *target; | |
831 char ch = *((*locpntr)++); | |
832 W_Window w; | |
833 int x, y; | |
834 int flags; | |
835 int capitalize = 0; | |
836 | |
837 buf[0] = 0; | |
838 | |
839 if (ch == '_') { | |
840 strcpy(buf, "Paradise netrek $ codes are orthogonal and make sense."); | |
841 while (**destpntr) | |
842 (*destpntr)++; | |
843 return; | |
844 } if (ch == 's') { | |
845 target = getTargetID((W_Window) 0, me->p_x, me->p_y, TARG_PLAYER | TARG_SELF); | |
846 } else { | |
847 switch (tolower(ch)) { | |
848 case 'n': | |
849 w = 0; | |
850 x = me->p_x; | |
851 y = me->p_y; | |
852 break; | |
853 case 't': | |
854 w = data->Window; | |
855 x = data->x; | |
856 y = data->y; | |
857 break; | |
858 default: | |
859 printf("Invalid $ code field 1 : `%c'\n", ch); | |
860 return; | |
861 } | |
862 | |
863 ch = *((*locpntr)++); | |
864 switch (tolower(ch)) { | |
865 case 'a': | |
866 flags = 0; | |
867 break; | |
868 case 't': | |
869 flags = TARG_TEAM; | |
870 break; | |
871 case 'f': | |
872 flags = TARG_FRIENDLY; | |
873 break; | |
874 case 'h': | |
875 flags = TARG_ENEMY; | |
876 break; | |
877 default: | |
878 printf("Invalid $ code field 2 : `%c'\n", ch); | |
879 return; | |
880 } | |
881 | |
882 ch = *((*locpntr)++); | |
883 switch (tolower(ch)) { | |
884 case 'a': | |
885 flags |= TARG_PLAYER | TARG_ASTRAL; | |
886 break; | |
887 case 'u': | |
888 flags |= TARG_PLAYER; | |
889 break; | |
890 case 'p': | |
891 flags |= TARG_PLANET; | |
892 break; | |
893 case 's': | |
894 flags |= TARG_STAR; | |
895 break; | |
896 case 'n': | |
897 flags |= TARG_NEBULA; | |
898 break; | |
899 case 'b': | |
900 flags |= TARG_BLACKHOLE; | |
901 break; | |
902 case '^': | |
903 flags |= (TARG_ASTRAL & ~TARG_PLANET); | |
904 /* fall through */ | |
905 case '*': | |
906 flags |= TARG_PLANET; | |
907 break; | |
908 default: | |
909 printf("Invalid $ code field 3 : `%c'\n", ch); | |
910 return; | |
911 } | |
912 | |
913 target = getTargetID(w, x, y, flags); | |
914 } | |
915 | |
916 ch = tolower(*((*locpntr)++)); | |
917 if (ch == 'l') | |
918 capitalize = -1; | |
919 else if (ch == 'c') | |
920 capitalize = 1; | |
921 else if (ch == 'u') | |
922 capitalize = 2; | |
923 else | |
924 (*locpntr)--; /* oops, back up and try again */ | |
925 | |
926 ch = *((*locpntr)++); | |
927 | |
928 switch (ch) { | |
929 case 'n': | |
930 strcpy(buf, target->name); | |
931 break; | |
932 case 'i': | |
933 /* if (target->type == PLANETTYPE) {*/ | |
934 strcpy(buf, target->mapstring); | |
935 /* | |
936 } else { | |
937 buf[0] = target->mapstring[1]; | |
938 buf[1] = 0; | |
939 }*/ | |
940 break; | |
941 case '#': | |
942 if (target->type == PLANETTYPE) { | |
943 sprintf(buf, "%d", target->number); | |
944 } else { | |
945 buf[0] = target->mapstring[1]; | |
946 buf[1] = 0; | |
947 } | |
948 break; | |
949 case 't': | |
950 strcpy(buf, teaminfo[target->team].name); | |
951 break; | |
952 case 's': | |
953 strcpy(buf, teaminfo[target->team].shortname); | |
954 break; | |
955 case 'l': | |
956 buf[0] = teaminfo[target->team].letter; | |
957 buf[1] = 0; | |
958 break; | |
959 case 'a': | |
960 sprintf(buf, "%d", (target->type == PLANETTYPE) ? | |
961 planets[target->number].pl_armies : | |
962 players[target->number].p_armies); | |
963 break; | |
964 case '@': | |
965 if (!paradise) | |
966 break; | |
967 if (target->type == PLANETTYPE) { | |
968 x = planets[target->number].pl_x; | |
969 y = planets[target->number].pl_y; | |
970 } else { | |
971 x = players[target->number].p_x; | |
972 y = players[target->number].p_y; | |
973 } | |
974 sprintf(buf, "%d-%d", x / GRIDSIZE + 1, y / GRIDSIZE + 1); | |
975 break; | |
976 case 'A': /* Arable or AGRI */ | |
977 buf[0] = '0'; | |
978 if (target->type == PLANETTYPE) { | |
979 if (planets[target->number].pl_flags & PLARABLE) | |
980 buf[0] = '1'; | |
981 if (planets[target->number].pl_flags & PLAGRI) | |
982 buf[0] = '2'; | |
983 } | |
984 buf[1] = 0; | |
985 break; | |
986 case 'M': /* Metal, Repair, or SY */ | |
987 buf[0] = '0'; | |
988 if (target->type == PLANETTYPE) { | |
989 if (planets[target->number].pl_flags & PLMETAL) | |
990 buf[0] = '1'; | |
991 if (planets[target->number].pl_flags & PLREPAIR) | |
992 buf[0] = '2'; | |
993 if (planets[target->number].pl_flags & PLSHIPYARD) | |
994 buf[0] = '3'; | |
995 } | |
996 buf[1] = 0; | |
997 break; | |
998 case 'D': /* Dilythium or Fuel */ | |
999 buf[0] = '0'; | |
1000 if (target->type == PLANETTYPE) { | |
1001 if (planets[target->number].pl_flags & PLDILYTH) | |
1002 buf[0] = '1'; | |
1003 if (planets[target->number].pl_flags & PLFUEL) | |
1004 buf[0] = '2'; | |
1005 } | |
1006 buf[1] = 0; | |
1007 break; | |
1008 default: | |
1009 printf("Invalid $ code field 4 : `%c'\n", ch); | |
1010 return; | |
1011 } | |
1012 | |
1013 if (capitalize < 0) { | |
1014 char *s; | |
1015 for (s = buf; *s; s++) | |
1016 *s = tolower(*s); | |
1017 } else if (capitalize > 1) { | |
1018 char *s; | |
1019 for (s = buf; *s; s++) | |
1020 *s = toupper(*s); | |
1021 } else if (capitalize) { | |
1022 char *s; | |
1023 s = buf; | |
1024 *s = toupper(*s); | |
1025 for (s++; *s; s++) | |
1026 *s = tolower(*s); | |
1027 } | |
1028 while (**destpntr) | |
1029 (*destpntr)++; | |
1030 return; | |
1031 } | |
1032 #endif /* MACROS */ |