xref: /netbsd-src/games/robots/move.c (revision 4b30c543a0b21e3ba94f2c569e9a82b4fdb2075f)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 /*static char sccsid[] = "from: @(#)move.c	5.4 (Berkeley) 6/1/90";*/
36 static char rcsid[] = "$Id: move.c,v 1.3 1993/08/01 18:52:44 mycroft Exp $";
37 #endif /* not lint */
38 
39 # include	"robots.h"
40 # include	<ctype.h>
41 
42 # define	ESC	'\033'
43 
44 /*
45  * get_move:
46  *	Get and execute a move from the player
47  */
48 get_move()
49 {
50 	register int	c;
51 	register int	y, x, lastmove;
52 	static COORD	newpos;
53 
54 	if (Waiting)
55 		return;
56 
57 #ifdef	FANCY
58 	if (Pattern_roll) {
59 		if (Next_move >= Move_list)
60 			lastmove = *Next_move;
61 		else
62 			lastmove = -1;	/* flag for "first time in" */
63 	}
64 #endif
65 	for (;;) {
66 		if (Teleport && must_telep())
67 			goto teleport;
68 		if (Running)
69 			c = Run_ch;
70 		else if (Count != 0)
71 			c = Cnt_move;
72 #ifdef	FANCY
73 		else if (Num_robots > 1 && Stand_still)
74 			c = '>';
75 		else if (Num_robots > 1 && Pattern_roll) {
76 			if (*++Next_move == '\0') {
77 				if (lastmove < 0)
78 					goto over;
79 				Next_move = Move_list;
80 			}
81 			c = *Next_move;
82 			mvaddch(0, 0, c);
83 			if (c == lastmove)
84 				goto over;
85 		}
86 #endif
87 		else {
88 over:
89 			c = getchar();
90 			if (isdigit(c)) {
91 				Count = (c - '0');
92 				while (isdigit(c = getchar()))
93 					Count = Count * 10 + (c - '0');
94 				if (c == ESC)
95 					goto over;
96 				Cnt_move = c;
97 				if (Count)
98 					leaveok(stdscr, TRUE);
99 			}
100 		}
101 
102 		switch (c) {
103 		  case ' ':
104 		  case '.':
105 			if (do_move(0, 0))
106 				goto ret;
107 			break;
108 		  case 'y':
109 			if (do_move(-1, -1))
110 				goto ret;
111 			break;
112 		  case 'k':
113 			if (do_move(-1, 0))
114 				goto ret;
115 			break;
116 		  case 'u':
117 			if (do_move(-1, 1))
118 				goto ret;
119 			break;
120 		  case 'h':
121 			if (do_move(0, -1))
122 				goto ret;
123 			break;
124 		  case 'l':
125 			if (do_move(0, 1))
126 				goto ret;
127 			break;
128 		  case 'b':
129 			if (do_move(1, -1))
130 				goto ret;
131 			break;
132 		  case 'j':
133 			if (do_move(1, 0))
134 				goto ret;
135 			break;
136 		  case 'n':
137 			if (do_move(1, 1))
138 				goto ret;
139 			break;
140 		  case 'Y': case 'U': case 'H': case 'J':
141 		  case 'K': case 'L': case 'B': case 'N':
142 		  case '>':
143 			Running = TRUE;
144 			if (c == '>')
145 				Run_ch = ' ';
146 			else
147 				Run_ch = tolower(c);
148 			leaveok(stdscr, TRUE);
149 			break;
150 		  case 'q':
151 		  case 'Q':
152 			if (query("Really quit?"))
153 				quit();
154 			refresh();
155 			break;
156 		  case 'w':
157 		  case 'W':
158 			Waiting = TRUE;
159 			leaveok(stdscr, TRUE);
160 			flushok(stdscr, FALSE);
161 			goto ret;
162 		  case 't':
163 		  case 'T':
164 teleport:
165 			Running = FALSE;
166 			mvaddch(My_pos.y, My_pos.x, ' ');
167 			My_pos = *rnd_pos();
168 			mvaddch(My_pos.y, My_pos.x, PLAYER);
169 			leaveok(stdscr, FALSE);
170 			refresh();
171 			flush_in();
172 			goto ret;
173 		  case CTRL('L'):
174 			wrefresh(curscr);
175 			break;
176 		  case EOF:
177 			break;
178 		  default:
179 			putchar(CTRL('G'));
180 			reset_count();
181 			fflush(stdout);
182 			break;
183 		}
184 	}
185 ret:
186 	if (Count > 0)
187 		if (--Count == 0)
188 			leaveok(stdscr, FALSE);
189 }
190 
191 /*
192  * must_telep:
193  *	Must I teleport; i.e., is there anywhere I can move without
194  * being eaten?
195  */
196 must_telep()
197 {
198 	register int	x, y;
199 	static COORD	newpos;
200 
201 #ifdef	FANCY
202 	if (Stand_still && Num_robots > 1 && eaten(&My_pos))
203 		return TRUE;
204 #endif
205 
206 	for (y = -1; y <= 1; y++) {
207 		newpos.y = My_pos.y + y;
208 		if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE)
209 			continue;
210 		for (x = -1; x <= 1; x++) {
211 			newpos.x = My_pos.x + x;
212 			if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE)
213 				continue;
214 			if (Field[newpos.y][newpos.x] > 0)
215 				continue;
216 			if (!eaten(&newpos))
217 				return FALSE;
218 		}
219 	}
220 	return TRUE;
221 }
222 
223 /*
224  * do_move:
225  *	Execute a move
226  */
227 do_move(dy, dx)
228 int	dy, dx;
229 {
230 	static COORD	newpos;
231 
232 	newpos.y = My_pos.y + dy;
233 	newpos.x = My_pos.x + dx;
234 	if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE ||
235 	    newpos.x <= 0 || newpos.x >= X_FIELDSIZE ||
236 	    Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) {
237 		if (Running) {
238 			Running = FALSE;
239 			leaveok(stdscr, FALSE);
240 			move(My_pos.y, My_pos.x);
241 			refresh();
242 		}
243 		else {
244 			putchar(CTRL('G'));
245 			reset_count();
246 		}
247 		return FALSE;
248 	}
249 	else if (dy == 0 && dx == 0)
250 		return TRUE;
251 	mvaddch(My_pos.y, My_pos.x, ' ');
252 	My_pos = newpos;
253 	mvaddch(My_pos.y, My_pos.x, PLAYER);
254 	if (!jumping())
255 		refresh();
256 	return TRUE;
257 }
258 
259 /*
260  * eaten:
261  *	Player would get eaten at this place
262  */
263 eaten(pos)
264 register COORD	*pos;
265 {
266 	register int	x, y;
267 
268 	for (y = pos->y - 1; y <= pos->y + 1; y++) {
269 		if (y <= 0 || y >= Y_FIELDSIZE)
270 			continue;
271 		for (x = pos->x - 1; x <= pos->x + 1; x++) {
272 			if (x <= 0 || x >= X_FIELDSIZE)
273 				continue;
274 			if (Field[y][x] == 1)
275 				return TRUE;
276 		}
277 	}
278 	return FALSE;
279 }
280 
281 /*
282  * reset_count:
283  *	Reset the count variables
284  */
285 reset_count()
286 {
287 	Count = 0;
288 	Running = FALSE;
289 	leaveok(stdscr, FALSE);
290 	refresh();
291 }
292 
293 /*
294  * jumping:
295  *	See if we are jumping, i.e., we should not refresh.
296  */
297 jumping()
298 {
299 	return (Jump && (Count || Running || Waiting));
300 }
301