]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - warp/move.c
5c6123ee9eba3b970892d107ec7c395fe4c8ba8e
[bsdgames-darwin.git] / warp / move.c
1 /* $Header: /cvsroot/src/games/warp/move.c,v 1.1 2020/11/09 23:37:05 kamil Exp $ */
2
3 /* $Log: move.c,v $
4 /* Revision 1.1 2020/11/09 23:37:05 kamil
5 /* Add Warp Kit, Version 7.0 by Larry Wall
6 /*
7 /* Warp is a real-time space war game that doesn't get boring very quickly.
8 /* Read warp.doc and the manual page for more information.
9 /*
10 /* games/warp originally distributed with 4.3BSD-Reno, is back to the BSD
11 /* world via NetBSD. Its remnants were still mentioned in games/Makefile.
12 /*
13 /* Larry Wall, the original author and the copyright holder, generously
14 /* donated the game and copyright to The NetBSD Foundation, Inc.
15 /*
16 /* Import the game sources as-is from 4.3BSD-Reno, with the cession
17 /* of the copyright and license to BSD-2-clause NetBSD-style.
18 /*
19 /* Signed-off-by: Larry Wall <larry@wall.org>
20 /* Signed-off-by: Kamil Rytarowski <kamil@netbsd.org>
21 /*
22 * Revision 7.0.1.2 86/10/20 14:37:06 lwall
23 * Picked some lint.
24 *
25 * Revision 7.0.1.1 86/10/16 10:52:09 lwall
26 * Added Damage. Fixed random bugs.
27 *
28 * Revision 7.0 86/10/08 15:12:40 lwall
29 * Split into separate files. Added amoebas and pirates.
30 *
31 */
32
33 #include "EXTERN.h"
34 #include "warp.h"
35 #include "bang.h"
36 #include "object.h"
37 #include "move.h"
38 #include "play.h"
39 #include "score.h"
40 #include "term.h"
41 #include "them.h"
42 #include "us.h"
43 #include "util.h"
44 #include "weapon.h"
45 #include "INTERN.h"
46 #include "move.h"
47
48 void
49 move_init()
50 {
51 ;
52 }
53
54 void
55 bounce(obj)
56 Reg4 OBJECT *obj;
57 {
58 Reg1 int x;
59 Reg2 int y;
60 Reg3 int count=0;
61
62 y = (obj->posy - sgn(obj->vely) + YSIZE00) % YSIZE;
63 x = (obj->posx - sgn(obj->velx) + XSIZE00) % XSIZE;
64 while (occupant[y][x]) {
65 y = (y + rand_mod(3) - 1 + YSIZE00) % YSIZE;
66 x = (x + rand_mod(3) - 1 + XSIZE00) % XSIZE;
67 if (++count > 10000) { /* if universe full, get out of it fast */
68 unmake_object(obj);
69 if (ent) unmake_object(ent);
70 if (base) unmake_object(base);
71 finish = 1;
72 return;
73 }
74 }
75 obj->posy = y;
76 obj->posx = x;
77 obj->vely = 0;
78 obj->velx = 0;
79 occupant[y][x] = obj;
80 if (numamoebas && obj->image == ' ')
81 mvaddc(y+1, x*2, amb[y][x]);
82 else
83 mvaddc(y+1, x*2, obj->image);
84 }
85
86 void
87 move_universe()
88 {
89 Reg1 OBJECT *curobj;
90 Reg2 int x;
91 Reg3 int y;
92 Reg4 OBJECT *temp;
93 OBJECT *thenext;
94
95 for (curobj = movers; curobj != &root; curobj = curobj->next) {
96 x = curobj->posx;
97 y = curobj->posy;
98 if (curobj == occupant[y][x]) {
99 occupant[y][x] = 0;
100 }
101 else if (curobj->type != Torp && curobj->type != Web) {
102 resetty();
103 abort();
104 }
105 }
106 for (curobj = movers; curobj != &root; curobj = thenext) {
107 thenext = curobj->next;
108 if (curobj->vely || curobj->velx) {
109 y = curobj->posy;
110 x = curobj->posx;
111 if (curobj->image != ' ' &&
112 (!(temp=occupant[y][x]) || temp->image==' ') ) {
113 move(y+1, x*2, numamoebas ? amb[y][x] : ' ');
114 }
115 y = (y + curobj->vely + YSIZE00) % YSIZE;
116 x = (x + curobj->velx + XSIZE00) % XSIZE;
117 if (!(temp=occupant[y][x]) || temp->type != Star ||
118 curobj->type != Torp || curobj->image == '+' ||
119 curobj->image == 'x') {
120 curobj->posy = y;
121 curobj->posx = x;
122 }
123 else {
124 if (curobj->image == '0') {
125 curobj->vely = rand_mod(3)-1;
126 curobj->velx = rand_mod(3)-1;
127 }
128 else
129 curobj->vely = curobj->velx = 0;
130 y = curobj->posy;
131 x = curobj->posx;
132 }
133 }
134 else { /* not moving */
135 y = curobj->posy;
136 x = curobj->posx;
137 if (curobj->type == Torp ||
138 curobj->type == Star ||
139 curobj->type == Web) {
140 curobj->flags |= STATIC;
141 curobj->next->prev = curobj->prev;
142 curobj->prev->next = curobj->next;
143 curobj->prev = movers->prev;
144 curobj->next = movers;
145 movers->prev->next = curobj;
146 movers->prev = curobj;
147 }
148 }
149 if (temp = occupant[y][x]) { /* already occupied? */
150 if (!temp->contend) {
151 if (temp->type == Torp) {
152 if (temp->image == '+')
153 blast[y][x] += 1250;
154 else if (temp->image == 'o' && (base||ent))
155 blast[y][x] += 500+super*20;
156 else if (temp->image == 'O' && (base||ent))
157 blast[y][x] += 5000+super*100;
158 }
159 }
160 yblasted[y] |= 1;
161 xblasted[x] |= 1;
162 blasted = TRUE;
163 curobj->contend = temp;
164 occupant[y][x] = curobj;
165 switch (curobj->type) {
166 case Enemy:
167 if (numamoebas && curobj == nuke && temp->image == '+')
168 blast[y][x] += 80000;
169 else if (temp->type == Enemy)
170 blast[y][x] += 10;
171 else
172 goto defblast;
173 break;
174 case Crusher:
175 if (curobj->velx)
176 blast[y][x] += 100000;
177 else
178 goto defblast;
179 break;
180 case Torp:
181 if (curobj->image == '+')
182 blast[y][x] += (temp==nuke ? 80000 : 1250);
183 else if (curobj->image == 'o')
184 blast[y][x] += 500+super*20;
185 else if (curobj->image == 'O')
186 blast[y][x] += 5000+super*100;
187 goto defblast;
188 case Star:
189 if (temp == ent)
190 goto damshield;
191 goto defblast;
192 case Enterprise:
193 if (temp->type == Star) {
194 damshield:
195 if (!rand_mod(10)) {
196 if (!damflag[NOSHIELDS])
197 damage++;
198 if (damflag[NOSHIELDS] < 100)
199 damflag[NOSHIELDS] += rand_mod(smarts)/5+2;
200 }
201 }
202 goto defblast;
203 default:
204 defblast:
205 blast[y][x] += rand_mod(751)+1;
206 break;
207 }
208 }
209 else {
210 occupant[y][x] = curobj;
211 if (curobj->image != ' ' &&
212 (curobj->velx || curobj->vely ||
213 curobj->type == Torp || curobj->type == Web) ) {
214 mvaddc(y+1, x*2, curobj->image);
215 }
216 if (curobj->type == Crusher && curobj->velx) {
217 blast[y][x] += 100000;
218 yblasted[y] |= 1;
219 xblasted[x] |= 1;
220 blasted = TRUE;
221 }
222 }
223 }
224 if (blasted) {
225 Reg7 int minxblast = -1;
226 Reg8 int maxxblast = -2;
227 Reg5 long tmpblast;
228
229 blasted = numamoebas;
230 for (x=0; x<XSIZE; x++) {
231 if (xblasted[x]) {
232 xblasted[x] = 0;
233 maxxblast = x;
234 if (minxblast < 0)
235 minxblast = x;
236 }
237 }
238 for (y=0; y<YSIZE; y++) {
239 if (yblasted[y]) {
240 yblasted[y] = 0;
241 for (x=minxblast; x<=maxxblast; x++) {
242 tmpblast = blast[y][x];
243 if (numamoebas && amb[y][x] == '~') {
244 if (temp = occupant[y][x]) {
245 if (temp->image == '&')
246 tmpblast >>= 1;
247 else if (temp->type == Web)
248 tmpblast = 100000;
249 else
250 tmpblast += 50 + temp->energy/100;
251 if (tmpblast > 250 && !rand_mod(5+(inumstars>>4)))
252 modify_amoeba(y,x,1,'~',5);
253 }
254 xblasted[x] = 2;
255 yblasted[y] = 2;
256 }
257 if (tmpblast) {
258 Reg6 OBJECT *biggie = 0;
259
260 blast[y][x] = 0;
261 temp = occupant[y][x];
262 if (tmpblast < 0) {
263 if (numamoebas && tmpblast < -1000000 &&
264 amb[y][x] == '~' && temp != nuke) {
265 amb[y][x] = ' ';
266 if (!temp)
267 make_plink(y,x);
268 ambsize--;
269 }
270 tmpblast = 0;
271 }
272 if (temp) {
273 if ((!numamoebas || amb[y][x]==' ') &&
274 tmpblast < 100000)
275 make_plink(y,x);
276 for ( ;temp;
277 temp = curobj->contend,curobj->contend = 0){
278 curobj = temp;
279 switch (curobj->type) {
280 case Enterprise: {
281 long tmp = curobj->energy;
282
283 if (ent->energy>500 || apolloflag & 1)
284 curobj->energy -= tmpblast /
285 ((apolloflag & 1)
286 ? 20
287 : (5+abs(ent->velx)+abs(ent->vely))
288 / ((damflag[NOSHIELDS]>>3)+1)+1);
289 else
290 curobj->energy -= tmpblast;
291 if (rand_mod(1 + tmp - curobj->energy) > 100
292 || ent->energy < (entmax>>1)) {
293 if (debug & 128 ||
294 (damage <= smarts/10 &&
295 !rand_mod(6-smarts/20-massacre) )) {
296 tmp = rand_mod(MAXDAMAGE);
297 if (damflag[tmp]) {
298 if (damflag[tmp] < 60)
299 damflag[tmp] += rand_mod(60);
300 }
301 else {
302 damflag[tmp] =
303 rand_mod(smarts+10)+2;
304 damage++;
305 }
306 }
307 }
308 break;
309 }
310 case Base:
311 if (base->energy > 1000 || apolloflag & 2)
312 curobj->energy -= tmpblast /
313 ((apolloflag & 2)?20:5);
314 else
315 curobj->energy -= tmpblast;
316 break;
317 case Crusher:
318 if (tmpblast > 132767)
319 curobj->energy -= (tmpblast - 100000);
320 else if (tmpblast >= 100000) {
321 curobj->energy += (tmpblast - 100000);
322 if (curobj->energy > 32767)
323 curobj->energy = 32767;
324 }
325 else /* vulnerable while feeding */
326 curobj->energy -= tmpblast;
327 break;
328 case Enemy:
329 curobj->energy -= tmpblast*10/enemshields;
330 break;
331 default:
332 curobj->energy -= tmpblast;
333 break;
334 }
335 if (curobj->energy < 0) { /* killed it? */
336 switch (curobj->image) {
337 case 'A':
338 tmpblast = 100000;
339 make_blast(y,x,8192L,1);
340 numapollos = apolloflag = 0;
341 numstars--;
342 numenemies--;
343 curscore += 5000;
344 deados = 0;
345 break;
346 case 'E': case 'e': case 'C': case 'c':
347 ent = 0;
348 numents--;
349 if (base)
350 status = 2;
351 else
352 status = 3;
353 deados = 0;
354 break;
355 case 'B': case 'b':
356 base = 0;
357 numbases--;
358 if (ent)
359 status = entmode;
360 else
361 status = 3;
362 deados = 0;
363 break;
364 case '&': {
365 int i, xxx, yyy;
366
367 for (i = 0; i < YSIZE; i++)
368 yblasted[i] &= 1;
369 for (i = 0; i < XSIZE; i++)
370 xblasted[i] &= 1;
371 numamoebas = 0; /* ignore amb[][] now */
372 for (yyy = 0; yyy < YSIZE; yyy++) {
373 for (xxx = 0; xxx < XSIZE; xxx++) {
374 if (amb[yyy][xxx] == '~' &&
375 !occupant[yyy][xxx]) {
376 mvaddch(yyy+1,xxx*2,' ');
377 }
378 }
379 }
380 numenemies--;
381 curscore += 10000;
382 if (curobj == enemies)
383 enemies = curobj->next;
384 deados = 0;
385 break;
386 }
387 case '<': case '>': {
388 int i;
389
390 numenemies--;
391 numcrushes = 0;
392 curscore += 10000;
393 if (curobj == movers)
394 movers = curobj->next;
395 if (curobj == enemies)
396 enemies = curobj->next;
397 deados = 0;
398
399 tmpblast = 100000;
400 make_blast(y,(x+XSIZE00)%XSIZE,10000L,0);
401 if (curobj->image == '<') {
402 for (i=XSIZE00; i<=XSIZE01; i++)
403 make_blast(y,(x+i)%XSIZE,
404 10000L,0);
405 for (i=XSIZE00; i<=XSIZE02; i++)
406 make_blast(y,(x+i)%XSIZE,
407 10000L,0);
408 make_blast(y,(x+XSIZE03)%XSIZE,
409 10000L,1);
410 for (i=XSIZE00; i<=XSIZE08; i++)
411 make_blast(y,(x+i)%XSIZE,
412 10000L,0);
413 }
414 else {
415 for (i=XSIZE00; i>=XSIZE99; i--)
416 make_blast(y,(x+i)%XSIZE,
417 10000L,0);
418 for (i=XSIZE00; i>=XSIZE98; i--)
419 make_blast(y,(x+i)%XSIZE,
420 10000L,0);
421 make_blast(y,(x+XSIZE97)%XSIZE,
422 10000L,1);
423 for (i=XSIZE00; i>=XSIZE92; i--)
424 make_blast(y,(x+i)%XSIZE,
425 10000L,0);
426 }
427 }
428 break;
429 case 'K':
430 numenemies--;
431 curscore += curobj->mass;
432 if (curobj == enemies)
433 enemies = curobj->next;
434 deados = 0;
435 break;
436 case 'T':
437 numenemies--;
438 curscore += curobj->mass*3/2;
439 if (curobj == enemies)
440 enemies = curobj->next;
441 deados = 0;
442 break;
443 case 'R': case ' ': case 'P':
444 numenemies--;
445 if (curobj->flags & PIRATE)
446 curscore += curobj->mass;
447 else
448 curscore += curobj->mass*3;
449 if (curobj == enemies)
450 enemies = curobj->next;
451 deados = 0;
452 break;
453 case 'G':
454 numenemies--;
455 numgorns--;
456 tmpblast = 100000;
457 if (madgorns)
458 curscore += curobj->mass/2;
459 else
460 curscore += curobj->mass*2;
461 if (curobj == enemies)
462 enemies = curobj->next;
463 {
464 int xxx,yyy;
465
466 for (xxx = -1; xxx<=1; xxx++)
467 for (yyy = -1; yyy<=1; yyy++)
468 if (rand_mod(2+massacre))
469 fire_torp(curobj,
470 yyy,xxx);
471 }
472 deados = 0;
473 break;
474 case '@':
475 numinhab--;
476 /* FALL THROUGH */
477 case '*':
478 banging = TRUE;
479 numstars--;
480 break;
481 case '|': case '-': case '/': case '\\':
482 tmpblast = 100000;
483 make_blast(y,x,curobj->mass,1);
484 banging = TRUE;
485 deados = 0;
486 break;
487 case 'x':
488 curscore += 10;
489 deados = 0;
490 break;
491 case 'X':
492 curscore += 100;
493 numxes--;
494 deados = 0;
495 break;
496 case '0':
497 curscore += 35;
498 numos--;
499 deados += 3;
500 break;
501 case 'o':
502 curscore += 100;
503 numos--;
504 deados++;
505 break;
506 case 'O':
507 curscore += 200;
508 numos--;
509 deados += 2;
510 break;
511 case 'M':
512 deadmudds++;
513 inumfriends--;
514 numfriends--;
515 if (curobj == enemies)
516 enemies = curobj->next;
517 break;
518 case 'Q': case 'W': case 'Y': case 'U':
519 case 'I': case 'S': case 'D': case 'H':
520 case 'J': case 'L': case 'Z': case 'V':
521 case 'F':
522 numfriends--;
523 if (curobj == enemies)
524 enemies = curobj->next;
525 if (inumfriends < 10)
526 madfriends += 500;
527 else
528 madfriends += 10000/inumfriends;
529 break;
530 }
531 if (tmpblast < 100000)
532 make_blast(y,x,curobj->mass,1);
533 unmake_object(curobj);
534 }
535 else { /* didn't kill anything */
536 if (!biggie)
537 biggie = curobj;
538 else {
539 if (biggie->mass > curobj->mass)
540 bounce(curobj);
541 else {
542 bounce(biggie);
543 biggie = curobj;
544 }
545 }
546 }
547 }
548 if (biggie) {
549 occupant[y][x] = biggie;
550 if (numamoebas && biggie->image == ' ')
551 mvaddch(y+1,x*2, amb[y][x]);
552 else
553 mvaddch(y+1,x*2, biggie->image);
554 }
555 else {
556 occupant[y][x] = 0;
557 mvaddch(y+1, x*2, numamoebas ? amb[y][x] : ' ');
558 }
559 }
560 }
561 }
562 }
563 }
564 }
565 do_bangs();
566 if (numcrushes && movers->type == Crusher)
567 movers->vely = 0;
568 if (curobj = base) {
569 char ch;
570
571 curobj->velx = 0;
572 curobj->vely = 0;
573 curobj->energy += 25*lookaround(curobj->posy,curobj->posx,Star);
574 if (curobj->energy > basemax)
575 curobj->energy = basemax;
576 if (curobj->energy >= 1000)
577 ch = 'B';
578 else
579 ch = 'b';
580 if (ch != curobj->image) {
581 setimage(curobj, ch);
582 }
583 }
584 if (curobj = ent) {
585 char ch;
586
587 if (entmode == 0) {
588 curobj->velx = 0;
589 curobj->vely = 0;
590 }
591 if (base && !cloaking && !curobj->velx && !curobj->vely &&
592 lookfor(curobj->posy,curobj->posx,Base)) {
593 int tmp;
594
595 #ifdef lint
596 tmp = 0;
597 #else
598 tmp = (int) (base->energy - 1000 < entmax - curobj->energy ?
599 base->energy - 1000 : entmax - curobj->energy);
600 #endif
601 if (tmp < 0)
602 tmp = 0;
603 curobj->energy += tmp;
604 base->energy -= tmp;
605 tmp = (btorp < 50 - etorp ?
606 btorp : 50 - etorp);
607 etorp += tmp;
608 btorp -= tmp;
609 if (damage) {
610 tmp = rand_mod(MAXDAMAGE);
611 if (damflag[tmp] > 5) {
612 damflag[tmp] = rand_mod(5)+1;
613 }
614 }
615 }
616 if (curobj->energy >= 500 && (!damage || !damflag[NOSHIELDS]))
617 ch = cloaked?'C':'E';
618 else
619 ch = cloaked?'c':'e';
620 if (ch != curobj->image) {
621 setimage(curobj, ch);
622 }
623 }
624 }
625
626 int
627 lookaround(y, x, what)
628 Reg1 int y;
629 Reg2 int x;
630 Reg4 char what;
631 {
632 Reg3 OBJECT *obj;
633 Reg5 int count=0;
634 Reg6 int xp;
635 Reg7 int xm;
636
637 if ((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what) /* 0, 1 */
638 count++;
639 if ((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what) /* 0, -1 */
640 count++;
641 if ((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what) /* -1, 1 */
642 count++;
643 if ((obj=occupant[y][x])&&obj->type == what) /* -1, 0 */
644 count++;
645 if ((obj=occupant[y][xm])&&obj->type == what) /* -1, -1 */
646 count++;
647 if ((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what) /* 1, 1 */
648 count++;
649 if ((obj=occupant[y][x])&&obj->type == what) /* 1, 0 */
650 count++;
651 if ((obj=occupant[y][xm])&&obj->type == what) /* 1, -1 */
652 count++;
653 return (count);
654 }
655
656 int
657 lookfor(y, x, what)
658 Reg1 int y;
659 Reg2 int x;
660 Reg4 char what;
661 {
662 Reg3 OBJECT *obj;
663 Reg5 int xp;
664 Reg6 int xm;
665
666 if ((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what ||/* 0, 1 */
667 (obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what ||/* 0, -1 */
668 (obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what ||/* -1, 1 */
669 (obj=occupant[y][x])&&obj->type == what ||/* -1, 0 */
670 (obj=occupant[y][xm])&&obj->type == what ||/* -1,-1 */
671 (obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what ||/* 1, 1 */
672 (obj=occupant[y][x])&&obj->type == what ||/* 1, 0 */
673 (obj=occupant[y][xm])&&obj->type == what) /* 1, -1 */
674 return(1);
675 return (0);
676 }
677
678 OBJECT*
679 lookimg(y, x, what)
680 Reg1 int y;
681 Reg2 int x;
682 Reg4 char what;
683 {
684 Reg3 OBJECT *obj;
685 Reg5 int xp;
686 Reg6 int xm;
687
688 if ((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->image==what ||/* 0, 1 */
689 (obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->image==what ||/* 0, -1 */
690 (obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->image==what ||/* -1, 1 */
691 (obj=occupant[y][x])&&obj->image==what ||/* -1, 0 */
692 (obj=occupant[y][xm])&&obj->image==what ||/* -1,-1 */
693 (obj=occupant[y=(y+2)%YSIZE][xp])&&obj->image==what ||/* 1, 1 */
694 (obj=occupant[y][x])&&obj->image==what ||/* 1, 0 */
695 (obj=occupant[y][xm])&&obj->image==what) /* 1, -1 */
696 return obj;
697 return Null(OBJECT*);
698 }