Mercurial > ~darius > hgwebdir.cgi > paradise_server
comparison src/snakemove.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 | |
23 #ifdef apollo | |
24 #include <limits.h> | |
25 #define MAXINT INT_MAX | |
26 #else | |
27 #include <values.h> | |
28 #endif | |
29 | |
30 #include <math.h> | |
31 #include <time.h> | |
32 #include "defs.h" | |
33 #include "struct.h" | |
34 #include "data.h" | |
35 #include "planets.h" | |
36 #include "shmem.h" | |
37 | |
38 #define SYSWIDTH (GWIDTH/5)/* width of a system */ | |
39 | |
40 /* distance on either side of center */ | |
41 #define EYEWIDTH 100 /* 100 */ | |
42 /* which torp the eyes are positioned alongside */ | |
43 #define EYETORP 0 /* 0 */ | |
44 /* angle from EYETORP */ | |
45 #define EYEANGLE 64 /* 64 */ | |
46 #define TORPSEP WARP1*12 | |
47 #define PLANRAD 900 | |
48 #define PLANRATE 16 | |
49 | |
50 /* threshold to avoid galactic boundaries */ | |
51 #define MD 4500 | |
52 /* overlap threshold on team boundaries */ | |
53 #define TMD 2250 | |
54 | |
55 /* how often to check for bombers in cyles (1/10th second) */ | |
56 #define BOMBCHECK 20 | |
57 | |
58 /* how often to check for players in the game in cyles (1/10th second) */ | |
59 #define PLAYERCHECK 100 | |
60 | |
61 #define WARHOSTILE(p) ((((p)->p_swar | (p)->p_hostile)& \ | |
62 perfs[0]->p_team) || ((perfs[0]->p_swar | \ | |
63 perfs[0]->p_hostile) & (p)->p_team)) | |
64 | |
65 #define SNAKETORPDAMAGE 30 | |
66 #define SNAKEPLASMADAMAGE 100 | |
67 | |
68 static struct torp *thead, *eyet, *eyetp; | |
69 static int lx, ly; | |
70 static struct plasmatorp *fl, *fr; | |
71 static int explode, explodetorps, tfuse; | |
72 | |
73 extern struct player *perfs[2]; | |
74 extern int num_perfs; | |
75 extern int debug; | |
76 extern int lastm; | |
77 extern int tno; | |
78 extern int target; | |
79 extern int berserk; | |
80 extern int patrol; | |
81 extern int noSmush; | |
82 extern int plan_guard; /* KAO */ | |
83 extern int planet1, planet2; /* KAO */ | |
84 extern int team1, team2; | |
85 extern int length; | |
86 | |
87 static int plan_count = 0; | |
88 static int s_clock; | |
89 static _move(); | |
90 static int defenders[ALLTEAM]; | |
91 | |
92 struct player *whokilledme(); | |
93 struct planet *homeworld = 0; | |
94 struct planet *homestar = 0; | |
95 | |
96 unsigned char getacourse(); | |
97 extern void (*r_signal()) (); | |
98 | |
99 | |
100 struct planet * | |
101 star_of(pl) | |
102 struct planet *pl; | |
103 { | |
104 int i; | |
105 if (pl->pl_system < 1) | |
106 return 0; | |
107 | |
108 for (i = 0; i < NUMPLANETS; i++) | |
109 { | |
110 if (!(planets[i].pl_flags & PLSTAR)) | |
111 continue; | |
112 if (planets[i].pl_system == pl->pl_system) | |
113 return &planets[i]; | |
114 } | |
115 | |
116 return 0; | |
117 } | |
118 | |
119 | |
120 | |
121 snakemove() | |
122 { | |
123 s_clock++; | |
124 | |
125 _move(); | |
126 } | |
127 | |
128 static | |
129 _move() | |
130 { | |
131 if (!perfs[0] || !perfs[1]) | |
132 exitSnake(); | |
133 | |
134 /* keep ghostbuster away */ | |
135 perfs[0]->p_ghostbuster = 0; | |
136 perfs[1]->p_ghostbuster = 0; | |
137 | |
138 if (s_clock == 5) | |
139 startsnake(); | |
140 else if (s_clock > 5) | |
141 { | |
142 check_explode(); | |
143 if (!explode) | |
144 { | |
145 movesnake(); | |
146 } | |
147 else if ((perfs[0]->p_ntorp == 0 && perfs[1]->p_ntorp == 0 && | |
148 perfs[0]->p_nplasmatorp == 0 && perfs[1]->p_nplasmatorp == 0) || | |
149 /* xx -- sometimes above doesn't work? */ | |
150 s_clock - explode > 56) | |
151 exitSnake(); | |
152 } | |
153 return 1; | |
154 } | |
155 | |
156 startsnake() | |
157 { | |
158 register i, l; | |
159 register struct player *j; | |
160 register struct torp *k; | |
161 struct player *p1 = perfs[0], *p2 = perfs[1]; | |
162 int first = 1; | |
163 int px, py; | |
164 | |
165 for (i = 0; i < NUMPLANETS; i++) | |
166 { | |
167 if (planets[i].pl_flags & PLHOME && planets[i].pl_owner == 1 << tno) | |
168 { | |
169 homeworld = &planets[i]; | |
170 break; | |
171 } | |
172 if (!homeworld && planets[i].pl_owner == 1 << tno) | |
173 homeworld = &planets[i]; | |
174 } | |
175 | |
176 if (!homeworld) | |
177 { | |
178 /* ouch */ | |
179 homeworld = &planets[lrand48() % NUMPLANETS]; | |
180 fprintf(stderr, "snake: My race (%d) has no planets. Picking one at random: %s\n", tno, homeworld->pl_name); | |
181 } | |
182 homestar = star_of(homeworld); | |
183 if (!homestar) | |
184 homestar = homeworld; | |
185 | |
186 px = (lrand48() % 10000) - 5000; | |
187 py = (lrand48() % 10000) - 5000; | |
188 | |
189 p1->p_ntorp = p2->p_ntorp = 0; | |
190 p1->p_nplasmatorp = p2->p_nplasmatorp = 0; | |
191 | |
192 /* body */ | |
193 | |
194 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
195 { | |
196 | |
197 for (l = 0, i = j->p_no * MAXTORP, k = &torps[i]; | |
198 i < j->p_no * MAXTORP + length; i++, k++, l++) | |
199 { | |
200 | |
201 if (l == EYETORP && j == perfs[0]) | |
202 { | |
203 /* eye location */ | |
204 eyet = k; | |
205 } | |
206 if (l == ((EYETORP == 0) ? 1 : (EYETORP - 1)) && j == perfs[0]) | |
207 { | |
208 /* perpendicular torp offset */ | |
209 eyetp = k; | |
210 } | |
211 /* torps are free here */ | |
212 snake_torp(k, i, j); | |
213 /* note: have to be same team for this to work */ | |
214 k->t_x = homeworld->pl_x + px; | |
215 k->t_y = homeworld->pl_y + py - (l + (j == perfs[1] ? length : 0)) * TORPSEP; | |
216 /* | |
217 * if(debug) fprintf(stderr, "k->t_x %d, k->t_y %d\n", k->t_x, k->t_y); | |
218 */ | |
219 if (first) | |
220 { | |
221 thead = k; | |
222 first = 0; | |
223 } | |
224 } | |
225 } | |
226 | |
227 /* eyes */ | |
228 fl = &plasmatorps[perfs[0]->p_no * MAXPLASMA]; | |
229 fl->pt_no = perfs[0]->p_no * MAXPLASMA; | |
230 fl->pt_status = PTMOVE; | |
231 fl->pt_owner = perfs[0]->p_no; | |
232 fl->pt_team = perfs[0]->p_team; | |
233 fl->pt_x = eyet->t_x - EYEWIDTH; | |
234 fl->pt_y = eyet->t_y; | |
235 if (plan_guard == 0) | |
236 fl->pt_damage = SNAKEPLASMADAMAGE; | |
237 else | |
238 fl->pt_damage = SNAKEPLASMADAMAGE * 10; | |
239 fl->pt_speed = 0; | |
240 fl->pt_war = 0; | |
241 fl->pt_fuse = MAXINT; | |
242 fl->pt_turns = 0; | |
243 | |
244 perfs[0]->p_nplasmatorp++; | |
245 | |
246 fr = &plasmatorps[perfs[1]->p_no * MAXPLASMA]; | |
247 fr->pt_no = perfs[1]->p_no * MAXPLASMA; | |
248 fr->pt_status = PTMOVE; | |
249 fr->pt_owner = perfs[1]->p_no; | |
250 fr->pt_team = perfs[1]->p_team; /* doesn't work */ | |
251 fr->pt_x = eyet->t_x + EYEWIDTH; | |
252 fr->pt_y = eyet->t_y; | |
253 fr->pt_damage = SNAKEPLASMADAMAGE; | |
254 fr->pt_speed = 0; | |
255 fr->pt_war = 0; | |
256 fr->pt_fuse = MAXINT; | |
257 fr->pt_turns = 0; | |
258 | |
259 perfs[1]->p_nplasmatorp++; | |
260 | |
261 if (debug) | |
262 fprintf(stderr, "started\n"); | |
263 } | |
264 | |
265 restore_eye() | |
266 { | |
267 if (fl->pt_status != PTMOVE) | |
268 { | |
269 /* eyes */ | |
270 fl = &plasmatorps[perfs[0]->p_no * MAXPLASMA]; | |
271 fl->pt_no = perfs[0]->p_no * MAXPLASMA; | |
272 fl->pt_status = PTMOVE; | |
273 fl->pt_owner = perfs[0]->p_no; | |
274 fl->pt_team = perfs[0]->p_team; | |
275 fl->pt_x = eyet->t_x - EYEWIDTH; | |
276 fl->pt_y = eyet->t_y; | |
277 if (plan_guard == 0) | |
278 fl->pt_damage = SNAKEPLASMADAMAGE; | |
279 else | |
280 fl->pt_damage = SNAKEPLASMADAMAGE * 10; | |
281 fl->pt_speed = 0; | |
282 fl->pt_war = 0; | |
283 fl->pt_fuse = MAXINT; | |
284 fl->pt_turns = 0; | |
285 perfs[0]->p_nplasmatorp++; | |
286 } | |
287 if (fr->pt_status != PTMOVE) | |
288 { | |
289 fr = &plasmatorps[perfs[1]->p_no * MAXPLASMA]; | |
290 fr->pt_no = perfs[1]->p_no * MAXPLASMA; | |
291 fr->pt_status = PTMOVE; | |
292 fr->pt_owner = perfs[1]->p_no; | |
293 fr->pt_team = perfs[1]->p_team; /* doesn't work */ | |
294 fr->pt_x = eyet->t_x + EYEWIDTH; | |
295 fr->pt_y = eyet->t_y; | |
296 fr->pt_damage = SNAKEPLASMADAMAGE; | |
297 fr->pt_speed = 0; | |
298 fr->pt_war = 0; | |
299 fr->pt_fuse = MAXINT; | |
300 fr->pt_turns = 0; | |
301 perfs[1]->p_nplasmatorp++; | |
302 } | |
303 } | |
304 | |
305 movesnake() | |
306 { | |
307 register i, px, py; | |
308 register struct player *j; | |
309 register struct torp *k /* , *prev = thead */ ; | |
310 unsigned char tc; | |
311 struct player *tr; | |
312 static | |
313 int dir = 8; | |
314 int ok; | |
315 | |
316 if ((s_clock % PLAYERCHECK) == 0) | |
317 { | |
318 /* every x seconds make sure there's people in the game */ | |
319 ok = 0; | |
320 defenders[FED] = defenders[ROM] = defenders[KLI] = defenders[ORI] = 0; | |
321 for (i = 0, j = players; i < MAXPLAYER; i++, j++) | |
322 { | |
323 if ((j->p_status != PFREE) && !(j->p_flags & PFROBOT)) | |
324 { | |
325 ok = 1; | |
326 defenders[j->p_team]++; | |
327 } | |
328 } | |
329 if (!ok) | |
330 exitSnake(); | |
331 } | |
332 if (patrol && (target == -1) && (s_clock % BOMBCHECK) == 0) | |
333 { | |
334 target = bombcheck(team1, team2); | |
335 } | |
336 if ((s_clock % (4 + (lrand48() % 4))) == 0) | |
337 dir = -dir; | |
338 | |
339 thead->t_dir += dir + rrnd(8); | |
340 | |
341 if (target > -1) | |
342 { | |
343 tr = &players[target]; | |
344 if (tr->p_status == PALIVE) | |
345 { | |
346 int nd, td; | |
347 tc = getacourse(tr->p_x, tr->p_y, thead->t_x, thead->t_y); | |
348 nd = angdist(thead->t_dir, tc); | |
349 if (nd > 8) | |
350 { | |
351 td = tc + nd; | |
352 if (td == thead->t_dir) | |
353 thead->t_dir -= 8; | |
354 else | |
355 thead->t_dir += 8; | |
356 } | |
357 } | |
358 } | |
359 if (target == -1) | |
360 { | |
361 if (!patrol) | |
362 check_tboundary(ALLTEAM, &thead->t_dir, 8, thead->t_x, thead->t_y); | |
363 else | |
364 check_tboundary(team1 | team2, &thead->t_dir, 8, thead->t_x, thead->t_y); | |
365 } | |
366 lx = thead->t_x; | |
367 ly = thead->t_y; | |
368 | |
369 if (!plan_guard) | |
370 { | |
371 /* NOTE: we aren't letting the daemon move the torp head */ | |
372 thead->t_x += (double) TORPSEP *Cos[thead->t_dir]; | |
373 thead->t_y += (double) TORPSEP *Sin[thead->t_dir]; | |
374 } | |
375 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
376 { | |
377 if (plan_guard) | |
378 { | |
379 int temp; | |
380 thead = &torps[j->p_no * MAXTORP]; | |
381 if (j == perfs[0]) | |
382 temp = planet1; | |
383 else | |
384 temp = planet2; | |
385 lx = thead->t_x; | |
386 ly = thead->t_y; | |
387 thead->t_x = planets[temp].pl_x + Cos[255 - plan_count] * PLANRAD; | |
388 thead->t_y = planets[temp].pl_y + Sin[255 - plan_count] * PLANRAD; | |
389 } | |
390 for (i = j->p_no * MAXTORP, k = &torps[i]; | |
391 i < j->p_no * MAXTORP + length; i++, k++) | |
392 { | |
393 | |
394 if (k->t_status == TFREE) | |
395 /* got exploded. x & y location will remain however */ | |
396 snake_torp(k, i, j); | |
397 | |
398 if (k == thead) | |
399 continue; | |
400 | |
401 px = k->t_x; | |
402 py = k->t_y; | |
403 | |
404 k->t_x = lx; | |
405 k->t_y = ly; | |
406 | |
407 lx = px; | |
408 ly = py; | |
409 } | |
410 } | |
411 if (plan_guard) | |
412 { | |
413 thead = &torps[perfs[0]->p_no * MAXTORP]; | |
414 plan_count = (plan_count + PLANRATE) % 256; | |
415 } | |
416 lx = thead->t_x; | |
417 ly = thead->t_y; | |
418 doeyes(); | |
419 } | |
420 | |
421 check_explode() | |
422 { | |
423 register int i, l; | |
424 register struct player *j; | |
425 register struct torp *k; | |
426 static struct player *killer; | |
427 | |
428 if (fl->pt_status == PTDET || fr->pt_status == PTDET || | |
429 fl->pt_status == PTEXPLODE || fr->pt_status == PTEXPLODE || explode) | |
430 { | |
431 if (plan_guard) | |
432 { | |
433 restore_eye(); | |
434 return; | |
435 } /* KAO */ | |
436 if (debug) | |
437 fprintf(stderr, "snake exploding\n"); | |
438 if (!explode) | |
439 { | |
440 /* do once */ | |
441 explode = s_clock; | |
442 tfuse = 0; | |
443 if (fl->pt_status == PTDET || fl->pt_status == PTEXPLODE) | |
444 { | |
445 killer = whokilledme(fl); | |
446 if (killer) | |
447 award(killer); | |
448 } | |
449 if (fr->pt_status == PTDET || fr->pt_status == PTEXPLODE) | |
450 { | |
451 killer = whokilledme(fr); | |
452 if (killer) | |
453 award(killer); | |
454 } | |
455 } | |
456 if (fl->pt_status != PTFREE && fl->pt_status != PTEXPLODE) | |
457 { | |
458 fl->pt_war = FED | ROM | KLI | ORI; /* make sure its at war when | |
459 * it explodes */ | |
460 fl->pt_status = PTEXPLODE; | |
461 fl->pt_fuse = 10; | |
462 } | |
463 if (fl->pt_status != PTFREE && fr->pt_status != PTEXPLODE) | |
464 { | |
465 fl->pt_war = FED | ROM | KLI | ORI; | |
466 fr->pt_status = PTEXPLODE; | |
467 fr->pt_fuse = 10; | |
468 } | |
469 /* | |
470 * now for some fancy stuff. If killer is our target and is hostile or at | |
471 * war with our team then snake torp head makes a beeline for him. This | |
472 * lasts until killer dies or torps have been chasing killer for 40 | |
473 * cycles | |
474 */ | |
475 | |
476 if (killer && WARHOSTILE(killer) && (noSmush < 1) && (killer->p_status == PALIVE) && | |
477 tfuse < 40 && (killer->p_no == target || noSmush < 0)) | |
478 { | |
479 crash_killer(killer); | |
480 } | |
481 else | |
482 { | |
483 /* explode all torps in sequence, 1 per cycle until all gone */ | |
484 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
485 { | |
486 for (l = (j == perfs[0]) ? 0 : length, i = j->p_no * MAXTORP, k = &torps[i]; | |
487 i < j->p_no * MAXTORP + length; i++, k++, l++) | |
488 { | |
489 if (l == explodetorps && k->t_status != TEXPLODE && | |
490 k->t_status != TFREE) | |
491 { | |
492 k->t_status = TEXPLODE; | |
493 k->t_fuse = 10; | |
494 explodetorps++; | |
495 return; | |
496 } | |
497 else if (l == explodetorps) | |
498 explodetorps++; | |
499 } | |
500 } | |
501 } | |
502 } | |
503 } | |
504 | |
505 crash_killer(p) | |
506 struct player *p; | |
507 { | |
508 register int i, px, py; | |
509 register struct player *j; | |
510 register struct torp *k; | |
511 unsigned char tc; | |
512 int active = 0; | |
513 | |
514 tfuse++; | |
515 | |
516 tc = getacourse(p->p_x, p->p_y, thead->t_x, thead->t_y); | |
517 thead->t_dir = tc; | |
518 | |
519 lx = thead->t_x; | |
520 ly = thead->t_y; | |
521 | |
522 thead->t_x += (double) (12 * WARP1) * Cos[thead->t_dir]; | |
523 thead->t_y += (double) (12 * WARP1) * Sin[thead->t_dir]; | |
524 | |
525 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
526 { | |
527 for (i = j->p_no * MAXTORP, k = &torps[i]; | |
528 i < j->p_no * MAXTORP + length; i++, k++) | |
529 { | |
530 | |
531 /* move the head up if it exploded */ | |
532 if (k != thead && thead->t_status == TFREE) | |
533 thead = k; | |
534 else if (k == thead) | |
535 continue; | |
536 | |
537 if (k->t_status != TFREE) | |
538 active++; | |
539 | |
540 px = k->t_x; | |
541 py = k->t_y; | |
542 | |
543 k->t_x = lx; | |
544 k->t_y = ly; | |
545 | |
546 lx = px; | |
547 ly = py; | |
548 } | |
549 } | |
550 return active; | |
551 } | |
552 | |
553 | |
554 doeyes() | |
555 { | |
556 unsigned char c = getacourse(eyetp->t_x, eyetp->t_y, eyet->t_x, | |
557 eyet->t_y); | |
558 int ew = EYEWIDTH, war_ok; | |
559 | |
560 /* c + 64 -- fl c - 64 -- fr */ | |
561 | |
562 if (plan_guard) | |
563 { | |
564 fl->pt_x = planets[planet1].pl_x + Cos[255 - plan_count] * PLANRAD; | |
565 fl->pt_y = planets[planet1].pl_y + Sin[255 - plan_count] * PLANRAD; | |
566 fr->pt_x = planets[planet2].pl_x + Cos[255 - plan_count] * PLANRAD; | |
567 fr->pt_y = planets[planet2].pl_y + Sin[255 - plan_count] * PLANRAD; | |
568 return; | |
569 } | |
570 if (fl->pt_war) | |
571 ew += 15; | |
572 | |
573 fl->pt_x = eyet->t_x + (double) (ew) * Cos[(unsigned char) (c - EYEANGLE)]; | |
574 fl->pt_y = eyet->t_y + (double) (ew) * Sin[(unsigned char) (c - EYEANGLE)]; | |
575 | |
576 #ifdef nodef | |
577 if (fl->pt_x < 0) | |
578 fl->pt_x = 0; | |
579 else if (fl->pt_x > GWIDTH) | |
580 fl->pt_x = GWIDTH; | |
581 | |
582 if (fl->pt_y < 0) | |
583 fl->pt_y = 0; | |
584 else if (fl->pt_y > GWIDTH) | |
585 fl->pt_y = GWIDTH; | |
586 #endif | |
587 | |
588 if (fr->pt_war) | |
589 ew += 15; | |
590 | |
591 fr->pt_x = eyet->t_x + (double) (ew) * Cos[(unsigned char) (c + EYEANGLE)]; | |
592 fr->pt_y = eyet->t_y + (double) (ew) * Sin[(unsigned char) (c + EYEANGLE)]; | |
593 | |
594 #ifdef nodef | |
595 if (fr->pt_x < 0) | |
596 fr->pt_x = 0; | |
597 else if (fl->pt_x > GWIDTH) | |
598 fr->pt_x = GWIDTH; | |
599 | |
600 if (fr->pt_y < 0) | |
601 fr->pt_y = 0; | |
602 else if (fl->pt_y > GWIDTH) | |
603 fr->pt_y = GWIDTH; | |
604 #endif | |
605 | |
606 /* toggle war */ | |
607 if ((s_clock % 6) == 0) | |
608 { | |
609 /* | |
610 * your home planet and shipyards are always safe from your own snake | |
611 * unless you are a target. | |
612 */ | |
613 war_ok = !sp_area(thead->t_x, thead->t_y); | |
614 | |
615 if (!fr->pt_war && war_ok) | |
616 fr->pt_war = (FED | ROM | KLI | ORI) & ~(war_ok ? 0 : (1 << tno)); | |
617 else | |
618 fr->pt_war = 0; | |
619 | |
620 if (!fl->pt_war && war_ok) | |
621 fl->pt_war = (FED | ROM | KLI | ORI) & ~(war_ok ? 0 : (1 << tno)); | |
622 else | |
623 fl->pt_war = 0; | |
624 } | |
625 } | |
626 | |
627 exitSnake(sig) | |
628 int sig; | |
629 { | |
630 register int i; | |
631 register struct player *j; | |
632 register struct torp *k; | |
633 register struct plasmatorp *f; | |
634 | |
635 r_signal(SIGALRM, SIG_DFL); | |
636 | |
637 if (debug) | |
638 fprintf(stderr, "snake exiting\n"); | |
639 | |
640 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
641 { | |
642 for (i = j->p_no * MAXTORP, k = &torps[i]; | |
643 i < j->p_no * MAXTORP + length; i++, k++) | |
644 { | |
645 /* torps are free here */ | |
646 if (k->t_status != TFREE) | |
647 k->t_status = TOFF; | |
648 } | |
649 f = &plasmatorps[j->p_no * MAXPLASMA]; | |
650 f->pt_status = PTFREE; | |
651 /* plasma */ | |
652 } | |
653 | |
654 memset(perfs[0], 0, sizeof(struct player)); | |
655 memset(perfs[1], 0, sizeof(struct player)); | |
656 perfs[0]->p_stats.st_tticks = 1; | |
657 perfs[1]->p_stats.st_tticks = 1; | |
658 | |
659 /* | |
660 * note: if we had a segmentation violation or bus error we want a core | |
661 * file to debug | |
662 */ | |
663 if (sig == SIGBUS || sig == SIGSEGV) | |
664 abort(); | |
665 else | |
666 exit(0); | |
667 } | |
668 | |
669 pmessage(str, recip, group, address) | |
670 char *str; | |
671 int recip; | |
672 int group; | |
673 char *address; | |
674 { | |
675 pmessage2(str, recip, group, address, 255); | |
676 } | |
677 | |
678 pmessage2(str, recip, group, address, from) | |
679 char *str; | |
680 int recip; | |
681 int group; | |
682 char *address; | |
683 unsigned char from; | |
684 { | |
685 struct message *cur; | |
686 int mesgnum; | |
687 | |
688 if ((mesgnum = ++(mctl->mc_current)) >= MAXMESSAGE) | |
689 { | |
690 mctl->mc_current = 0; | |
691 mesgnum = 0; | |
692 } | |
693 cur = &messages[mesgnum]; | |
694 cur->m_no = mesgnum; | |
695 cur->m_flags = group; | |
696 cur->m_recpt = recip; | |
697 cur->m_from = from; | |
698 (void) sprintf(cur->m_data, "%-9s %s", address, str); | |
699 cur->m_flags |= MVALID; | |
700 } | |
701 | |
702 /* get course from (mx,my) to (x,y) */ | |
703 unsigned char | |
704 getacourse(x, y, mx, my) | |
705 int x, y, mx, my; | |
706 { | |
707 if (x == mx && y == my) | |
708 return 0; | |
709 | |
710 return (unsigned char) (int) (atan2((double) (x - mx), | |
711 (double) (my - y)) / 3.14159 * 128.); | |
712 } | |
713 | |
714 /* | |
715 * FED 1 ROM 2 KLI 4 ORI 8 | |
716 */ | |
717 | |
718 /* | |
719 * 256/0 192 + 64 128 */ | |
720 | |
721 check_tboundary(teams, mycrs, range, x, y) | |
722 int teams; | |
723 int x, y; | |
724 unsigned char *mycrs; | |
725 int range; | |
726 { | |
727 int lx = homestar->pl_x - SYSWIDTH / 2, rx = homestar->pl_x + SYSWIDTH / 2, | |
728 ty = homestar->pl_y - SYSWIDTH / 2, by = homestar->pl_y + SYSWIDTH / 2; | |
729 int r = 0, l = 0; | |
730 unsigned char crs = *mycrs; | |
731 | |
732 if (x < lx && crs >= 128) | |
733 { | |
734 if (crs >= 192) | |
735 *mycrs += range; | |
736 else | |
737 *mycrs -= range; | |
738 l = 1; | |
739 } | |
740 else if (x > rx && crs < 128) | |
741 { | |
742 if (crs > 64) | |
743 *mycrs += range; | |
744 else | |
745 *mycrs -= range; | |
746 r = 1; | |
747 } | |
748 if (y < ty && (crs >= 192 || crs < 64)) | |
749 { | |
750 if (crs >= 192 && !l) | |
751 *mycrs -= range; | |
752 else | |
753 *mycrs += range; | |
754 } | |
755 else if (y > by && (crs < 192 && crs >= 64)) | |
756 { | |
757 if (crs < 128 && !r) | |
758 *mycrs -= range; | |
759 else | |
760 *mycrs += range; | |
761 } | |
762 } | |
763 | |
764 /* return rnd between -range & range */ | |
765 rrnd(range) | |
766 int range; | |
767 { | |
768 return lrand48() % (2 * range) - range; | |
769 } | |
770 | |
771 #ifdef nodef | |
772 /* NOTUSED */ | |
773 contrast(t) | |
774 int t; | |
775 { | |
776 return ROM; /* experiment */ | |
777 switch (t) | |
778 { | |
779 case FED: | |
780 return ORI; | |
781 case ORI: | |
782 return FED; | |
783 case KLI: | |
784 return ROM; | |
785 case ROM: | |
786 return KLI; | |
787 default: | |
788 return FED; | |
789 } | |
790 } | |
791 | |
792 #endif | |
793 | |
794 snake_torp(t, n, p) | |
795 struct torp *t; | |
796 int n; | |
797 struct player *p; | |
798 { | |
799 t->t_no = n; | |
800 t->t_status = TMOVE; | |
801 t->t_owner = p->p_no; | |
802 t->t_team = p->p_team; | |
803 t->t_dir = 128; | |
804 if (plan_guard == 0) | |
805 t->t_damage = SNAKETORPDAMAGE; | |
806 else | |
807 t->t_damage = SNAKETORPDAMAGE * 10; | |
808 t->t_speed = 0; | |
809 if (berserk) | |
810 t->t_war = FED | ROM | ORI | KLI; | |
811 else if (target == -1) | |
812 t->t_war = 0; | |
813 else | |
814 t->t_war = perfs[0]->p_swar | perfs[0]->p_hostile; | |
815 t->t_fuse = MAXINT; | |
816 t->t_turns = 0; | |
817 p->p_ntorp++; | |
818 } | |
819 | |
820 struct player * | |
821 whokilledme(pt) | |
822 struct plasmatorp *pt; | |
823 { | |
824 register i; | |
825 register struct phaser *j; | |
826 | |
827 for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++) | |
828 { | |
829 if (j->ph_status == PHHIT2) | |
830 { | |
831 if (debug) | |
832 { | |
833 fprintf(stderr, "found PHHIT2 from %d at %d,%d\n", players[i].p_no, | |
834 j->ph_x, j->ph_y); | |
835 fprintf(stderr, "plasma is at %d,%d\n", pt->pt_x, pt->pt_y); | |
836 fprintf(stderr, "fl is at %d,%d\n", fl->pt_x, fl->pt_y); | |
837 fprintf(stderr, "fr is at %d,%d\n", fr->pt_x, fr->pt_y); | |
838 } | |
839 if (j->ph_x == pt->pt_x && j->ph_y == pt->pt_y) | |
840 { | |
841 return &players[i]; | |
842 } | |
843 } | |
844 } | |
845 return NULL; | |
846 } | |
847 | |
848 /* | |
849 * NOTE: the procedure could be writing shared memory variables at the same | |
850 * time as the daemon. This may produce unpredicatable results. A better | |
851 * implementation would mark the "snake plasma" and have the daemon do the | |
852 * awarding. | |
853 */ | |
854 | |
855 award(win) | |
856 struct player *win; | |
857 { | |
858 char buf[80]; | |
859 char addrbuf[10]; | |
860 | |
861 if (!win) | |
862 return; | |
863 | |
864 if (target == -1 && !(win->p_flags & PFROBOT) && !WARHOSTILE(win)) | |
865 { | |
866 strcpy(buf, "Snake eyes!"); | |
867 | |
868 /* what do we have for our big winner today, fred? */ | |
869 | |
870 if (((100 * win->p_damage) / win->p_ship.s_maxdamage) > 50 || | |
871 ((100 * win->p_shield) / win->p_ship.s_maxshield) < 50) | |
872 { | |
873 win->p_damage = 0; | |
874 win->p_shield = win->p_ship.s_maxshield; | |
875 strcat(buf, " You win free repairs!"); | |
876 } | |
877 else if (((100 * win->p_fuel) / win->p_ship.s_maxfuel) < 50) | |
878 { | |
879 win->p_fuel = win->p_ship.s_maxfuel; | |
880 strcat(buf, " You win free fuel!"); | |
881 } | |
882 else if (((100 * win->p_etemp) / win->p_ship.s_maxegntemp) > 60) | |
883 { | |
884 win->p_etemp = 0; | |
885 strcat(buf, " You win free engine cooling!"); | |
886 } | |
887 else if (((100 * win->p_wtemp) / win->p_ship.s_maxwpntemp) > 60) | |
888 { | |
889 win->p_wtemp = 0; | |
890 strcat(buf, " You win free weapons cooling!"); | |
891 } | |
892 else | |
893 { | |
894 win->p_damage = 0; | |
895 win->p_shield = win->p_ship.s_maxshield; | |
896 win->p_fuel = win->p_ship.s_maxfuel; | |
897 win->p_etemp = 0; | |
898 win->p_wtemp = 0; | |
899 strcat(buf, " You feel healthy!"); | |
900 } | |
901 | |
902 /* ... */ | |
903 | |
904 sprintf(addrbuf, "%s->%c%c", SERVNAME, | |
905 teams[win->p_team].letter, shipnos[win->p_no]); | |
906 pmessage2(buf, win->p_no, MINDIV, addrbuf, 255); | |
907 } | |
908 sprintf(buf, "%s (%c%c) slew the vile space serpent!", | |
909 win->p_name, teams[win->p_team].letter, shipnos[win->p_no]); | |
910 pmessage(buf, 0, MALL | MKILLA, MSERVA, 255); | |
911 | |
912 /* and get .5 kills */ | |
913 | |
914 win->p_kills += 0.5; | |
915 if (win->p_ship.s_type == STARBASE) | |
916 { | |
917 if (win->p_stats.st_sbmaxkills < win->p_kills) | |
918 { | |
919 win->p_stats.st_sbmaxkills = win->p_kills; | |
920 } | |
921 } | |
922 else if (win->p_stats.st_tmaxkills < win->p_kills) | |
923 { | |
924 win->p_stats.st_tmaxkills = win->p_kills; | |
925 } | |
926 } | |
927 | |
928 bombcheck(team1, team2) | |
929 int team1, team2; | |
930 { | |
931 register i; | |
932 register struct player *j; | |
933 struct planet *p; | |
934 | |
935 for (i = 0, j = players; i < MAXPLAYER; i++, j++) | |
936 { | |
937 if (j->p_status == PALIVE) | |
938 { | |
939 if ((j->p_flags & PFBOMB) && (j->p_flags & PFORBIT)) | |
940 { | |
941 p = &planets[j->p_planet]; | |
942 if (!((j->p_swar | j->p_hostile) & p->pl_owner)) | |
943 continue; | |
944 | |
945 if (defenders[p->pl_owner] >= configvals->tournplayers) | |
946 continue; | |
947 | |
948 #if 0 | |
949 /* ignore planets that aren't within team boundaries */ | |
950 if (p->pl_x > boundaries[p->pl_owner].rx || | |
951 p->pl_x < boundaries[p->pl_owner].lx || | |
952 p->pl_y > boundaries[p->pl_owner].by || | |
953 p->pl_y < boundaries[p->pl_owner].ty) | |
954 continue; | |
955 #endif | |
956 | |
957 if (!team1 && !team2) | |
958 { | |
959 /* any planet */ | |
960 printf("snake found bomber: targeting %c%c\n", | |
961 teams[j->p_team].letter, shipnos[j->p_no]); | |
962 fflush(stdout); | |
963 make_war(j, p->pl_owner); | |
964 return j->p_no; | |
965 } | |
966 else | |
967 { | |
968 if (team1) | |
969 { | |
970 if (p->pl_owner == team1) | |
971 { | |
972 printf("found bomber: targeting %c%c\n", | |
973 teams[j->p_team].letter, shipnos[j->p_no]); | |
974 fflush(stdout); | |
975 make_war(j, p->pl_owner); | |
976 return j->p_no; | |
977 } | |
978 } | |
979 if (team2) | |
980 { | |
981 if (p->pl_owner == team2) | |
982 { | |
983 printf("found bomber: targeting %c%c\n", | |
984 teams[j->p_team].letter, shipnos[j->p_no]); | |
985 fflush(stdout); | |
986 make_war(j, p->pl_owner); | |
987 return j->p_no; | |
988 } | |
989 } | |
990 } | |
991 } | |
992 } | |
993 } | |
994 return -1; | |
995 } | |
996 | |
997 make_war(p, plteam) | |
998 struct player *p; | |
999 int plteam; | |
1000 { | |
1001 register int i; | |
1002 register struct player *j; | |
1003 register struct torp *k; | |
1004 | |
1005 perfs[0]->p_team = plteam; | |
1006 perfs[0]->p_swar = 0; | |
1007 perfs[0]->p_hostile = 0; | |
1008 perfs[1]->p_team = plteam; | |
1009 perfs[1]->p_swar = 0; | |
1010 perfs[1]->p_hostile = 0; | |
1011 | |
1012 perfs[0]->p_swar |= p->p_team; | |
1013 perfs[0]->p_hostile |= p->p_team; | |
1014 perfs[1]->p_swar |= p->p_team; | |
1015 perfs[1]->p_hostile |= p->p_team; | |
1016 | |
1017 /* update our torps war status */ | |
1018 for (j = perfs[0]; j; j = (j == perfs[1] ? NULL : perfs[1])) | |
1019 { | |
1020 for (i = j->p_no * MAXTORP, k = &torps[i]; | |
1021 i < j->p_no * MAXTORP + length; i++, k++) | |
1022 { | |
1023 | |
1024 k->t_war = perfs[0]->p_swar | perfs[0]->p_hostile; | |
1025 } | |
1026 } | |
1027 } | |
1028 | |
1029 | |
1030 | |
1031 /* | |
1032 * start planet areas are places where people will likely enter the game | |
1033 * (only considers 1 start planet at this time) | |
1034 */ | |
1035 | |
1036 sp_area(x, y) | |
1037 int x, y; | |
1038 { | |
1039 register i, j, px, py; | |
1040 | |
1041 #if 0 | |
1042 /* check for proximity to a shipyard? */ | |
1043 return 0; | |
1044 #else | |
1045 | |
1046 for (i = 0; i < NUMPLANETS; i++) | |
1047 { | |
1048 struct planet *pl = &planets[i]; | |
1049 if (!(pl->pl_flags & (PLSHIPYARD | PLHOME))) | |
1050 continue; | |
1051 px = pl->pl_x; | |
1052 py = pl->pl_y; | |
1053 /* printf("checking %s (%d,%d)\n", pl->pl_name, i*10,j); */ | |
1054 | |
1055 if (!(x < px - 5300 || x > px + 5300 || | |
1056 y < py - 5300 || y > py + 5300)) | |
1057 { | |
1058 #ifdef maybe /* not used. */ | |
1059 if (target != -1) | |
1060 { | |
1061 struct player *p = &players[target]; | |
1062 /* | |
1063 * if target is also in same home area, he should at least be able to | |
1064 * phaser the snake since the torps are already deadly | |
1065 */ | |
1066 if (!(p->p_x < px - 5300 || p->p_x > px + 5300 || | |
1067 p->p_y < py - 5300 || p->p_y > py + 5300)) | |
1068 return 0; | |
1069 else | |
1070 return 1; | |
1071 } | |
1072 #endif | |
1073 return 1; | |
1074 } | |
1075 } | |
1076 | |
1077 return 0; | |
1078 | |
1079 #endif | |
1080 } |