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