|
|
1.1 root 1: /* $Header: weapon.c,v 7.0.1.2 86/10/20 14:36:33 lwall Exp $ */
2:
3: /* $Log: weapon.c,v $
4: * Revision 7.0.1.2 86/10/20 14:36:33 lwall
5: * Picked some lint.
6: *
7: * Revision 7.0.1.1 86/10/16 10:54:42 lwall
8: * Added Damage. Fixed random bugs.
9: *
10: * Revision 7.0 86/10/08 15:18:08 lwall
11: * Split into separate files. Added amoebas and pirates.
12: *
13: */
14:
15: #include "EXTERN.h"
16: #include "warp.h"
17: #include "bang.h"
18: #include "object.h"
19: #include "move.h"
20: #include "score.h"
21: #include "sig.h"
22: #include "term.h"
23: #include "them.h"
24: #include "us.h"
25: #include "util.h"
26: #include "INTERN.h"
27: #include "weapon.h"
28:
29: void
30: weapon_init()
31: {
32: ;
33: }
34:
35: void
36: fire_torp(from, ydir, xdir)
37: Reg1 OBJECT *from;
38: Reg3 int ydir;
39: Reg4 int xdir;
40: {
41: Reg2 OBJECT *to;
42:
43: if (from->type == Enemy ||
44: (from == ent && etorp > 0) ||
45: (from == base && btorp > 0)) {
46: to = occupant[(from->posy+from->vely+ydir+YSIZE00)%YSIZE]
47: [(from->posx+from->velx+xdir+XSIZE00)%XSIZE];
48: if (from->type != Enemy || !to || to->vely || to->velx) {
49: if (from->type != Enemy &&
50: (to = isatorp[from==base][ydir+1][xdir+1])) {
51: to->vely += ydir;
52: to->velx += xdir;
53: }
54: else {
55: if (from == ent) {
56: to = make_object(Torp, '+', from->posy,from->posx,
57: from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
58: aretorps++;
59: isatorp[0][ydir+1][xdir+1] = to;
60: etorp--;
61: }
62: else if (from == base) {
63: to = make_object(Torp, '+', from->posy,from->posx,
64: from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
65: aretorps++;
66: isatorp[1][ydir+1][xdir+1] = to;
67: btorp--;
68: }
69: else if (from->image == 'G') {
70: numos++;
71: to = make_object(Torp, 'o', from->posy,from->posx,
72: from->vely+ydir,from->velx+xdir, 100L, 1L,&root);
73: if (madgorns) {
74: possiblescore += 35;
75: to->image = '0';
76: to->mass = 2000;
77: to->energy = 2000;
78: }
79: else if (rand_mod(120)+10 > smarts)
80: possiblescore += 100;
81: else {
82: possiblescore += 200;
83: to->image = 'O';
84: }
85: }
86: else {
87: to = make_object(Torp, 'x', from->posy,from->posx,
88: from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
89: if (rand_mod(160)+10 > smarts)
90: possiblescore += 10;
91: else {
92: possiblescore += 100;
93: to->image = 'X';
94: to->mass = 1000+super*20;
95: numxes++;
96: }
97: }
98: }
99: }
100: }
101: }
102:
103: void
104: attack(attackee)
105: Reg7 OBJECT *attackee;
106: {
107: Reg1 int dx;
108: Reg2 int dy;
109: Reg3 int curx;
110: Reg4 int cury;
111: Reg5 int prob;
112: Reg6 OBJECT *obj;
113: Reg8 bool torps;
114: Reg9 bool webnear = FALSE;
115: Reg10 bool thru_stars;
116: int nukey;
117: int nukex;
118: int nukedist;
119:
120: if (attackee) {
121: if (attackee == nuke) {
122: if (amb[attackee->posy][attackee->posx] != '~')
123: return;
124: nukey = nukex = 0;
125: nukedist = 100;
126: }
127: for (dx= -1; dx<=1 ; dx++) {
128: for (dy= -1; dy<=1; dy++) {
129: if (dx||dy) {
130: cury = attackee->posy;
131: curx = attackee->posx;
132: torps = thru_stars = FALSE;
133: if (massacre || madgorns || !rand_mod(53-super) )
134: webnear += rand_mod(2);
135: else
136: webnear = FALSE;
137: for (prob = scandist;prob;prob--) {
138: cury = (cury + dy + YSIZE00) % YSIZE;
139: curx = (curx + dx + XSIZE00) % XSIZE;
140: if (obj = occupant[cury][curx]) {
141: switch (obj->image) {
142: case 'P': case 'K': case 'R': case ' ':
143: pot_shot:
144: if (attackee == nuke) {
145: if (rand_mod(2+scandist-prob) <
146: rand_mod(smarts/40+1))
147: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
148: }
149: if (rand_mod(51 - sm50) <= prob) {
150: switch (obj->strategy||thru_stars?0:
151: rand_mod(ent?4:2)) {
152: case 1: case 2:
153: if (-dy + attackee->vely == obj->vely
154: && -dx + attackee->velx == obj->velx)
155: fire_torp(obj,
156: -dy + attackee->vely,
157: -dx + attackee->velx);
158: else
159: fire_torp(obj,
160: -dy + attackee->vely - obj->vely,
161: -dx + attackee->velx - obj->velx);
162: if (obj->image == ' ')
163: setimage(obj,
164: obj->flags & PIRATE ? 'P' : 'R');
165: break;
166: case 3: {
167: int newspeed =
168: rand_mod(prob<5&&smarts>70?4:3)-1;
169:
170: obj->vely = -dy * newspeed;
171: obj->velx = -dx * newspeed;
172: if (newspeed >= 0 &&
173: !rand_mod(82-sm80)) {
174: obj->vely += attackee->vely;
175: obj->velx += attackee->velx;
176: }
177: break;
178: }
179: case 0:
180: if (!torps && obj->energy > 1000) {
181: fire_phaser(obj, -dy, -dx);
182: if (smarts > 40 &&
183: (scandist-prob > 5
184: || attackee==base) &&
185: (massacre || obj->strategy ||
186: rand_mod(2)))
187: while (rand_mod(2))
188: fire_phaser(obj, -dy, -dx);
189: if (obj->image == ' ')
190: setimage(obj,
191: obj->flags&PIRATE ? 'P':'R');
192: }
193: if (obj->strategy) {
194: obj->velx = obj->vely = 0;
195: if (obj->energy < 1000 ||
196: bvely || bvelx)
197: obj->strategy = 0;
198: }
199: else if ((attackee==base ||
200: (cloaking && attackee==ent)
201: ) &&
202: scandist-prob > 5 &&
203: !(rand_mod(
204: ent?antibase*2:antibase)) )
205: obj->strategy = 1;
206: break;
207: }
208: }
209: goto bombout;
210: case 'G':
211: if (thru_stars && obj->strategy < 7)
212: goto bombout;
213: if (attackee == nuke) {
214: if (rand_mod(2+scandist-prob) <
215: rand_mod(smarts/40+1))
216: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
217: goto bombout;
218: }
219: if (obj->strategy) {
220: if (madgorns || !rand_mod(4)) {
221: obj->vely = attackee->vely;
222: obj->velx = attackee->velx;
223: }
224: obj->strategy += (!torps && deados > 10);
225: if (obj->strategy > 4)
226: madgorns = TRUE;
227: if (!torps && obj->strategy > 5) {
228: do {
229: fire_phaser(obj, -dy, -dx);
230: } while (rand_mod(2));
231: }
232: }
233: else if (numgorns >= numenemies-1 &&
234: deados > 15+numgorns*5)
235: obj->strategy = 1;
236: if (madgorns || rand_mod(51 - sm50) <= prob) {
237: if (-dy + attackee->vely == obj->vely
238: && -dx + attackee->velx == obj->velx)
239: fire_torp(obj,
240: -dy + attackee->vely,
241: -dx + attackee->velx);
242: else
243: fire_torp(obj,
244: -dy + attackee->vely - obj->vely,
245: -dx + attackee->velx - obj->velx);
246: }
247: goto bombout;
248: case 'T':
249: if (attackee == nuke) {
250: if (rand_mod(2+scandist-prob) <
251: rand_mod(smarts/40+1))
252: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
253: }
254: if (thru_stars)
255: goto bombout;
256: if (webnear && scandist-prob > 5) {
257: if (massacre || rand_mod(50) < super) {
258: if (!torps && obj->energy > 1000) {
259: fire_phaser(obj, -dy, -dx);
260: while (!rand_mod(57-sm55))
261: fire_phaser(obj, -dy, -dx);
262: }
263: }
264: }
265: goto bombout;
266: case 'C': case 'c':
267: if (thru_stars)
268: goto bombout;
269: break;
270: case 'Q': case 'W': case 'Y': case 'U':
271: case 'I': case 'S': case 'D': case 'H': case 'J':
272: case 'L': case 'Z': case 'V': case 'M': case 'F':
273: if (attackee == nuke) {
274: if (rand_mod(2+scandist-prob) <
275: rand_mod(smarts/40+1))
276: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
277: if (rand_mod(2))
278: goto pot_shot;
279: }
280: if (madfriends > 1000) {
281: madfriends -= 200;
282: goto pot_shot;
283: }
284: /* FALL THROUGH */
285: case '+':
286: if (attackee == nuke) {
287: if (smarts > 70) {
288: if (
289: (obj->posx + obj->velx + XSIZE00)%XSIZE
290: == attackee->posx &&
291: (obj->posy + obj->vely + YSIZE00)%YSIZE
292: == attackee->posy ) {
293: Tract(nuke,dy,dx,-1);
294: }
295: else
296: while (!rand_mod(82-sm80))
297: Tract(nuke,dy,dx,-1);
298: }
299: else if (smarts > 60 ||
300: rand_mod(2+scandist-prob) <
301: rand_mod(smarts/20+1))
302: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
303: }
304: torps = FALSE;
305: thru_stars = FALSE;
306: break;
307: case '|': case '-': case '/': case '\\':
308: if (thru_stars)
309: goto bombout;
310: webnear = (scandist-prob < 3);
311: torps = FALSE;
312: break;
313: case 'x':
314: if (attackee == nuke) {
315: if (rand_mod(2+scandist-prob) <
316: rand_mod(smarts/20+1))
317: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
318: }
319: if (thru_stars)
320: goto bombout;
321: torps = TRUE;
322: break;
323: case 'o': case 'O': case '0':
324: if (attackee == nuke) {
325: if (rand_mod(2+scandist-prob) <
326: rand_mod(smarts/20+1))
327: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
328: }
329: if (thru_stars)
330: goto bombout;
331: torps = TRUE;
332: if (rand_mod(99+3*scandist) < smarts+3*prob) {
333: obj->vely = -dy + attackee->vely;
334: obj->velx = -dx + attackee->velx;
335: if (obj->flags & STATIC) {/* not a mover? */
336: obj->flags &= ~STATIC;
337: obj->prev->next = obj->next;
338: obj->next->prev = obj->prev;
339: root.prev->next = obj;
340: obj->prev = root.prev;
341: root.prev = obj;
342: obj->next = &root;
343: }
344: }
345: if (obj->image != '0')
346: break;
347: /* DROP THROUGH! */
348: case 'X':
349: if (attackee == nuke) {
350: if (rand_mod(2+scandist-prob) <
351: rand_mod(smarts/20+1))
352: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
353: }
354: torps = TRUE;
355: if (thru_stars)
356: goto bombout;
357: if (prob == scandist) {
358: int y, x;
359:
360: blast[y=(obj->posy+obj->vely+YSIZE00)%YSIZE]
361: [x=(obj->posx+obj->velx+XSIZE00)%XSIZE]
362: += (obj->image == '0' ? 2000 : 200);
363: yblasted[y] |= 1;
364: xblasted[x] |= 1;
365: blasted = TRUE;
366: }
367: break;
368: case 'A':
369: if (attackee != nuke) {
370: if (scandist-prob>1 && !rand_mod(51-super))
371: Tract(obj,-dy,-dx,1);
372: }
373: /* FALL THROUGH */
374: case '*': case '@':
375: if (attackee == nuke) {
376: if (amb[cury][curx] != '~') {
377: if (scandist-prob < nukedist) {
378: nukedist = scandist-prob;
379: nukey = dy; /* nearest food in */
380: nukex = dx; /* this direction */
381: }
382: if (smarts > 55 && scandist-prob > 8) {
383: if (rand_mod(30+scandist-prob) <
384: rand_mod(smarts/20+1))
385: Tract(nuke,dy,dx,1);
386: }
387: }
388: else if (obj->vely || obj->velx) {
389: Tract(nuke,dy,dx,1); /* for looks */
390: obj->vely = obj->velx = 0;
391: }
392: }
393: if (!thru_stars)
394: if (rand_mod(97-sm95))
395: goto bombout;
396: else
397: thru_stars = TRUE;
398: break;
399: case '<': case '>':
400: if (attackee == nuke) {
401: if ((!dy && scandist-prob < 8) ||
402: rand_mod(2+scandist-prob) <
403: rand_mod(smarts/20+1) ) {
404: nuke->mass += 10000;
405: Tract(nuke,dy,dx,-1);
406: nuke->mass -= 10000;
407: }
408: }
409: goto bombout;
410: case 'E': case 'B':
411: if (attackee == nuke) {
412: if (rand_mod(2+scandist-prob) <
413: rand_mod(smarts/40+1))
414: Tract(nuke,dy,dx,rand_mod(3)?1:-1);
415: }
416: goto bombout;
417: default:
418: goto bombout;
419: }
420: }
421: else {
422: if (thru_stars)
423: goto bombout;
424: }
425: }
426: bombout: ; /* end of loop */
427: }
428: }
429: }
430: if (attackee == nuke && nukedist < 100) {/* aim amoeba at nearest */
431: if (nukey < 0) /* free star */
432: nukey = 2;
433: if (nukex < 0)
434: nukex = 2;
435: nuke->strategy = nukey + (nukex << 2);
436: }
437: }
438: }
439:
440: void
441: fire_phaser(obj, dy, dx)
442: Reg7 OBJECT *obj;
443: Reg5 int dy;
444: Reg6 int dx;
445: {
446: Reg1 int y;
447: Reg2 int x;
448: Reg3 int skipping;
449: Reg4 int size=5000;
450: int decr = 50, oldy, oldx;
451: static char curchar[] = "@* ";
452:
453: if (obj == ent)
454: decr = 100;
455: else if (obj == base) {
456: decr = 1000;
457: size = 200;
458: }
459: if (!dy)
460: curchar[2] = '-';
461: else if (!dx)
462: curchar[2] = '!';
463: else if (dy == dx)
464: curchar[2] = '\\';
465: else
466: curchar[2] = '/';
467: if (obj->energy >= decr) {
468: obj->energy -= decr;
469: for (
470: /* initialize */
471: skipping = (obj != base),
472: y = (obj->posy+(obj==base?dy*2:dy)+YSIZE00)%YSIZE,
473: x = (obj->posx+(obj==base?dx*2:dx)+XSIZE00)%XSIZE;
474: /* while */
475: size && (!occupant[y][x]||(skipping && occupant[y][x]->type==Star));
476: /* at end of loop */
477: y = (y+dy+YSIZE00) % YSIZE,
478: x = (x+dx+XSIZE00) % XSIZE,
479: size = size * 3 / 4 ) {
480: move(y+1,x*2,0);
481: beg_qwrite();
482: if (obj == base || obj->image == 'T') {
483: *filler = '@';
484: qwrite();
485: *filler = '#';
486: qwrite();
487: *filler = '~';
488: qwrite();
489: *filler = '%';
490: qwrite();
491: *filler = ':';
492: qwrite();
493: *filler = '@';
494: }
495: else {
496: *filler = size >= 500 ?
497: *curchar : (size >= 50 ?
498: curchar[1] :
499: curchar[2]);
500: }
501: qwrite();
502: if (occupant[y][x])
503: qaddc(occupant[y][x]->image);
504: else {
505: if (numamoebas)
506: qaddc(amb[y][x]);
507: else
508: qaddspace();
509: if (skipping)
510: skipping = 0;
511: }
512: end_qwrite();
513: }
514: if (size) {
515: char img;
516:
517: assert(occupant[y][x]);
518: img = occupant[y][x]->image;
519: if (occupant[y][x]->type == Crusher) {
520: if (dy)
521: return;
522: if (dx==(img == '<' ? 1 : -1) ) {
523: occupant[y][x]->image =
524: (occupant[y][x]->velx *= -1) < 0 ? '>' : '<';
525: return;
526: }
527: }
528: else if (occupant[y][x]->flags & FRIENDLY)
529: madfriends += 200;
530: if (numamoebas && amb[y][x] == '~' && smarts % 3 &&
531: (smarts > 70 || rand_mod(smarts) > rand_mod(20)) ) {
532: if (size > 10000)
533: modify_amoeba(y,x,1,'~',10);
534: else if (size > 1000)
535: modify_amoeba(y,x,1,'~',7);
536: else if (size > 50)
537: modify_amoeba(y,x,1,'~',5);
538: else
539: modify_amoeba(y,x,1,'~',2);
540: if (occupant[y][x] == nuke) {
541: nuke->strategy = rand_mod(30);
542: nuke->flags |= COUNTDOWN;
543: }
544: return;
545: }
546: else {
547: move(y+1,x*2,0);
548: beg_qwrite();
549: if (img == ' ') {
550: *filler = occupant[y][x]->flags & PIRATE ? 'P' : 'R';
551: occupant[y][x]->image = *filler;
552: occupant[y][x]->strategy = 0;
553: qwrite();
554: qwrite();
555: }
556: else if (img == 'C' || img == 'c') {
557: cloaked = 0;
558: img += 2;
559: occupant[y][x]->image = img;
560: *filler = img;
561: qwrite();
562: qwrite();
563: }
564: else if (img == 'K' && size > 50)
565: occupant[y][x]->strategy = 0;
566: *filler = '@';
567: qwrite();
568: *filler = '#';
569: qwrite();
570: *filler = '@';
571: qwrite();
572: *filler = '#';
573: qwrite();
574: *filler = '@';
575: qwrite();
576: qaddc(img);
577: end_qwrite();
578: oldy = y;
579: oldx = x;
580: y = (occupant[oldy][oldx]->posy + occupant[oldy][oldx]->vely +
581: YSIZE00) % YSIZE;
582: x = (occupant[oldy][oldx]->posx + occupant[oldy][oldx]->velx +
583: XSIZE00) % XSIZE;
584: if (occupant[y][x] && occupant[y][x]->type == Star) {
585: y = occupant[oldy][oldx]->posy;
586: x = occupant[oldy][oldx]->posx;
587: }
588: if (obj==base)
589: blast[y][x] += size>50 ? 15000 : (size>15 ? 1500 : 150);
590: else if (obj==ent)
591: blast[y][x] += size*4;
592: else if (obj->image=='T')
593: blast[y][x] += 15000;
594: else
595: blast[y][x] += size*smarts/25;
596: yblasted[y] |= 1;
597: xblasted[x] |= 1;
598: blasted = TRUE;
599: }
600: }
601: }
602: }
603:
604: int
605: tract(obj, dy, dx, to_or_fro)
606: Reg7 OBJECT *obj;
607: Reg4 int dy;
608: Reg5 int dx;
609: int to_or_fro;
610: {
611: Reg1 int y;
612: Reg2 int x;
613: Reg3 int size=10;
614: static char ch;
615: Reg6 OBJECT *tractee;
616:
617: if (!dy)
618: ch = '|';
619: else if (!dx)
620: ch = '-';
621: else if (dy == dx)
622: ch = '/';
623: else
624: ch = '\\';
625: {
626: for (
627: y = (obj->posy+dy+YSIZE00)%YSIZE,
628: x = (obj->posx+dx+XSIZE00)%XSIZE;
629: size && (!occupant[y][x]);
630: y = (y+dy+YSIZE00) % YSIZE, x = (x+dx+XSIZE00) % XSIZE, size--) {
631: move(y+1,x*2,0);
632: beg_qwrite();
633: *filler = ch;
634: qwrite();
635: qwrite();
636: if (numamoebas)
637: qaddch(amb[y][x]);
638: else
639: qaddspace();
640: end_qwrite();
641: }
642: tractee = occupant[y][x];
643: if (size) {
644: assert(tractee);
645: if (numamoebas && obj != nuke && amb[y][x] == '~') {
646: if (to_or_fro > 0)
647: modify_amoeba(y,x,2,'~',size);
648: else
649: modify_amoeba(y,x,1,' ',size);
650: }
651: if (tractee->type != Web &&
652: (tractee->mass < obj->mass * 5 ||
653: (tractee->type == Crusher && !dx) ) ) {
654: if (tractee == ent) {
655: evely -= dy * to_or_fro;
656: evelx -= dx * to_or_fro;
657: }
658: else if (tractee == base) {
659: bvely -= dy * to_or_fro;
660: bvelx -= dx * to_or_fro;
661: }
662: else {
663: tractee->vely -= dy * to_or_fro;
664: tractee->velx -= dx * to_or_fro;
665: }
666: if (tractee->type == Torp ||
667: tractee->type == Star) {
668: if (tractee->flags & STATIC) { /* not a mover? */
669: tractee->flags &= ~STATIC;
670: tractee->prev->next = tractee->next;
671: tractee->next->prev = tractee->prev;
672: root.prev->next = tractee;
673: tractee->prev = root.prev;
674: root.prev = tractee;
675: tractee->next = &root;
676: }
677: }
678: }
679: else if (tractee->type == Crusher && !dy &&
680: dx==(tractee->image == '<' ? 1 : -1) ) {
681: setimage(tractee, (tractee->velx *= -1) < 0 ? '>' : '<');
682: }
683: if (tractee->mass * 5 > obj->mass)
684: return(1);
685: }
686: }
687: return(0);
688: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.