6
|
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 }
|