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