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
30void
31us_init(void)
32{
33    ;
34}
35
36void
37do_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
108void
109ctrl_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
133void
134shift_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
158void
159get_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
167top:
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