xref: /netbsd-src/games/warp/us.c (revision 1182a44c59cae4d586117d55eca24b4b8b173211)
1 /* Header: us.c,v 7.0.1.3 87/01/13 17:13:21 lwall Exp */
2 
3 /* Log:	us.c,v
4  * Revision 7.0.1.3  87/01/13  17:13:21  lwall
5  * Partially fixed ^S behavior.  It now just ignores ^S.
6  *
7  * Revision 7.0.1.2  86/12/12  17:06:09  lwall
8  * Baseline for net release.
9  *
10  * Revision 7.0.1.1  86/10/16  10:53:50  lwall
11  * Added Damage.  Fixed random bugs.
12  *
13  * Revision 7.0  86/10/08  15:14:21  lwall
14  * Split into separate files.  Added amoebas and pirates.
15  *
16  */
17 
18 #include "EXTERN.h"
19 #include "warp.h"
20 #include "bang.h"
21 #include "object.h"
22 #include "play.h"
23 #include "sig.h"
24 #include "term.h"
25 #include "util.h"
26 #include "weapon.h"
27 #include "INTERN.h"
28 #include "us.h"
29 
30 void
us_init(void)31 us_init(void)
32 {
33     ;
34 }
35 
36 void
do_direction(int dy,int dx)37 do_direction(int dy, int dx)
38 {
39     int decr;
40     OBJECT *obj;
41 
42     if (status < 2) {
43 	if (cloaking) {
44 	    char ch;
45 
46 	    cloaked = false;
47 	    ch = (ent->energy >= 500?'E':'e');
48 	    if (ch != ent->image) {
49 		setimage(ent, ch);
50 	    }
51 	}
52 	decr = 5+abs(evely)+abs(evelx)+tractor*tractor;
53 	if (ent->energy >= decr) {
54 	    ent->energy -= decr;
55 	    if (tractor) {
56 		if (!damage || !damflag[NOTRACTORS]) {
57 		    if (!rand_mod(50)) {
58 			damage++;
59 			damflag[NOTRACTORS] = rand_mod(smarts+10)+2;
60 		    }
61 		    if (tract(ent,dy,dx,tractor)) {
62 			evely += tractor*dy;
63 			evelx += tractor*dx;
64 		    }
65 		}
66 	    }
67 	    else if (!damage ||
68 	      (!entmode && !damflag[NOIMPULSE]) ||
69 	      (entmode && !damflag[NOWARP]) ) {
70 		if (!rand_mod(30+500/(abs(evely)+abs(evelx)+1))) {
71 		    damage++;
72 		    damflag[entmode?NOWARP:NOIMPULSE] = rand_mod(smarts+10)+2;
73 		}
74 		evely += dy;
75 		evelx += dx;
76 	    }
77 	    if (inumthols &&
78 	      (obj=occupant[(ent->posy+evely+YSIZE00)%YSIZE]
79 			   [(ent->posx+evelx+XSIZE00)%XSIZE] ) &&
80 	      obj->type == Web)
81 		evely = evelx = 0;
82 	}
83     }
84     else if (status == 2) {
85 	decr = 500+abs(bvely)*5+abs(bvelx)*5+tractor*tractor*100;
86 	if (base->energy >= decr) {
87 	    base->energy -= decr;
88 	    if (tractor) {
89 		if (tract(base,dy,dx,tractor)) {
90 		    bvely += tractor*dy;
91 		    bvelx += tractor*dx;
92 		}
93 	    }
94 	    else {
95 		bvely += dy;
96 		bvelx += dx;
97 	    }
98 	    if (inumthols &&
99 	      (obj=occupant[(base->posy+bvely+YSIZE00)%YSIZE]
100 			   [(base->posx+bvelx+XSIZE00)%XSIZE] ) &&
101 	      obj->type == Web)
102 		bvely = bvelx = 0;
103 	}
104     }
105     tractor = 0;
106 }
107 
108 void
ctrl_direction(int dy,int dx)109 ctrl_direction(int dy, int dx)
110 {
111     if (status < 2) {
112 	if (cloaking) {
113 	    char ch;
114 
115 	    cloaked = false;
116 	    ch = (ent->energy >= 500?'E':'e');
117 	    if (ch != ent->image) {
118 		setimage(ent, ch);
119 	    }
120 	}
121 	if (!damage || !damflag[NOPHASERS]) {
122 	    if (!rand_mod(200)) {
123 		damage++;
124 		damflag[NOPHASERS] = rand_mod(smarts+10)+2;
125 	    }
126 	    fire_phaser(ent, dy, dx);
127 	}
128     }
129     else if (status == 2)
130 	fire_phaser(base, dy, dx);
131 }
132 
133 void
shift_direction(int dy,int dx)134 shift_direction(int dy, int dx)
135 {
136     if (status < 2) {
137 	if (cloaking) {
138 	    char ch;
139 
140 	    cloaked = false;
141 	    ch = (ent->energy >= 500?'E':'e');
142 	    if (ch != ent->image) {
143 		setimage(ent, ch);
144 	    }
145 	}
146 	if (!damage || !damflag[NOTORPS]) {
147 	    if (!rand_mod(300)) {
148 		damage++;
149 		damflag[NOTORPS] = rand_mod(smarts+10)+2;
150 	    }
151 	    fire_torp(ent, dy, dx);
152 	}
153     }
154     else if (status == 2)
155 	fire_torp(base, dy, dx);
156 }
157 
158 void
get_commands(bool * done)159 get_commands(bool *done)
160 {
161     static char ch[80];
162     int i;
163     int count;
164     bool ctrla = false;
165     char numdestructs = 0, numzaps = 0;
166 
167 top:
168     while ((count = read_nd(ch,(sizeof ch)))) {
169 	for (i=0; i<count; i++) {
170 	    if (ch[i] == 'Q') {
171 		bombed_out = true;
172 		*done = true;
173 		keepgoing = false;
174 		return;
175 	    }
176 	    if (ch[i] == 'q' || ch[i] == BREAKCH || ch[i] == INTRCH) {
177 		int x;
178 		static char quest[] = "Do you wish to escape from reality? ";
179 
180 		if (timer >= whenok) {
181 		    mvaddstr(12,22,quest);
182 		    do {
183 			getcmd(&ch[i]);
184 		    } while (ch[i] != 'y' && ch[i] != 'n');
185 		    if (ch[i] == 'y') {
186 			bombed_out = true;
187 			*done = true;
188 			return;
189 		    }
190 		    else {
191 			for (x=11; x<=28; x++) {
192 			    mvaddch(12,x*2,
193 				occupant[11][x]
194 				   ? occupant[11][x]->image
195 				   : numamoebas
196 				      ? amb[11][x]
197 				      : ' ');
198 			    addspace();
199 			}
200 			roundsleep(2);
201 			whenok = timer + 10;
202 			goto top;
203 		    }
204 		}
205 		else {
206 		    write(1,"\07",1);
207 		    goto top;
208 		}
209 	    }
210 	}
211 	for (i=0; i<count; i++) {
212 	    if (ctrla) {
213 		switch (ch[i]) {
214 		case '1': case 'b':
215 		    ctrl_direction(1, -1);
216 		    break;
217 		case '2': case 'j':
218 		    ctrl_direction(1, 0);
219 		    break;
220 		case '3': case 'n':
221 		    ctrl_direction(1, 1);
222 		    break;
223 		case '4': case 'h':
224 		    ctrl_direction(0, -1);
225 		    break;
226 		case '6': case 'l':
227 		    ctrl_direction(0, 1);
228 		    break;
229 		case '7': case 'y':
230 		    ctrl_direction(-1, -1);
231 		    break;
232 		case '8': case 'k':
233 		    ctrl_direction(-1, 0);
234 		    break;
235 		case '9': case 'u':
236 		    ctrl_direction(-1, 1);
237 		    break;
238 		case 'r':
239 		    rewrite();
240 		    roundsleep(3);
241 		    ctrla = false;
242 		    goto top;
243 		case 'w':
244 		    clear();
245 		    while (!input_pending())
246 			sleep(1);
247 		    rewrite();
248 		    roundsleep(3);
249 		    ctrla = false;
250 		    goto top;
251 #ifdef SIGTSTP
252 		case 'z':
253 		    clear();
254 		    mytstp();
255 		    sleep(4);
256 		    ctrla = false;
257 		    goto top;
258 #endif
259 		default:
260 		    break;
261 		}
262 		ctrla = false;
263 	    }
264 	    else {
265 		switch (ch[i]) {
266 		case 'Z':
267 		    clear();
268 		    mytstp();
269 		    sleep(4);
270 		    goto top;
271 		case 'i':
272 		    if (ent && (!damage || !damflag[NOIMPULSE])) {
273 			entmode = 0;
274 			status = 0;
275 		    }
276 		    break;
277 		case 'w':
278 		    if (ent && (!damage || !damflag[NOWARP])) {
279 			entmode = 1;
280 			status = 1;
281 		    }
282 		    break;
283 		case 'p':
284 		    if (base) {
285 			status = 2;
286 		    }
287 		    break;
288 		case 'o':
289 		    if (status < 2) {
290 			if (base)
291 			    status = 2;
292 		    }
293 		    else if (status == 2) {
294 			if (ent)
295 			    status = entmode;
296 		    }
297 		    break;
298 		case 'v':
299 		    if (ent) {
300 			status = entmode;
301 		    }
302 		    cloaking=false;
303 		    cloaked=false;
304 		    break;
305 		case 'c':
306 		    if (ent) {
307 			status = entmode;
308 			if (ent->energy >= 250)
309 			    cloaking = true;
310 		    }
311 		    break;
312 		case 'z':
313 		    if (ent && (!damage || !damflag[NOZAPPER])) {
314 			++numzaps;
315 			if (!rand_mod(100/numzaps)) {
316 			    damage++;
317 			    damflag[NOZAPPER] = rand_mod(smarts+10)+2;
318 			}
319 			if (nxtbang && bangm[nxtbang-1] < 0)
320 			    --nxtbang;	/* consolidate zaps */
321 			make_blast(evely*2+ent->posy,evelx*2+ent->posx,
322 			    -5000000L, 3*numzaps);
323 			ent->energy /= 2;
324 		    }
325 		    break;
326 		case 'D':
327 		    if (status < 2 && (!damage || !damflag[NODESTRUCT])) {
328 			if (ent && !rand_mod(10)) {
329 			    damage++;
330 			    damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
331 			}
332 			if (++numdestructs <= 2)
333 			    make_blast(evely*2+ent->posy,evelx*2+ent->posx,
334 				15000L, 3);
335 			ent->energy /= 4;
336 		    }
337 		    else if (status == 2) {
338 			if (numdestructs)
339 			    base->energy = base->energy / 2;
340 			if (++numdestructs <= 2)
341 			    make_blast(base->posy, base->posx, 15000L, 5);
342 		    }
343 		    break;
344 		case 'd':
345 		    if ((!damage || !damflag[NODESTRUCT]) && (base||ent)) {
346 			OBJECT *obj;
347 			int x, y;
348 
349 			if (ent && !rand_mod(200)) {
350 			    damage++;
351 			    damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
352 			}
353 			for (obj = root.prev;
354 			  obj != &root;
355 			  obj = obj->prev) {
356 			    if (obj->image == '+') {
357 				blast[y=(obj->posy+obj->vely+YSIZE00)%YSIZE]
358 				     [x=(obj->posx+obj->velx+XSIZE00)%XSIZE]
359 				     += 1;
360 				yblasted[y] |= 1;
361 				xblasted[x] |= 1;
362 				blasted = true;
363 				obj->mass = (massacre?3000:4000);
364 			    }
365 			}
366 		    }
367 		    break;
368 		case 's':
369 		    if ((!damage || !damflag[NODESTRUCT]) && (base||ent)) {
370 			OBJECT *obj;
371 			if (ent && !rand_mod(200)) {
372 			    damage++;
373 			    damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
374 			}
375 			for (obj = root.prev;
376 			  obj->type == Torp || obj->type == Web ||
377 			  obj->type == Star;
378 			  obj = obj->prev) {
379 			    if (obj->image == '+')
380 				obj->vely = obj->velx = 0;
381 			}
382 		    }
383 		    break;
384 		case '\001':
385 		    ctrla = true;
386 		    break;
387 		case '\002':
388 		case '\003':
389 		case '\004':
390 		case '\005':
391 		case '\006':
392 		case '\007':
393 		case '\010':
394 		case '\011':
395 		case '\012':
396 		case '\013':
397 		case '\014':
398 		case '\015':
399 		case '\016':
400 		case '\017':
401 		case '\020':
402 		case '\021':
403 		case '\022':
404 		case '\023':
405 		case '\024':
406 		case '\025':
407 		case '\026':
408 		case '\027':
409 		case '\030':
410 		case '\031':
411 		case '\032':
412 		    ch[i] += 96;
413 		    i--;
414 		    ctrla = true;
415 		    break;
416 		case '\033':
417 		    tractor = 0;
418 		    break;
419 		case 'a':
420 		    tractor++;
421 		    break;
422 		case 'r':
423 		    tractor--;
424 		    break;
425 		case '1': case 'b':
426 		    do_direction(1,-1);
427 		    break;
428 		case '2': case 'j':
429 		    do_direction(1,0);
430 		    break;
431 		case '3': case 'n':
432 		    do_direction(1,1);
433 		    break;
434 		case '4': case 'h':
435 		    do_direction(0,-1);
436 		    break;
437 		case '6': case 'l':
438 		    do_direction(0,1);
439 		    break;
440 		case '7': case 'y':
441 		    do_direction(-1,-1);
442 		    break;
443 		case '8': case 'k':
444 		    do_direction(-1,0);
445 		    break;
446 		case '9': case 'u':
447 		    do_direction(-1,1);
448 		    break;
449 		case '0': case 'S':
450 		    if (status < 2) {
451 			evely = 0;
452 			evelx = 0;
453 		    }
454 		    break;
455 		case '-':
456 		    if (status < 2 && ent->energy >= 10) {
457 			evely *= -1;
458 			evelx *= -1;
459 			ent->energy -= 10;
460 		    }
461 		    break;
462 		case '%': case '\177': case '_':
463 		    shift_direction(0, -1);
464 		    shift_direction(0, 1);
465 		    shift_direction(-1, 0);
466 		    shift_direction(1, 0);
467 		    shift_direction(-1, -1);
468 		    shift_direction(-1, 1);
469 		    shift_direction(1, -1);
470 		    shift_direction(1, 1);
471 		    break;
472 		case '!': case 'B':
473 		    shift_direction(1, -1);
474 		    break;
475 		case '@': case 'J':
476 		    shift_direction(1, 0);
477 		    break;
478 		case '#': case 'N':
479 		    shift_direction(1, 1);
480 		    break;
481 		case '$': case 'H':
482 		    shift_direction(0, -1);
483 		    break;
484 		case '^': case 'L':
485 		    shift_direction(0, 1);
486 		    break;
487 		case '&': case 'Y':
488 		    shift_direction(-1, -1);
489 		    break;
490 		case '*': case 'K':
491 		    shift_direction(-1, 0);
492 		    break;
493 		case '(': case 'U':
494 		    shift_direction(-1, 1);
495 		    break;
496 		case '?':
497 		    helper();
498 		    roundsleep(3);
499 		    goto top;
500 		default:
501 		    break;
502 		}
503 	    }
504 	}
505     }
506 }
507