Mercurial > ~darius > hgwebdir.cgi > paradise_server
comparison src/rmove.c @ 6:8c6d5731234d
First entry of Paradise Server 2.9 patch 10 Beta
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:04 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:054275999194 | 6:8c6d5731234d |
---|---|
1 /*-------------------------------------------------------------------------- | |
2 NETREK II -- Paradise | |
3 | |
4 Permission to use, copy, modify, and distribute this software and its | |
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL | |
6 purpose and without fee is hereby granted, provided that this copyright | |
7 notice appear in all copies. No representations are made about the | |
8 suitability of this software for any purpose. This software is provided | |
9 "as is" without express or implied warranty. | |
10 | |
11 Xtrek Copyright 1986 Chris Guthrie | |
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith | |
13 Scott Silvey | |
14 Paradise II (Netrek II) Copyright 1993 Larry Denys | |
15 Kurt Olsen | |
16 Brandon Gillespie | |
17 --------------------------------------------------------------------------*/ | |
18 | |
19 #include "config.h" | |
20 #include <stdio.h> | |
21 #include <signal.h> | |
22 #include <math.h> | |
23 #include "defs.h" | |
24 #include "struct.h" | |
25 #include "data.h" | |
26 #include "weapons.h" | |
27 #include "shmem.h" | |
28 | |
29 #define SIZEOF(s) (sizeof (s) / sizeof (*(s))) | |
30 #define AVOID_TIME 4 | |
31 #define AVOID_CLICKS 200 | |
32 | |
33 #define BOREDOM_TIME 1200 /* 10 minutes since last torp fired | |
34 * => become hostile to all 4/13/92 | |
35 * TC */ | |
36 | |
37 #define AVOID_STAR 8000 /* Distance from star within which collision | |
38 * avoidance is invoked. - MAK, 16-Jun-93 */ | |
39 #define AVOID_MELT 2000 /* Distance from star within which collision | |
40 * prevention is invoked. - MAK, 16-Jun-93 */ | |
41 | |
42 #define NORMALIZE(d) (((d) + 256) % 256) | |
43 | |
44 #define E_INTRUDER 0x01 | |
45 #define E_TSHOT 0x02 | |
46 #define E_PSHOT 0x04 | |
47 #define E_TRACT 0x08 | |
48 #define NOENEMY (struct Enemy *) -1 | |
49 | |
50 struct Enemy | |
51 { | |
52 int e_info; | |
53 int e_dist; | |
54 unsigned char e_course; /* course to enemy */ | |
55 unsigned char e_edir; /* enemy's current heading */ | |
56 unsigned char e_tcourse; /* torpedo intercept course to enemy */ | |
57 unsigned int e_flags; | |
58 int e_tractor; /* who he's tractoring/pressoring */ | |
59 int e_phrange; /* his phaser range */ | |
60 unsigned int e_hisflags; /* his pflags. bug fix: 6/24/92 TC */ | |
61 }; | |
62 | |
63 static int avoidTime; | |
64 | |
65 #define MESSFUSEVAL 200 /* maint: removed trailing ';' 6/22/92 TC */ | |
66 static int messfuse = MESSFUSEVAL; | |
67 static char rmessage[110]; | |
68 static char tmessage[110]; | |
69 static char *rmessages[] = { | |
70 /* I got bored and actually made it say something: 'DIE SCUM' */ | |
71 "1000100 1001001 1000101 100000 1010011 1000011 1010101 1001101 !" | |
72 "Crush, Kill, DESTROY!!", | |
73 "Run coward!", | |
74 "Hey! Come on you Hoser! I dare you!", | |
75 "Resistance is useless!", | |
76 "Dry up and blow away you weenie!", | |
77 "Go ahead, MAKE MY DAY!", | |
78 "Just hit '<shift> Q' ... and spare both of us the trouble", | |
79 "Is that REALLY you Kurt?", | |
80 "I have you now!", | |
81 "By the way, any last requests?", | |
82 "Dropping your shields is considered a peaceful act.", | |
83 "Drop your shields, and I MAY let you live ...", | |
84 "Don't you have midterms coming up or something?", | |
85 "Ya wanna Tango baby?", | |
86 "Hey! Outta my turf you filthy $t!", | |
87 "I seeeee you...", | |
88 "I claim this space for the $f.", | |
89 "Give up fool ... you're meat.", | |
90 "And another one bites the dust ...", | |
91 "Surrender ... NOW!", | |
92 "Hey! Have you heard about the clever $t? No?.. Me neither.", | |
93 "You have been registered for termination.", | |
94 "This'll teach you to mind your own business!", | |
95 "Man, you stupid $ts never learn!", | |
96 "ALL RIGHT, enough goofing off ... you're toast buster!", | |
97 "You pesky humans just NEVER give up, do you?", | |
98 "You're actually paying money so you can play this game?", | |
99 "My job is to put over-zealous newbies like you out of your misery.", | |
100 "How can you stand to be $T?!? What a hideous life!", | |
101 "All $ts are losers!", | |
102 "$ts all suck. Come join the $f!", | |
103 "The $f shall crush all filthy $ts like you!", | |
104 "TWINK", | |
105 "How can your friends stand to let you live?", | |
106 "Happy, Happy, Joy, Joy." | |
107 }; | |
108 | |
109 char *termie_messages[] = { | |
110 "$n: Hasta la vista, Baby.", | |
111 "Come quietly, or there will be trouble. [thump] [thump]", | |
112 "Make your peace with GOD.", | |
113 "$n: Say your prayers", | |
114 "This galaxy isn't big enough for the two of us, $n.", | |
115 "$n, I have a warrant for your arrest.", | |
116 "$n, self-destruct now.", | |
117 "Coming through. Out of my way.", | |
118 "You feel lucky, punk?", | |
119 "Killing is our business. Business is good.", | |
120 "$n, Die. You have 10 seconds to comply.", | |
121 "You can run $n, but you can't hide!", | |
122 "Sorry, I am out of cool quotes. Just die.", | |
123 "$n: duck." | |
124 }; | |
125 | |
126 extern int debug; | |
127 extern int hostile; | |
128 extern int sticky; | |
129 extern int practice; | |
130 extern int polymorphic; | |
131 | |
132 extern int startplanet; /* CRD feature - MAK, 2-Jun-93 */ | |
133 | |
134 extern int target; /* robotII.c 7/27/91 TC */ | |
135 extern int phrange; /* robotII.c 7/31/91 TC */ | |
136 extern int trrange; /* robotII.c 8/2/91 TC */ | |
137 | |
138 extern int dogslow; /* robotII.c 8/9/91 TC */ | |
139 extern int dogfast; | |
140 extern int runslow; | |
141 extern int runfast; | |
142 extern int closeslow; | |
143 extern int closefast; | |
144 | |
145 unsigned char getcourse(); | |
146 char *robo_message(); | |
147 char *termie_message(); /* added 8/2/91 TC */ | |
148 | |
149 | |
150 extern void (*r_signal()) (); | |
151 #ifndef IRIX | |
152 extern int fprintf(); | |
153 #endif | |
154 extern unsigned int sleep(); | |
155 void exitRobot(); | |
156 extern void move_player(); | |
157 void messAll(); | |
158 int phaser_plasmas(); | |
159 void pmessage2(); | |
160 int do_repair(); | |
161 void go_home(); | |
162 extern int ntorp(); | |
163 extern int repair_off(); | |
164 extern int cloak_off(); | |
165 extern int phaser(); | |
166 extern int angdist(); | |
167 int isTractoringMe(); | |
168 extern int pressor_player(); | |
169 extern int tractor_player(); | |
170 int projectDamage(); | |
171 extern int set_course(); | |
172 extern int cloak_on(); | |
173 extern int shield_up(); | |
174 extern void detothers(); | |
175 extern int shield_down(); | |
176 extern int set_speed(); | |
177 extern int lock_planet(); | |
178 extern int orbit(); | |
179 extern int repair(); | |
180 #ifdef ROBOTSTATS | |
181 extern void save_robot(); | |
182 #endif | |
183 | |
184 void | |
185 rmove() | |
186 { | |
187 register struct player *j; | |
188 register struct planet *l; | |
189 register int i; | |
190 register int burst; | |
191 register int numHits, tDir; | |
192 int avDir; | |
193 extern struct Enemy *get_nearest(); | |
194 struct Enemy *enemy_buf; | |
195 struct player *enemy; | |
196 static int clock = 0; | |
197 static int avoid[2] = {-32, 32}; | |
198 int no_cloak; | |
199 char towhom[80]; | |
200 int timer; | |
201 static int lastTorpped = 0; /* when we last fired a torp 4/13/92 TC */ | |
202 | |
203 clock++; | |
204 /* Check that I'm alive */ | |
205 if (me->p_status == PEXPLODE) | |
206 { | |
207 r_signal(SIGALRM, SIG_IGN); | |
208 if (debug) | |
209 fprintf(stderr, "Robot: Augh! exploding.\n"); | |
210 | |
211 | |
212 /* hack: get rid of robot processes! */ | |
213 | |
214 if (1) | |
215 { | |
216 sleep(3); | |
217 } | |
218 else | |
219 { | |
220 while (me->p_status == PEXPLODE); | |
221 } | |
222 if (debug) | |
223 fprintf(stderr, "Robot: done exploding.\n"); | |
224 if (1) | |
225 { | |
226 sleep(3); | |
227 } | |
228 else | |
229 { | |
230 while (me->p_ntorp > 0); | |
231 } | |
232 if (debug) | |
233 fprintf(stderr, "Robot: torps are gone.\n"); | |
234 exitRobot(); | |
235 } | |
236 if (me->p_status == PDEAD) | |
237 { | |
238 r_signal(SIGALRM, SIG_IGN); | |
239 /* | |
240 * me->p_status = PFREE; move_player(me->p_no, -1,-1, 1); exit(0); | |
241 */ | |
242 exitRobot(); | |
243 } | |
244 /* keep ghostbuster away */ | |
245 me->p_ghostbuster = 0; | |
246 | |
247 timer = 0; | |
248 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) | |
249 { | |
250 if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT)) | |
251 timer = 1; | |
252 } | |
253 if (!timer && !sticky) | |
254 { | |
255 r_signal(SIGALRM, SIG_IGN); | |
256 me->p_status = PFREE; | |
257 move_player(me->p_no, -1, -1, 1); | |
258 exit(0); | |
259 } | |
260 /* if I'm a Terminator, quit if he quits, and quit if he dies and */ | |
261 /* I'm not "sticky" (-s) */ | |
262 | |
263 if (target >= 0) | |
264 { | |
265 if (players[target].p_status == PFREE) | |
266 { /* he went away */ | |
267 me->p_status = PEXPLODE; | |
268 return; | |
269 } | |
270 if ((!sticky) && (players[target].p_status != PALIVE)) | |
271 { /* he died */ | |
272 me->p_status = PEXPLODE; | |
273 return; | |
274 } | |
275 } | |
276 /* | |
277 * If it's been BOREDOM_TIME updates since we fired a torp, become hostile | |
278 * to all races, if we aren't already, and if we're not a practice robot | |
279 * (intended for guardian bots). 4/13/92 TC | |
280 */ | |
281 | |
282 if ((clock - lastTorpped > BOREDOM_TIME) && (!practice) && (!hostile) && | |
283 (me->p_team != 0)) | |
284 { | |
285 messAll("Bored, Bored, Bored."); | |
286 hostile++; | |
287 declare_war(ALLTEAM); | |
288 } | |
289 /* Our first priority is to phaser plasma torps in nearby vicinity... */ | |
290 /* If we fire, we aren't allowed to cloak... */ | |
291 no_cloak = phaser_plasmas(); | |
292 | |
293 /* Find an enemy */ | |
294 | |
295 enemy_buf = get_nearest(); | |
296 | |
297 if ((enemy_buf != NULL) && (enemy_buf != NOENEMY)) | |
298 { /* Someone to kill */ | |
299 enemy = &players[enemy_buf->e_info]; | |
300 if (((lrand48() % messfuse) == 0) && | |
301 (ihypot(me->p_x - enemy->p_x, me->p_y - enemy->p_y) < 20000)) | |
302 { | |
303 /* change 5/10/21 TC ...neut robots don't message */ | |
304 messfuse = MESSFUSEVAL; | |
305 if (me->p_team != 0) | |
306 { | |
307 sprintf(towhom, " %s->%s", | |
308 twoletters(&players[me->p_no]), | |
309 twoletters(&players[enemy->p_no])); | |
310 pmessage2(robo_message(enemy), enemy->p_no, | |
311 MINDIV, towhom, me->p_no); | |
312 } | |
313 else if (target >= 0) | |
314 { | |
315 /* | |
316 * MAK, 28-Apr-92 - send termie messages only to target | |
317 * messAll(termie_message(enemy)); | |
318 */ | |
319 sprintf(towhom, " %s->%s", | |
320 twoletters(&players[me->p_no]), | |
321 twoletters(&players[enemy->p_no])); | |
322 pmessage2(termie_message(enemy), enemy->p_no, | |
323 MINDIV, towhom, me->p_no); | |
324 } | |
325 } | |
326 else if (--messfuse == 0) | |
327 messfuse = 1; | |
328 timer = 0; | |
329 if (debug) | |
330 fprintf(stderr, "%d) noticed %d\n", me->p_no, enemy_buf->e_info); | |
331 } | |
332 else if (enemy_buf == NOENEMY) | |
333 { /* no more players. wait 1 minute. */ | |
334 if (do_repair()) | |
335 { | |
336 return; | |
337 } | |
338 go_home(0); | |
339 /* | |
340 * if (debug) fprintf(stderr, "%d) No players in game.\n", me->p_no); | |
341 */ | |
342 return; | |
343 } | |
344 else if (enemy_buf == 0) | |
345 { /* no one hostile */ | |
346 /* | |
347 * if (debug) fprintf(stderr, "%d) No hostile players in game.\n", | |
348 * me->p_no); | |
349 */ | |
350 if (do_repair()) | |
351 { | |
352 return; | |
353 } | |
354 go_home(0); | |
355 timer = 0; | |
356 return; | |
357 } | |
358 /* | |
359 * Note a bug in this algorithm: * Once someone dies, he is forgotten. | |
360 * This makes robots particularly easy * to kill on a suicide run, where | |
361 * you aim to where you think he will turn * as you die. Once dead, the | |
362 * robot will ignore you and all of your * active torpedoes! | |
363 */ | |
364 | |
365 /* | |
366 * Algorithm: * We have an enemy. * First priority: shoot at target in | |
367 * range. * Second: Dodge stars, torps, and plasma torps. * Third: Get away | |
368 * if we are damaged. * Fourth: repair. * Fifth: attack. | |
369 */ | |
370 | |
371 /* | |
372 * * If we are a practice robot, we will do all but the second. One * will | |
373 * be modified to shoot poorly and not use phasers. | |
374 */ | |
375 /* Fire weapons!!! */ | |
376 /* | |
377 * get_nearest() has already determined if torpedoes and phasers * will | |
378 * hit. It has also determined the courses which torps and * phasers | |
379 * should be fired. If so we will go ahead and shoot here. * We will lose | |
380 * repair and cloaking for the rest of this interrupt. * if we fire here. | |
381 */ | |
382 | |
383 if (practice) | |
384 { | |
385 no_cloak = 1; | |
386 if (enemy_buf->e_flags & E_TSHOT) | |
387 { | |
388 /* | |
389 * if (debug) fprintf(stderr, "%d) firing torps\n", me->p_no); | |
390 */ | |
391 for (burst = 0; (burst < 3) && (me->p_ntorp < MAXTORP); burst++) | |
392 { | |
393 ntorp(enemy_buf->e_tcourse, TMOVE); | |
394 } | |
395 } | |
396 } | |
397 else | |
398 { | |
399 if (enemy_buf->e_flags & E_TSHOT) | |
400 { | |
401 /* | |
402 * if (debug) fprintf(stderr, "%d) firing torps\n", me->p_no); | |
403 */ | |
404 for (burst = 0; (burst < 2) && (me->p_ntorp < MAXTORP); burst++) | |
405 { | |
406 repair_off(); | |
407 cloak_off(); | |
408 ntorp(enemy_buf->e_tcourse, TMOVE); /* was TSTRAIGHT 8/9/91 TC */ | |
409 no_cloak++; | |
410 lastTorpped = clock; /* record time of firing 4/13/92 TC */ | |
411 } | |
412 } | |
413 if (enemy_buf->e_flags & E_PSHOT) | |
414 { | |
415 /* | |
416 * if (debug) fprintf(stderr, "%d) phaser firing\n", me->p_no); | |
417 */ | |
418 no_cloak++; | |
419 repair_off(); | |
420 cloak_off(); | |
421 phaser(enemy_buf->e_course); | |
422 } | |
423 } | |
424 | |
425 /* auto pressor 7/27/91 TC */ | |
426 /* tractor/pressor rewritten on 5/1/92... glitches galore :-| TC */ | |
427 | |
428 /* | |
429 * whoa, too close for comfort, or he's tractoring me, or headed in for me, | |
430 * or I'm hurt | |
431 */ | |
432 | |
433 /* a little tuning -- 0.8 on phrange and +/- 90 degrees in for pressor */ | |
434 | |
435 /* | |
436 * pressor_player(-1); this didn't do anything before, so we'll let the | |
437 * pressors disengage by themselves 5/1/92 TC | |
438 */ | |
439 if (enemy_buf->e_flags & E_TRACT) | |
440 { /* if pressorable */ | |
441 if (((enemy_buf->e_dist < 0.8 * enemy_buf->e_phrange) && | |
442 (angdist(enemy_buf->e_edir, enemy_buf->e_course) > 64)) || | |
443 (isTractoringMe(enemy_buf)) || | |
444 (me->p_damage > 0)) | |
445 { | |
446 if (!(enemy->p_flags & PFCLOAK)) | |
447 { | |
448 if (debug) | |
449 fprintf(stderr, "%d) pressoring %d\n", me->p_no, | |
450 enemy_buf->e_info); | |
451 pressor_player(enemy->p_no); | |
452 no_cloak++; | |
453 repair_off(); | |
454 cloak_off(); | |
455 } | |
456 } | |
457 } | |
458 /* auto tractor 7/31/91 TC */ | |
459 | |
460 /* tractor if not pressoring and... */ | |
461 | |
462 /* tractor if: in range, not too close, and not headed +/- 90 degrees */ | |
463 /* of me, and I'm not hurt */ | |
464 | |
465 if ((!(me->p_flags & PFPRESS)) && | |
466 (enemy_buf->e_flags & E_TRACT) && | |
467 (angdist(enemy_buf->e_edir, enemy_buf->e_course) < 64) && | |
468 (enemy_buf->e_dist > 0.7 * enemy_buf->e_phrange)) | |
469 { | |
470 if (!(me->p_flags & PFTRACT)) | |
471 { | |
472 if (debug) | |
473 fprintf(stderr, "%d) tractoring %d\n", me->p_no, | |
474 enemy_buf->e_info); | |
475 tractor_player(enemy->p_no); | |
476 no_cloak++; | |
477 } | |
478 } | |
479 else | |
480 tractor_player(-1); /* otherwise don't tractor */ | |
481 | |
482 /* Avoid stars - MAK, 16-Jun-93 */ | |
483 /* | |
484 * This section of code allows robots to avoid crashing into stars. Within | |
485 * a specific range (AVOID_STAR), they will check to see if their current | |
486 * course will take them close to the star. If so, course will be adjusted | |
487 * to avoid the star. Within a smaller range (AVOID_MELT), course is | |
488 * adjusted directly away from the star. Collision avoidance is all they | |
489 * will do for this round, other than shooting. | |
490 */ | |
491 for (i = 0, l = &planets[0]; i < NUMPLANETS; i++, l++) | |
492 { | |
493 if (PL_TYPE(*l) == PLSTAR) | |
494 { | |
495 int dx, dy, stardir, newcourse = -1; | |
496 dx = ABS(l->pl_x - me->p_x); | |
497 dy = ABS(l->pl_y - me->p_y); | |
498 /* Avoid over box rather than circle to speed calculations */ | |
499 if (dx < AVOID_STAR && dy < AVOID_STAR) | |
500 { | |
501 stardir = getcourse(l->pl_x, l->pl_y); | |
502 | |
503 if (dx < AVOID_MELT && dy < AVOID_MELT) | |
504 { | |
505 /* Emergency! Way too close! */ | |
506 newcourse = NORMALIZE(stardir - 128); | |
507 if (debug) | |
508 { | |
509 fprintf(stderr, "Steering away from star %s, dir = %d\n", | |
510 l->pl_name, newcourse); | |
511 } | |
512 } | |
513 else if (angdist(me->p_dir, stardir) < 16) | |
514 { | |
515 /* Heading towards star, so adjust course. */ | |
516 newcourse = | |
517 NORMALIZE((me->p_dir < stardir) ? stardir - 32 : stardir + 32); | |
518 if (debug) | |
519 { | |
520 fprintf(stderr, "Adjusting course away from star %s, dir = %d\n", | |
521 l->pl_name, newcourse); | |
522 } | |
523 } | |
524 if (newcourse != -1) | |
525 { /* Change course and speed */ | |
526 me->p_desdir = newcourse; | |
527 if (angdist(me->p_desdir, me->p_dir) > 64) | |
528 me->p_desspeed = dogslow; | |
529 else | |
530 me->p_desspeed = dogfast; | |
531 return; | |
532 } | |
533 } | |
534 } | |
535 } | |
536 | |
537 /* Avoid torps */ | |
538 /* | |
539 * This section of code allows robots to avoid torps. * Within a specific | |
540 * range they will check to see if * any of the 'closest' enemies torps | |
541 * will hit them. * If so, they will evade for four updates. * Evading is | |
542 * all they will do for this round, other than shooting. | |
543 */ | |
544 | |
545 if (!practice) | |
546 { | |
547 if ((enemy->p_ntorp < 5)) | |
548 { | |
549 if ((enemy_buf->e_dist < 15000) || (avoidTime > 0)) | |
550 { | |
551 numHits = projectDamage(enemy->p_no, &avDir); | |
552 if (debug) | |
553 { | |
554 /* | |
555 * fprintf(stderr, "%d hits expected from %d from dir = %d\n", | |
556 * numHits, enemy->p_no, avDir); | |
557 */ | |
558 } | |
559 if (numHits == 0) | |
560 { | |
561 if (--avoidTime > 0) | |
562 { /* we may still be avoiding */ | |
563 if (angdist(me->p_desdir, me->p_dir) > 64) | |
564 me->p_desspeed = dogslow; | |
565 else | |
566 me->p_desspeed = dogfast; | |
567 return; | |
568 } | |
569 } | |
570 else | |
571 { | |
572 /* Actually avoid Torps */ | |
573 avoidTime = AVOID_TIME; | |
574 tDir = avDir - me->p_dir; | |
575 /* put into 0->255 range */ | |
576 tDir = NORMALIZE(tDir); | |
577 if (debug) | |
578 fprintf(stderr, "mydir = %d avDir = %d tDir = %d q = %d\n", | |
579 me->p_dir, avDir, tDir, tDir / 64); | |
580 switch (tDir / 64) | |
581 { | |
582 case 0: | |
583 case 1: | |
584 set_course(NORMALIZE(avDir + 64)); | |
585 break; | |
586 case 2: | |
587 case 3: | |
588 set_course(NORMALIZE(avDir - 64)); | |
589 break; | |
590 } | |
591 if (!no_cloak) | |
592 cloak_on(); | |
593 | |
594 if (angdist(me->p_desdir, me->p_dir) > 64) | |
595 me->p_desspeed = dogslow; | |
596 else | |
597 me->p_desspeed = dogfast; | |
598 | |
599 shield_up(); | |
600 detothers(); /* hmm */ | |
601 if (debug) | |
602 fprintf(stderr, "evading to dir = %d\n", me->p_desdir); | |
603 return; | |
604 } | |
605 } | |
606 } | |
607 /* | |
608 * Trying another scheme. * Robot will keep track of the number of torps | |
609 * a player has * launched. If they are greater than say four, the robot | |
610 * will * veer off immediately. Seems more humanlike to me. | |
611 */ | |
612 | |
613 else if (enemy_buf->e_dist < 15000) | |
614 { | |
615 if (--avoidTime > 0) | |
616 { /* we may still be avoiding */ | |
617 if (angdist(me->p_desdir, me->p_dir) > 64) | |
618 me->p_desspeed = dogslow; | |
619 else | |
620 me->p_desspeed = dogfast; | |
621 return; | |
622 } | |
623 if (lrand48() % 2) | |
624 { | |
625 me->p_desdir = NORMALIZE(enemy_buf->e_course - 64); | |
626 avoidTime = AVOID_TIME; | |
627 } | |
628 else | |
629 { | |
630 me->p_desdir = NORMALIZE(enemy_buf->e_course + 64); | |
631 avoidTime = AVOID_TIME; | |
632 } | |
633 if (angdist(me->p_desdir, me->p_dir) > 64) | |
634 me->p_desspeed = dogslow; | |
635 else | |
636 me->p_desspeed = dogfast; | |
637 shield_up(); | |
638 return; | |
639 } | |
640 } | |
641 /* Run away */ | |
642 /* | |
643 * The robot has taken damage. He will now attempt to run away from * the | |
644 * closest player. This obviously won't do him any good if there * is | |
645 * another player in the direction he wants to go. * Note that the robot | |
646 * will not run away if he dodged torps, above. * The robot will lower his | |
647 * shields in hopes of repairing some damage. | |
648 */ | |
649 | |
650 #define STARTDELTA 5000 /* ships appear +/- delta of home planet */ | |
651 | |
652 if (me->p_damage > 0 && enemy_buf->e_dist < 13000) | |
653 { | |
654 if (me->p_etemp > 900) /* 90% of 1000 */ | |
655 me->p_desspeed = runslow; | |
656 else | |
657 me->p_desspeed = runfast; | |
658 if (!no_cloak) | |
659 cloak_on(); | |
660 repair_off(); | |
661 shield_down(); | |
662 set_course(enemy_buf->e_course - 128); | |
663 if (debug) | |
664 fprintf(stderr, "%d(%d)(%d/%d) running from %s %16s damage (%d/%d) dist %d\n", | |
665 me->p_no, | |
666 (int) me->p_kills, | |
667 me->p_damage, | |
668 me->p_shield, | |
669 twoletters(enemy), | |
670 enemy->p_login, | |
671 enemy->p_damage, | |
672 enemy->p_shield, | |
673 enemy_buf->e_dist); | |
674 return; | |
675 } | |
676 /* Repair if necessary (we are safe) */ | |
677 /* | |
678 * The robot is safely away from players. It can now repair in peace. * It | |
679 * will try to do so now. | |
680 */ | |
681 | |
682 if (do_repair()) | |
683 { | |
684 return; | |
685 } | |
686 /* Attack. */ | |
687 /* | |
688 * The robot has nothing to do. It will check and see if the nearest * | |
689 * enemy fits any of its criterion for attack. If it does, the robot * | |
690 * will speed in and deliver a punishing blow. (Well, maybe) | |
691 */ | |
692 | |
693 if ((enemy_buf->e_flags & E_INTRUDER) || (enemy_buf->e_dist < 15000) | |
694 || (hostile)) | |
695 { | |
696 if ((!no_cloak) && (enemy_buf->e_dist < 10000)) | |
697 cloak_on(); | |
698 shield_up(); | |
699 if (debug) | |
700 fprintf(stderr, "%d(%d)(%d/%d) attacking %s %16s damage (%d/%d) dist %d\n", | |
701 me->p_no, | |
702 (int) me->p_kills, | |
703 me->p_damage, | |
704 me->p_shield, | |
705 twoletters(enemy), | |
706 enemy->p_login, | |
707 enemy->p_damage, | |
708 enemy->p_shield, | |
709 enemy_buf->e_dist); | |
710 | |
711 if (enemy_buf->e_dist < 15000) | |
712 { | |
713 set_course(enemy_buf->e_course + | |
714 avoid[(clock / AVOID_CLICKS) % SIZEOF(avoid)]); | |
715 if (angdist(me->p_desdir, me->p_dir) > 64) | |
716 set_speed(closeslow, 1); | |
717 else | |
718 set_speed(closefast, 1); | |
719 } | |
720 else | |
721 { | |
722 me->p_desdir = enemy_buf->e_course; | |
723 if (angdist(me->p_desdir, me->p_dir) > 64) | |
724 set_speed(closeslow, 1); | |
725 if (target >= 0) /* 7/27/91 TC */ | |
726 set_speed(12, 1); | |
727 else if (me->p_etemp > 900) /* 90% of 1000 */ | |
728 set_speed(runslow, 1); | |
729 else | |
730 set_speed(runfast, 1); | |
731 } | |
732 } | |
733 else | |
734 { | |
735 go_home(enemy_buf); | |
736 } | |
737 } | |
738 | |
739 unsigned char | |
740 getcourse(x, y) | |
741 int x, y; | |
742 { | |
743 return ((unsigned char) (int) (atan2((double) (x - me->p_x), | |
744 (double) (me->p_y - y)) / 3.14159 * 128.)); | |
745 } | |
746 | |
747 /* the 100000's here were once GWIDTHs... */ | |
748 struct | |
749 { | |
750 int x; | |
751 int y; | |
752 } center[] = | |
753 { | |
754 { | |
755 | |
756 100000 / 2, 100000 / 2 | |
757 }, /* change 5/20/91 TC was {0,0} */ | |
758 { | |
759 100000 / 4, 100000 * 3 / 4 | |
760 }, /* Fed */ | |
761 { | |
762 100000 / 4, 100000 / 4 | |
763 }, /* Rom */ | |
764 { | |
765 0, 0 | |
766 }, | |
767 { | |
768 100000 *3 / 4, 100000 / 4 | |
769 } , /* Kli */ | |
770 { | |
771 0, 0 | |
772 } , | |
773 { | |
774 0, 0 | |
775 } , | |
776 { | |
777 0, 0 | |
778 } , | |
779 { | |
780 100000 *3 / 4, 100000 * 3 / 4 | |
781 } | |
782 }; /* Ori */ | |
783 | |
784 /* | |
785 * This function means that the robot has nothing better to do. If there are | |
786 * hostile players in the game, it will try to get as close to them as it | |
787 * can, while staying in its own space. Otherwise, it will head to the center | |
788 * of its own space. | |
789 */ | |
790 /* CRD feature: robots now hover near their start planet - MAK, 2-Jun-93 */ | |
791 | |
792 #define GUARDDIST 8000 | |
793 | |
794 void | |
795 go_home(ebuf) | |
796 struct Enemy *ebuf; | |
797 { | |
798 int x, y; | |
799 double dx, dy; | |
800 struct player *j; | |
801 | |
802 if (ebuf == 0) | |
803 { /* No enemies */ | |
804 /* | |
805 * if (debug) fprintf(stderr, "%d) No enemies\n", me->p_no); | |
806 */ | |
807 if (target >= 0) | |
808 { | |
809 /* First priority, current target (if any) */ | |
810 j = &players[target]; | |
811 x = j->p_x; | |
812 y = j->p_y; | |
813 } | |
814 else if (startplanet == -1) | |
815 { | |
816 /* No start planet, so go to center of galaxy */ | |
817 x = (GWIDTH / 2); | |
818 y = (GWIDTH / 2); | |
819 } | |
820 else | |
821 { | |
822 /* Return to start planet */ | |
823 x = planets[startplanet].pl_x + (lrand48() % 2000) - 1000; | |
824 y = planets[startplanet].pl_y + (lrand48() % 2000) - 1000; | |
825 } | |
826 } | |
827 else | |
828 { /* Let's get near him */ | |
829 j = &players[ebuf->e_info]; | |
830 x = j->p_x; | |
831 y = j->p_y; | |
832 | |
833 if (startplanet != -1) | |
834 { | |
835 /* Get between enemy and planet */ | |
836 int px, py; | |
837 double theta; | |
838 | |
839 px = planets[startplanet].pl_x; | |
840 py = planets[startplanet].pl_y; | |
841 theta = atan2((double) (y - py), (double) (x - px)); | |
842 x = px + GUARDDIST * cos(theta); | |
843 y = py + GUARDDIST * sin(theta); | |
844 } | |
845 } | |
846 /* | |
847 * if (debug) fprintf(stderr, "%d) moving towards (%d/%d)\n", me->p_no, x, | |
848 * y); | |
849 */ | |
850 | |
851 /* | |
852 * Note that I've decided that robots should never stop moving. * It makes | |
853 * them too easy to kill | |
854 */ | |
855 | |
856 me->p_desdir = getcourse(x, y); | |
857 if (angdist(me->p_desdir, me->p_dir) > 64) | |
858 set_speed(dogslow, 1); | |
859 else if (me->p_etemp > 900) /* 90% of 1000 */ | |
860 set_speed(runslow, 1); | |
861 else | |
862 { | |
863 dx = x - me->p_x; | |
864 dy = y - me->p_y; | |
865 set_speed((ihypot((int) dx, (int) dy) / 5000) + 3, 1); | |
866 } | |
867 cloak_off(); | |
868 } | |
869 | |
870 int | |
871 phaser_plasmas() | |
872 { | |
873 register struct plasmatorp *pt; | |
874 register int i; | |
875 int myphrange; | |
876 | |
877 myphrange = phrange; /* PHASEDIST * me->p_ship.s_phaserdamage / | |
878 * 100; */ | |
879 for (i = 0, pt = &plasmatorps[0]; i < MAXPLASMA * MAXPLAYER; i++, pt++) | |
880 { | |
881 if (pt->pt_status != PTMOVE) | |
882 continue; | |
883 if (i == me->p_no) | |
884 continue; | |
885 if (!(pt->pt_war & me->p_team) && !(me->p_hostile & pt->pt_team)) | |
886 continue; | |
887 if (abs(pt->pt_x - me->p_x) > myphrange) | |
888 continue; | |
889 if (abs(pt->pt_y - me->p_y) > myphrange) | |
890 continue; | |
891 if (ihypot(pt->pt_x - me->p_x, pt->pt_y - me->p_y) > myphrange) | |
892 continue; | |
893 repair_off(); | |
894 cloak_off(); | |
895 phaser(getcourse(pt->pt_x, pt->pt_y)); | |
896 return 1; /* was this missing? 3/25/92 TC */ | |
897 break; | |
898 } | |
899 return 0; /* was this missing? 3/25/92 TC */ | |
900 } | |
901 | |
902 int | |
903 projectDamage(eNum, dirP) | |
904 int eNum; | |
905 int *dirP; | |
906 { | |
907 register int i, j, numHits = 0, mx, my, tx, ty, dx, dy; | |
908 double tdx, tdy, mdx, mdy; | |
909 register struct torp *t; | |
910 | |
911 *dirP = 0; | |
912 for (i = 0, t = &torps[eNum * MAXTORP]; i < MAXTORP; i++, t++) | |
913 { | |
914 if (t->t_status == TFREE) | |
915 continue; | |
916 tx = t->t_x; | |
917 ty = t->t_y; | |
918 mx = me->p_x; | |
919 my = me->p_y; | |
920 tdx = (double) t->t_speed * Cos[t->t_dir] * WARP1; | |
921 tdy = (double) t->t_speed * Sin[t->t_dir] * WARP1; | |
922 mdx = (double) me->p_speed * Cos[me->p_dir] * WARP1; | |
923 mdy = (double) me->p_speed * Sin[me->p_dir] * WARP1; | |
924 for (j = t->t_fuse; j > 0; j--) | |
925 { | |
926 tx += tdx; | |
927 ty += tdy; | |
928 mx += mdx; | |
929 my += mdy; | |
930 dx = tx - mx; | |
931 dy = ty - my; | |
932 if (ABS(dx) < EXPDIST && ABS(dy) < EXPDIST) | |
933 { | |
934 numHits++; | |
935 *dirP += t->t_dir; | |
936 break; | |
937 } | |
938 } | |
939 } | |
940 if (numHits > 0) | |
941 *dirP /= numHits; | |
942 return (numHits); | |
943 } | |
944 | |
945 int | |
946 isTractoringMe(enemy_buf) | |
947 struct Enemy *enemy_buf; | |
948 { | |
949 return ((enemy_buf->e_hisflags & PFTRACT) && /* bug fix: was using */ | |
950 !(enemy_buf->e_hisflags & PFPRESS) && /* e_flags 6/24/92 TC */ | |
951 (enemy_buf->e_tractor == me->p_no)); | |
952 } | |
953 | |
954 struct Enemy ebuf; | |
955 | |
956 struct Enemy * | |
957 get_nearest() | |
958 { | |
959 int pcount = 0; | |
960 register int i; | |
961 register struct player *j; | |
962 int intruder = 0; | |
963 int tdist; | |
964 double dx, dy; | |
965 double vxa, vya, l; /* Used for trap shooting */ | |
966 double vxt, vyt; | |
967 double vxs, vys; | |
968 double dp; | |
969 | |
970 /* Find an enemy */ | |
971 ebuf.e_info = me->p_no; | |
972 ebuf.e_dist = GWIDTH + 1; | |
973 | |
974 pcount = 0; /* number of human players in game */ | |
975 | |
976 if (target >= 0) | |
977 { | |
978 j = &players[target]; | |
979 if (!((me->p_swar | me->p_hostile) & j->p_team)) | |
980 declare_war(players[target].p_team); /* make sure we're at war | |
981 * 7/31/91 TC */ | |
982 | |
983 /* We have an enemy */ | |
984 /* Get his range */ | |
985 dx = j->p_x - me->p_x; | |
986 dy = j->p_y - me->p_y; | |
987 tdist = ihypot((int) dx, (int) dy); | |
988 | |
989 if (j->p_status != POUTFIT) | |
990 { /* ignore target if outfitting */ | |
991 ebuf.e_info = target; | |
992 ebuf.e_dist = tdist; | |
993 ebuf.e_flags &= ~(E_INTRUDER); | |
994 } | |
995 /* need a loop to find hostile ships */ | |
996 /* within tactical range */ | |
997 | |
998 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) | |
999 { | |
1000 if ((j->p_status != PALIVE) || (j == me) || | |
1001 ((j->p_flags & PFROBOT) && (!hostile))) | |
1002 continue; | |
1003 else | |
1004 pcount++; /* Other players in the game */ | |
1005 if (((j->p_swar | j->p_hostile) & me->p_team) | |
1006 || ((me->p_swar | me->p_hostile) & j->p_team)) | |
1007 { | |
1008 /* We have an enemy */ | |
1009 /* Get his range */ | |
1010 dx = j->p_x - me->p_x; | |
1011 dy = j->p_y - me->p_y; | |
1012 tdist = ihypot((int) dx, (int) dy); | |
1013 | |
1014 /* if target's teammate is too close, mark as nearest */ | |
1015 | |
1016 if ((tdist < ebuf.e_dist) && (tdist < 15000)) | |
1017 { | |
1018 ebuf.e_info = i; | |
1019 ebuf.e_dist = tdist; | |
1020 ebuf.e_flags &= ~(E_INTRUDER); | |
1021 } | |
1022 } /* end if */ | |
1023 } /* end for */ | |
1024 } | |
1025 else | |
1026 { /* no target */ | |
1027 /* avoid dead slots, me, other robots (which aren't hostile) */ | |
1028 for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) | |
1029 { | |
1030 if ((j->p_status != PALIVE) || (j == me) || | |
1031 ((j->p_flags & PFROBOT) && (!hostile))) | |
1032 continue; | |
1033 else | |
1034 pcount++; /* Other players in the game */ | |
1035 if (((j->p_swar | j->p_hostile) & me->p_team) | |
1036 || ((me->p_swar | me->p_hostile) & j->p_team)) | |
1037 { | |
1038 /* We have an enemy */ | |
1039 /* Get his range */ | |
1040 dx = j->p_x - me->p_x; | |
1041 dy = j->p_y - me->p_y; | |
1042 tdist = ihypot((int) dx, (int) dy); | |
1043 | |
1044 /* Check to see if ship is near our planet. */ | |
1045 if (startplanet != -1) | |
1046 { | |
1047 int px, py; | |
1048 px = planets[startplanet].pl_x; | |
1049 py = planets[startplanet].pl_y; | |
1050 | |
1051 intruder = (ihypot(j->p_x - px, j->p_y - py) | |
1052 < GUARDDIST); | |
1053 } | |
1054 if (tdist < ebuf.e_dist) | |
1055 { | |
1056 ebuf.e_info = i; | |
1057 ebuf.e_dist = tdist; | |
1058 if (intruder) | |
1059 ebuf.e_flags |= E_INTRUDER; | |
1060 else | |
1061 ebuf.e_flags &= ~(E_INTRUDER); | |
1062 } | |
1063 } /* end if */ | |
1064 } /* end for */ | |
1065 } /* end else */ | |
1066 if (pcount == 0) | |
1067 { | |
1068 return (NOENEMY); /* no players in game */ | |
1069 } | |
1070 else if (ebuf.e_info == me->p_no) | |
1071 { | |
1072 return (0); /* no hostile players in the game */ | |
1073 } | |
1074 else | |
1075 { | |
1076 j = &players[ebuf.e_info]; | |
1077 | |
1078 /* Get torpedo course to nearest enemy */ | |
1079 ebuf.e_flags &= ~(E_TSHOT); | |
1080 | |
1081 vxa = (j->p_x - me->p_x); | |
1082 vya = (j->p_y - me->p_y); | |
1083 l = ihypot((int) vxa, (int) vya); /* Normalize va */ | |
1084 if (l != 0) | |
1085 { | |
1086 vxa /= l; | |
1087 vya /= l; | |
1088 } | |
1089 vxs = (Cos[j->p_dir] * j->p_speed) * WARP1; | |
1090 vys = (Sin[j->p_dir] * j->p_speed) * WARP1; | |
1091 dp = vxs * vxa + vys * vya; /* Dot product of (va vs) */ | |
1092 dx = vxs - dp * vxa; | |
1093 dy = vys - dp * vya; | |
1094 l = hypot(dx, dy); /* Determine how much speed is required */ | |
1095 dp = (float) (me->p_ship.s_torp.speed * WARP1); | |
1096 l = (dp * dp - l * l); | |
1097 if (l > 0) | |
1098 { | |
1099 double he_x, he_y, area; | |
1100 | |
1101 /* Only shoot if within distance */ | |
1102 he_x = j->p_x + Cos[j->p_dir] * j->p_speed * 50 * WARP1; | |
1103 he_y = j->p_y + Sin[j->p_dir] * j->p_speed * 50 * WARP1; | |
1104 area = 50 * me->p_ship.s_torp.speed * WARP1; | |
1105 if (ihypot(he_x - me->p_x, he_y - me->p_y) < area) | |
1106 { | |
1107 l = sqrt(l); | |
1108 vxt = l * vxa + dx; | |
1109 vyt = l * vya + dy; | |
1110 ebuf.e_flags |= E_TSHOT; | |
1111 ebuf.e_tcourse = getcourse((int) vxt + me->p_x, (int) vyt + me->p_y); | |
1112 } | |
1113 } | |
1114 /* Get phaser shot status */ | |
1115 if (ebuf.e_dist < 0.8 * phrange) | |
1116 ebuf.e_flags |= E_PSHOT; | |
1117 else | |
1118 ebuf.e_flags &= ~(E_PSHOT); | |
1119 | |
1120 /* Get tractor/pressor status */ | |
1121 if (ebuf.e_dist < trrange) | |
1122 ebuf.e_flags |= E_TRACT; | |
1123 else | |
1124 ebuf.e_flags &= ~(E_TRACT); | |
1125 | |
1126 | |
1127 /* get his phaser range */ | |
1128 ebuf.e_phrange = PHASEDIST * j->p_ship.s_phaser.damage / 100; | |
1129 | |
1130 /* get course info */ | |
1131 ebuf.e_course = getcourse(j->p_x, j->p_y); | |
1132 ebuf.e_edir = j->p_dir; | |
1133 ebuf.e_hisflags = j->p_flags; | |
1134 ebuf.e_tractor = j->p_tractor; | |
1135 /* | |
1136 * if (debug) fprintf(stderr, "Set course to enemy is %d (%d)\n", | |
1137 * (int)ebuf.e_course, (int) ebuf.e_course * 360 / 256); | |
1138 */ | |
1139 | |
1140 /* check to polymorph */ | |
1141 | |
1142 if ((polymorphic) && (j->p_ship.s_type != me->p_ship.s_type) && | |
1143 (j->p_ship.s_type != ATT)) | |
1144 { /* don't polymorph to ATT 4/8/92 TC */ | |
1145 extern int config(); | |
1146 extern int getship(); | |
1147 int old_shield; | |
1148 int old_damage; | |
1149 old_shield = me->p_ship.s_maxshield; | |
1150 old_damage = me->p_ship.s_maxdamage; | |
1151 | |
1152 getship(&(me->p_ship), j->p_ship.s_type); | |
1153 config(); | |
1154 if (me->p_speed > me->p_ship.s_imp.maxspeed) | |
1155 me->p_speed = me->p_ship.s_imp.maxspeed; | |
1156 me->p_shield = (me->p_shield * (float) me->p_ship.s_maxshield) | |
1157 / (float) old_shield; | |
1158 me->p_damage = (me->p_damage * (float) me->p_ship.s_maxdamage) | |
1159 / (float) old_damage; | |
1160 } | |
1161 return (&ebuf); | |
1162 } | |
1163 } | |
1164 | |
1165 struct planet * | |
1166 get_nearest_planet() | |
1167 { | |
1168 register int i; | |
1169 register struct planet *l; | |
1170 register struct planet *nearest; | |
1171 int dist = GWIDTH; /* Manhattan distance to nearest planet */ | |
1172 int ldist; | |
1173 | |
1174 nearest = &planets[0]; | |
1175 for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) | |
1176 { | |
1177 if ((ldist = (abs(me->p_x - l->pl_x) + abs(me->p_y - l->pl_y))) < | |
1178 dist) | |
1179 { | |
1180 dist = ldist; | |
1181 nearest = l; | |
1182 } | |
1183 } | |
1184 return nearest; | |
1185 } | |
1186 | |
1187 int | |
1188 do_repair() | |
1189 { | |
1190 /* Repair if necessary (we are safe) */ | |
1191 | |
1192 register struct planet *l; | |
1193 int dx, dy; | |
1194 int dist; | |
1195 | |
1196 l = get_nearest_planet(); | |
1197 dx = abs(me->p_x - l->pl_x); | |
1198 dy = abs(me->p_y - l->pl_y); | |
1199 | |
1200 if (me->p_damage > 0) | |
1201 { | |
1202 if ((me->p_swar | me->p_hostile) & l->pl_owner) | |
1203 { | |
1204 if (l->pl_armies > 0) | |
1205 { | |
1206 if ((dx < PFIREDIST) && (dy < PFIREDIST)) | |
1207 { | |
1208 if (debug) | |
1209 fprintf(stderr, "%d) on top of hostile planet (%s)\n", me->p_no, l->pl_name); | |
1210 return (0); /* can't repair on top of hostile planets */ | |
1211 } | |
1212 if (ihypot((int) dx, (int) dy) < PFIREDIST) | |
1213 { | |
1214 if (debug) | |
1215 fprintf(stderr, "%d) on top of hostile planet (%s)\n", me->p_no, l->pl_name); | |
1216 return (0); | |
1217 } | |
1218 } | |
1219 me->p_desspeed = 0; | |
1220 } | |
1221 else | |
1222 { /* if friendly */ | |
1223 if ((l->pl_flags & PLREPAIR) && | |
1224 !(me->p_flags & PFORBIT)) | |
1225 { /* oh, repair! */ | |
1226 dist = ihypot((int) dx, (int) dy); | |
1227 | |
1228 if (debug) | |
1229 fprintf(stderr, "%d) locking on to planet %d\n", | |
1230 me->p_no, l->pl_no); | |
1231 cloak_off(); | |
1232 shield_down(); | |
1233 me->p_desdir = getcourse(l->pl_x, l->pl_y); | |
1234 lock_planet(l->pl_no); | |
1235 me->p_desspeed = 4; | |
1236 if (dist - (ORBDIST / 2) < (11500 * me->p_speed * me->p_speed) / | |
1237 me->p_ship.s_imp.dec) | |
1238 { | |
1239 if (me->p_desspeed > 2) | |
1240 { | |
1241 set_speed(2, 1); | |
1242 } | |
1243 } | |
1244 if ((dist < ENTORBDIST) && (me->p_speed <= 2)) | |
1245 { | |
1246 me->p_flags &= ~PFPLLOCK; | |
1247 orbit(); | |
1248 } | |
1249 return (1); | |
1250 } | |
1251 else | |
1252 { /* not repair, so ignore it */ | |
1253 me->p_desspeed = 0; | |
1254 } | |
1255 } | |
1256 shield_down(); | |
1257 if (me->p_speed == 0) | |
1258 repair(); | |
1259 if (debug) | |
1260 fprintf(stderr, "%d) repairing damage at %d\n", | |
1261 me->p_no, | |
1262 me->p_damage); | |
1263 return (1); | |
1264 } | |
1265 else | |
1266 { | |
1267 return (0); | |
1268 } | |
1269 } | |
1270 | |
1271 | |
1272 void | |
1273 pmessage(str, recip, group, address) | |
1274 char *str; | |
1275 int recip; | |
1276 int group; | |
1277 char *address; | |
1278 { | |
1279 pmessage2(str, recip, group, address, 255); | |
1280 } | |
1281 | |
1282 | |
1283 void | |
1284 pmessage2(str, recip, group, address, from) | |
1285 char *str; | |
1286 int recip; | |
1287 int group; | |
1288 char *address; | |
1289 unsigned char from; | |
1290 { | |
1291 struct message *cur; | |
1292 int mesgnum; | |
1293 | |
1294 if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE) | |
1295 { | |
1296 mctl->mc_current = 0; | |
1297 mesgnum = 0; | |
1298 } | |
1299 cur = &messages[mesgnum]; | |
1300 cur->m_no = mesgnum; | |
1301 cur->m_flags = group; | |
1302 cur->m_recpt = recip; | |
1303 cur->m_from = from; | |
1304 (void) sprintf(cur->m_data, "%-9s %s", address, str); | |
1305 cur->m_flags |= MVALID; | |
1306 } | |
1307 | |
1308 | |
1309 char * | |
1310 robo_message(enemy) | |
1311 struct player *enemy; | |
1312 { | |
1313 int i; | |
1314 char *s, *t; | |
1315 | |
1316 i = (lrand48() % (sizeof(rmessages) / sizeof(rmessages[0]))); | |
1317 | |
1318 for (t = rmessages[i], s = rmessage; *t != '\0'; s++, t++) | |
1319 { | |
1320 switch (*t) | |
1321 { | |
1322 case '$': | |
1323 switch (*(++t)) | |
1324 { | |
1325 case '$': | |
1326 *s = *t; | |
1327 break; | |
1328 case 'T': /* "a Fed" or "a Klingon" ... */ | |
1329 if (enemy->p_team != me->p_team && | |
1330 enemy->p_team == ORI) | |
1331 { | |
1332 strcpy(s, "an "); | |
1333 } | |
1334 else | |
1335 { | |
1336 strcpy(s, "a "); | |
1337 } | |
1338 s = s + strlen(s); | |
1339 case 't': /* "Fed" or "Orion" */ | |
1340 if (enemy->p_team != me->p_team) | |
1341 { | |
1342 switch (enemy->p_team) | |
1343 { | |
1344 case FED: | |
1345 strcpy(s, "Fed"); | |
1346 break; | |
1347 case ROM: | |
1348 strcpy(s, "Romulan"); | |
1349 break; | |
1350 case KLI: | |
1351 strcpy(s, "Klingon"); | |
1352 break; | |
1353 case ORI: | |
1354 strcpy(s, "Orion"); | |
1355 break; | |
1356 } | |
1357 } | |
1358 else | |
1359 { | |
1360 strcpy(s, "TRAITOR"); | |
1361 } | |
1362 s = s + strlen(s) - 1; | |
1363 break; | |
1364 case 'f': | |
1365 switch (me->p_team) | |
1366 { | |
1367 case FED: | |
1368 strcpy(s, "Federation"); | |
1369 break; | |
1370 case ROM: | |
1371 strcpy(s, "Romulan empire"); | |
1372 break; | |
1373 case KLI: | |
1374 strcpy(s, "Klingon empire"); | |
1375 break; | |
1376 case ORI: | |
1377 strcpy(s, "Orion empire"); | |
1378 break; | |
1379 } | |
1380 s = s + strlen(s) - 1; | |
1381 break; | |
1382 default: | |
1383 *s = *t; | |
1384 } | |
1385 break; | |
1386 default: | |
1387 *s = *t; | |
1388 break; | |
1389 } | |
1390 } | |
1391 *s = '\0'; | |
1392 return (rmessage); | |
1393 } | |
1394 | |
1395 char * | |
1396 termie_message(enemy) | |
1397 struct player *enemy; | |
1398 { | |
1399 int i; | |
1400 char *s, *t; | |
1401 | |
1402 i = (lrand48() % (sizeof(termie_messages) / sizeof(termie_messages[0]))); | |
1403 | |
1404 for (t = termie_messages[i], s = tmessage; *t != '\0'; s++, t++) | |
1405 { | |
1406 switch (*t) | |
1407 { | |
1408 case '$': | |
1409 switch (*(++t)) | |
1410 { | |
1411 case '$': | |
1412 *s = *t; | |
1413 break; | |
1414 case 'T': /* "a Fed" or "a Klingon" ... */ | |
1415 if (enemy->p_team != me->p_team && | |
1416 enemy->p_team == ORI) | |
1417 { | |
1418 strcpy(s, "an "); | |
1419 } | |
1420 else | |
1421 { | |
1422 strcpy(s, "a "); | |
1423 } | |
1424 s = s + strlen(s); | |
1425 case 't': /* "Fed" or "Orion" */ | |
1426 if (enemy->p_team != me->p_team) | |
1427 { | |
1428 switch (enemy->p_team) | |
1429 { | |
1430 case FED: | |
1431 strcpy(s, "Fed"); | |
1432 break; | |
1433 case ROM: | |
1434 strcpy(s, "Romulan"); | |
1435 break; | |
1436 case KLI: | |
1437 strcpy(s, "Klingon"); | |
1438 break; | |
1439 case ORI: | |
1440 strcpy(s, "Orion"); | |
1441 break; | |
1442 } | |
1443 } | |
1444 else | |
1445 { | |
1446 strcpy(s, "TRAITOR"); | |
1447 } | |
1448 s = s + strlen(s) - 1; | |
1449 break; | |
1450 case 'f': | |
1451 switch (me->p_team) | |
1452 { | |
1453 case FED: | |
1454 strcpy(s, "Federation"); | |
1455 break; | |
1456 case ROM: | |
1457 strcpy(s, "Romulan empire"); | |
1458 break; | |
1459 case KLI: | |
1460 strcpy(s, "Klingon empire"); | |
1461 break; | |
1462 case ORI: | |
1463 strcpy(s, "Orion empire"); | |
1464 break; | |
1465 } | |
1466 s = s + strlen(s) - 1; | |
1467 break; | |
1468 case 'n': /* name 8/2/91 TC */ | |
1469 strcpy(s, enemy->p_name); | |
1470 s = s + strlen(s) - 1; | |
1471 break; | |
1472 default: | |
1473 *s = *t; | |
1474 } | |
1475 break; | |
1476 default: | |
1477 *s = *t; | |
1478 break; | |
1479 } | |
1480 } | |
1481 *s = '\0'; | |
1482 return (tmessage); | |
1483 | |
1484 } | |
1485 | |
1486 void | |
1487 exitRobot() | |
1488 { | |
1489 static char buf[80]; | |
1490 | |
1491 r_signal(SIGALRM, SIG_IGN); | |
1492 if (me != NULL && me->p_team != ALLTEAM) | |
1493 { | |
1494 if (target >= 0) | |
1495 { | |
1496 strcpy(buf, "I'll be back."); | |
1497 messAll(buf); | |
1498 } | |
1499 else | |
1500 { | |
1501 /* | |
1502 * sprintf(buf, "%s %s (%s) leaving the game (%.16s@%.16s)", | |
1503 * ranks[me->p_stats.st_rank].name, me->p_name, me->p_mapchars, | |
1504 * me->p_login, me->p_monitor); messAll(buf); | |
1505 */ | |
1506 } | |
1507 } | |
1508 #ifdef ROBOTSTATS | |
1509 save_robot(); | |
1510 #endif | |
1511 | |
1512 strcpy(buf, me->p_name); | |
1513 /* something about Terminators hangs up the slot when a human */ | |
1514 /* tries to log in on that slot, so... */ | |
1515 memset(me, 0, sizeof(struct player)); /* confusion 8/5/91 TC */ | |
1516 strcpy(me->p_name, buf); | |
1517 | |
1518 /* | |
1519 * me->p_status = PFREE; move_player(me->p_no, -1,-1, 1); | |
1520 */ | |
1521 | |
1522 /* | |
1523 * all right, so zeroing out p_stats.st_tticks has undesireable side | |
1524 * effects when the client tries to compute ratings... | |
1525 */ | |
1526 | |
1527 me->p_stats.st_tticks = 1; /* quick fix 3/15/92 TC */ | |
1528 exit(0); | |
1529 } | |
1530 | |
1531 void | |
1532 messAll(buf) | |
1533 char *buf; /* wasn't K&R before...oops 5/1/92 TC */ | |
1534 { | |
1535 static char addrbuf[20]; | |
1536 | |
1537 sprintf(addrbuf, " %s->ALL", twoletters(me)); | |
1538 pmessage2(buf, 0, MALL, addrbuf, me->p_no); | |
1539 } |