xref: /original-bsd/games/robots/move.c (revision 08be3570)
1 /*
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)move.c	8.1 (Berkeley) 05/31/93";
10 #endif /* not lint */
11 
12 #include <sys/ttydefaults.h>
13 #include <ctype.h>
14 #include "robots.h"
15 
16 # define	ESC	'\033'
17 
18 /*
19  * get_move:
20  *	Get and execute a move from the player
21  */
22 get_move()
23 {
24 	register int	c;
25 	register int	y, x, lastmove;
26 	static COORD	newpos;
27 
28 	if (Waiting)
29 		return;
30 
31 #ifdef	FANCY
32 	if (Pattern_roll) {
33 		if (Next_move >= Move_list)
34 			lastmove = *Next_move;
35 		else
36 			lastmove = -1;	/* flag for "first time in" */
37 	}
38 #endif
39 	for (;;) {
40 		if (Teleport && must_telep())
41 			goto teleport;
42 		if (Running)
43 			c = Run_ch;
44 		else if (Count != 0)
45 			c = Cnt_move;
46 #ifdef	FANCY
47 		else if (Num_robots > 1 && Stand_still)
48 			c = '>';
49 		else if (Num_robots > 1 && Pattern_roll) {
50 			if (*++Next_move == '\0') {
51 				if (lastmove < 0)
52 					goto over;
53 				Next_move = Move_list;
54 			}
55 			c = *Next_move;
56 			mvaddch(0, 0, c);
57 			if (c == lastmove)
58 				goto over;
59 		}
60 #endif
61 		else {
62 over:
63 			c = getchar();
64 			if (isdigit(c)) {
65 				Count = (c - '0');
66 				while (isdigit(c = getchar()))
67 					Count = Count * 10 + (c - '0');
68 				if (c == ESC)
69 					goto over;
70 				Cnt_move = c;
71 				if (Count)
72 					leaveok(stdscr, TRUE);
73 			}
74 		}
75 
76 		switch (c) {
77 		  case ' ':
78 		  case '.':
79 			if (do_move(0, 0))
80 				goto ret;
81 			break;
82 		  case 'y':
83 			if (do_move(-1, -1))
84 				goto ret;
85 			break;
86 		  case 'k':
87 			if (do_move(-1, 0))
88 				goto ret;
89 			break;
90 		  case 'u':
91 			if (do_move(-1, 1))
92 				goto ret;
93 			break;
94 		  case 'h':
95 			if (do_move(0, -1))
96 				goto ret;
97 			break;
98 		  case 'l':
99 			if (do_move(0, 1))
100 				goto ret;
101 			break;
102 		  case 'b':
103 			if (do_move(1, -1))
104 				goto ret;
105 			break;
106 		  case 'j':
107 			if (do_move(1, 0))
108 				goto ret;
109 			break;
110 		  case 'n':
111 			if (do_move(1, 1))
112 				goto ret;
113 			break;
114 		  case 'Y': case 'U': case 'H': case 'J':
115 		  case 'K': case 'L': case 'B': case 'N':
116 		  case '>':
117 			Running = TRUE;
118 			if (c == '>')
119 				Run_ch = ' ';
120 			else
121 				Run_ch = tolower(c);
122 			leaveok(stdscr, TRUE);
123 			break;
124 		  case 'q':
125 		  case 'Q':
126 			if (query("Really quit?"))
127 				quit();
128 			refresh();
129 			break;
130 		  case 'w':
131 		  case 'W':
132 			Waiting = TRUE;
133 			leaveok(stdscr, TRUE);
134 			flushok(stdscr, FALSE);
135 			goto ret;
136 		  case 't':
137 		  case 'T':
138 teleport:
139 			Running = FALSE;
140 			mvaddch(My_pos.y, My_pos.x, ' ');
141 			My_pos = *rnd_pos();
142 			mvaddch(My_pos.y, My_pos.x, PLAYER);
143 			leaveok(stdscr, FALSE);
144 			refresh();
145 			flush_in();
146 			goto ret;
147 		  case CTRL('L'):
148 			wrefresh(curscr);
149 			break;
150 		  case EOF:
151 			break;
152 		  default:
153 			putchar(CTRL('G'));
154 			reset_count();
155 			fflush(stdout);
156 			break;
157 		}
158 	}
159 ret:
160 	if (Count > 0)
161 		if (--Count == 0)
162 			leaveok(stdscr, FALSE);
163 }
164 
165 /*
166  * must_telep:
167  *	Must I teleport; i.e., is there anywhere I can move without
168  * being eaten?
169  */
170 must_telep()
171 {
172 	register int	x, y;
173 	static COORD	newpos;
174 
175 #ifdef	FANCY
176 	if (Stand_still && Num_robots > 1 && eaten(&My_pos))
177 		return TRUE;
178 #endif
179 
180 	for (y = -1; y <= 1; y++) {
181 		newpos.y = My_pos.y + y;
182 		if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE)
183 			continue;
184 		for (x = -1; x <= 1; x++) {
185 			newpos.x = My_pos.x + x;
186 			if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE)
187 				continue;
188 			if (Field[newpos.y][newpos.x] > 0)
189 				continue;
190 			if (!eaten(&newpos))
191 				return FALSE;
192 		}
193 	}
194 	return TRUE;
195 }
196 
197 /*
198  * do_move:
199  *	Execute a move
200  */
201 do_move(dy, dx)
202 int	dy, dx;
203 {
204 	static COORD	newpos;
205 
206 	newpos.y = My_pos.y + dy;
207 	newpos.x = My_pos.x + dx;
208 	if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE ||
209 	    newpos.x <= 0 || newpos.x >= X_FIELDSIZE ||
210 	    Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) {
211 		if (Running) {
212 			Running = FALSE;
213 			leaveok(stdscr, FALSE);
214 			move(My_pos.y, My_pos.x);
215 			refresh();
216 		}
217 		else {
218 			putchar(CTRL('G'));
219 			reset_count();
220 		}
221 		return FALSE;
222 	}
223 	else if (dy == 0 && dx == 0)
224 		return TRUE;
225 	mvaddch(My_pos.y, My_pos.x, ' ');
226 	My_pos = newpos;
227 	mvaddch(My_pos.y, My_pos.x, PLAYER);
228 	if (!jumping())
229 		refresh();
230 	return TRUE;
231 }
232 
233 /*
234  * eaten:
235  *	Player would get eaten at this place
236  */
237 eaten(pos)
238 register COORD	*pos;
239 {
240 	register int	x, y;
241 
242 	for (y = pos->y - 1; y <= pos->y + 1; y++) {
243 		if (y <= 0 || y >= Y_FIELDSIZE)
244 			continue;
245 		for (x = pos->x - 1; x <= pos->x + 1; x++) {
246 			if (x <= 0 || x >= X_FIELDSIZE)
247 				continue;
248 			if (Field[y][x] == 1)
249 				return TRUE;
250 		}
251 	}
252 	return FALSE;
253 }
254 
255 /*
256  * reset_count:
257  *	Reset the count variables
258  */
259 reset_count()
260 {
261 	Count = 0;
262 	Running = FALSE;
263 	leaveok(stdscr, FALSE);
264 	refresh();
265 }
266 
267 /*
268  * jumping:
269  *	See if we are jumping, i.e., we should not refresh.
270  */
271 jumping()
272 {
273 	return (Jump && (Count || Running || Waiting));
274 }
275