xref: /dragonfly/games/robots/move.c (revision b40e316c)
1 /*
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  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  * @(#)move.c	8.1 (Berkeley) 5/31/93
34  * $FreeBSD: src/games/robots/move.c,v 1.6 1999/11/30 03:49:18 billf Exp $
35  * $DragonFly: src/games/robots/move.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
36  */
37 
38 #include <sys/ttydefaults.h>
39 #include <ctype.h>
40 #include "robots.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 	int	c;
51 	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 	} else
64 		lastmove = 0; /* Shut up gcc */
65 #endif
66 	for (;;) {
67 		if (Teleport && must_telep())
68 			goto teleport;
69 		if (Running)
70 			c = Run_ch;
71 		else if (Count != 0)
72 			c = Cnt_move;
73 #ifdef	FANCY
74 		else if (Num_robots > 1 && Stand_still)
75 			c = '>';
76 		else if (Num_robots > 1 && Pattern_roll) {
77 			if (*++Next_move == '\0') {
78 				if (lastmove < 0)
79 					goto over;
80 				Next_move = Move_list;
81 			}
82 			c = *Next_move;
83 			mvaddch(0, 0, c);
84 			if (c == lastmove)
85 				goto over;
86 		}
87 #endif
88 		else {
89 over:
90 			c = getchar();
91 			if (isdigit(c)) {
92 				Count = (c - '0');
93 				while (isdigit(c = getchar()))
94 					Count = Count * 10 + (c - '0');
95 				if (c == ESC)
96 					goto over;
97 				Cnt_move = c;
98 				if (Count)
99 					leaveok(stdscr, TRUE);
100 			}
101 		}
102 
103 		switch (c) {
104 		  case ' ':
105 		  case '.':
106 			if (do_move(0, 0))
107 				goto ret;
108 			break;
109 		  case 'y':
110 			if (do_move(-1, -1))
111 				goto ret;
112 			break;
113 		  case 'k':
114 			if (do_move(-1, 0))
115 				goto ret;
116 			break;
117 		  case 'u':
118 			if (do_move(-1, 1))
119 				goto ret;
120 			break;
121 		  case 'h':
122 			if (do_move(0, -1))
123 				goto ret;
124 			break;
125 		  case 'l':
126 			if (do_move(0, 1))
127 				goto ret;
128 			break;
129 		  case 'b':
130 			if (do_move(1, -1))
131 				goto ret;
132 			break;
133 		  case 'j':
134 			if (do_move(1, 0))
135 				goto ret;
136 			break;
137 		  case 'n':
138 			if (do_move(1, 1))
139 				goto ret;
140 			break;
141 		  case 'Y': case 'U': case 'H': case 'J':
142 		  case 'K': case 'L': case 'B': case 'N':
143 		  case '>':
144 			Running = TRUE;
145 			if (c == '>')
146 				Run_ch = ' ';
147 			else
148 				Run_ch = tolower(c);
149 			leaveok(stdscr, TRUE);
150 			break;
151 		  case 'q':
152 		  case 'Q':
153 			if (query("Really quit?"))
154 				quit();
155 			refresh();
156 			break;
157 		  case 'w':
158 		  case 'W':
159 			Waiting = TRUE;
160 			leaveok(stdscr, TRUE);
161 			/* flushok(stdscr, FALSE); */
162 			goto ret;
163 		  case 't':
164 		  case 'T':
165 teleport:
166 			Running = FALSE;
167 			mvaddch(My_pos.y, My_pos.x, ' ');
168 			My_pos = *rnd_pos();
169 			mvaddch(My_pos.y, My_pos.x, PLAYER);
170 			leaveok(stdscr, FALSE);
171 			refresh();
172 			flush_in();
173 			goto ret;
174 		  case CTRL('L'):
175 			wrefresh(curscr);
176 			break;
177 		  case EOF:
178 			break;
179 		  default:
180 			putchar(CTRL('G'));
181 			reset_count();
182 			fflush(stdout);
183 			break;
184 		}
185 	}
186 ret:
187 	if (Count > 0)
188 		if (--Count == 0)
189 			leaveok(stdscr, FALSE);
190 }
191 
192 /*
193  * must_telep:
194  *	Must I teleport; i.e., is there anywhere I can move without
195  * being eaten?
196  */
197 must_telep()
198 {
199 	int	x, y;
200 	static COORD	newpos;
201 
202 #ifdef	FANCY
203 	if (Stand_still && Num_robots > 1 && eaten(&My_pos))
204 		return TRUE;
205 #endif
206 
207 	for (y = -1; y <= 1; y++) {
208 		newpos.y = My_pos.y + y;
209 		if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE)
210 			continue;
211 		for (x = -1; x <= 1; x++) {
212 			newpos.x = My_pos.x + x;
213 			if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE)
214 				continue;
215 			if (Field[newpos.y][newpos.x] > 0)
216 				continue;
217 			if (!eaten(&newpos))
218 				return FALSE;
219 		}
220 	}
221 	return TRUE;
222 }
223 
224 /*
225  * do_move:
226  *	Execute a move
227  */
228 do_move(dy, dx)
229 int	dy, dx;
230 {
231 	static COORD	newpos;
232 
233 	newpos.y = My_pos.y + dy;
234 	newpos.x = My_pos.x + dx;
235 	if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE ||
236 	    newpos.x <= 0 || newpos.x >= X_FIELDSIZE ||
237 	    Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) {
238 		if (Running) {
239 			Running = FALSE;
240 			leaveok(stdscr, FALSE);
241 			move(My_pos.y, My_pos.x);
242 			refresh();
243 		}
244 		else {
245 			putchar(CTRL('G'));
246 			reset_count();
247 		}
248 		return FALSE;
249 	}
250 	else if (dy == 0 && dx == 0)
251 		return TRUE;
252 	mvaddch(My_pos.y, My_pos.x, ' ');
253 	My_pos = newpos;
254 	mvaddch(My_pos.y, My_pos.x, PLAYER);
255 	if (!jumping())
256 		refresh();
257 	return TRUE;
258 }
259 
260 /*
261  * eaten:
262  *	Player would get eaten at this place
263  */
264 eaten(pos)
265 COORD	*pos;
266 {
267 	int	x, y;
268 
269 	for (y = pos->y - 1; y <= pos->y + 1; y++) {
270 		if (y <= 0 || y >= Y_FIELDSIZE)
271 			continue;
272 		for (x = pos->x - 1; x <= pos->x + 1; x++) {
273 			if (x <= 0 || x >= X_FIELDSIZE)
274 				continue;
275 			if (Field[y][x] == 1)
276 				return TRUE;
277 		}
278 	}
279 	return FALSE;
280 }
281 
282 /*
283  * reset_count:
284  *	Reset the count variables
285  */
286 reset_count()
287 {
288 	Count = 0;
289 	Running = FALSE;
290 	leaveok(stdscr, FALSE);
291 	refresh();
292 }
293 
294 /*
295  * jumping:
296  *	See if we are jumping, i.e., we should not refresh.
297  */
298 jumping()
299 {
300 	return (Jump && (Count || Running || Waiting));
301 }
302