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