Merge from vendor branch PKGSRC:
[netbsd-mini2440.git] / games / robots / move.c
blob39a5eef39d8fdb09f90e1f0f3d39110c7645201f
1 /* $NetBSD: move.c,v 1.15 2009/07/20 06:39:06 dholland Exp $ */
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
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.15 2009/07/20 06:39:06 dholland Exp $");
38 #endif
39 #endif /* not lint */
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"
48 #define ESC '\033'
50 static bool do_move(int, int);
51 static bool eaten(const COORD *);
52 static bool must_telep(void);
55 * get_move:
56 * Get and execute a move from the player
58 void
59 get_move(void)
61 int c;
62 #ifdef FANCY
63 int lastmove;
64 #endif /*FANCY*/
66 if (Waiting)
67 return;
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;
94 c = *Next_move;
95 mvaddch(0, 0, c);
96 if (c == lastmove)
97 goto over;
99 #endif
100 else {
101 over:
102 if (Auto_bot) {
103 c = automove();
104 if (!Jump) {
105 usleep(10000);
106 refresh();
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);
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;
208 ret:
209 if (Count > 0)
210 if (--Count == 0)
211 leaveok(stdscr, FALSE);
215 * must_telep:
216 * Must I teleport; i.e., is there anywhere I can move without
217 * being eaten?
219 static bool
220 must_telep(void)
222 int x, y;
223 static COORD newpos;
225 #ifdef FANCY
226 if (Stand_still && Num_robots > 1 && eaten(&My_pos))
227 return true;
228 #endif
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;
244 return true;
248 * do_move:
249 * Execute a move
251 static bool
252 do_move(int dy, int dx)
254 static COORD newpos;
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();
267 else {
268 putchar(CTRL('G'));
269 reset_count();
271 return false;
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;
284 * eaten:
285 * Player would get eaten at this place
287 static bool
288 eaten(const COORD *pos)
290 int x, y;
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;
302 return false;
306 * reset_count:
307 * Reset the count variables
309 void
310 reset_count(void)
312 Count = 0;
313 Running = false;
314 leaveok(stdscr, FALSE);
315 refresh();
319 * jumping:
320 * See if we are jumping, i.e., we should not refresh.
322 bool
323 jumping(void)
325 return (Jump && (Count || Running || Waiting));