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=&macrotable[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 */