sh: Add simple tests for set -x and PS4.
[dragonfly.git] / games / robots / move.c
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. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)move.c   8.1 (Berkeley) 5/31/93
30  * $FreeBSD: src/games/robots/move.c,v 1.6 1999/11/30 03:49:18 billf Exp $
31  * $DragonFly: src/games/robots/move.c,v 1.3 2006/08/27 21:45:07 pavalos Exp $
32  */
33
34 #include <sys/ttydefaults.h>
35 #include <ctype.h>
36 #include "robots.h"
37
38 #define ESC     '\033'
39
40 static bool must_telep(void);
41 static bool do_move(int, int);
42 static bool eaten(COORD *);
43
44 /*
45  * get_move:
46  *      Get and execute a move from the player
47  */
48 void
49 get_move(void)
50 {
51         int c;
52 #ifdef FANCY
53         int lastmove;
54 #endif
55         if (Waiting)
56                 return;
57
58 #ifdef FANCY
59         if (Pattern_roll) {
60                 if (Next_move >= Move_list)
61                         lastmove = *Next_move;
62                 else
63                         lastmove = -1;  /* flag for "first time in" */
64         } else
65                 lastmove = 0; /* Shut up gcc */
66 #endif
67         for (;;) {
68                 if (Teleport && must_telep())
69                         goto teleport;
70                 if (Running)
71                         c = Run_ch;
72                 else if (Count != 0)
73                         c = Cnt_move;
74 #ifdef FANCY
75                 else if (Num_robots > 1 && Stand_still)
76                         c = '>';
77                 else if (Num_robots > 1 && Pattern_roll) {
78                         if (*++Next_move == '\0') {
79                                 if (lastmove < 0)
80                                         goto over;
81                                 Next_move = Move_list;
82                         }
83                         c = *Next_move;
84                         mvaddch(0, 0, c);
85                         if (c == lastmove)
86                                 goto over;
87                 }
88 #endif
89                 else {
90 over:
91                         c = getchar();
92                         if (isdigit(c)) {
93                                 Count = (c - '0');
94                                 while (isdigit(c = getchar()))
95                                         Count = Count * 10 + (c - '0');
96                                 if (c == ESC)
97                                         goto over;
98                                 Cnt_move = c;
99                                 if (Count)
100                                         leaveok(stdscr, true);
101                         }
102                 }
103
104                 switch (c) {
105                   case ' ':
106                   case '.':
107                         if (do_move(0, 0))
108                                 goto ret;
109                         break;
110                   case 'y':
111                         if (do_move(-1, -1))
112                                 goto ret;
113                         break;
114                   case 'k':
115                         if (do_move(-1, 0))
116                                 goto ret;
117                         break;
118                   case 'u':
119                         if (do_move(-1, 1))
120                                 goto ret;
121                         break;
122                   case 'h':
123                         if (do_move(0, -1))
124                                 goto ret;
125                         break;
126                   case 'l':
127                         if (do_move(0, 1))
128                                 goto ret;
129                         break;
130                   case 'b':
131                         if (do_move(1, -1))
132                                 goto ret;
133                         break;
134                   case 'j':
135                         if (do_move(1, 0))
136                                 goto ret;
137                         break;
138                   case 'n':
139                         if (do_move(1, 1))
140                                 goto ret;
141                         break;
142                   case 'Y': case 'U': case 'H': case 'J':
143                   case 'K': case 'L': case 'B': case 'N':
144                   case '>':
145                         Running = true;
146                         if (c == '>')
147                                 Run_ch = ' ';
148                         else
149                                 Run_ch = tolower(c);
150                         leaveok(stdscr, true);
151                         break;
152                   case 'q':
153                   case 'Q':
154                         if (query("Really quit?"))
155                                 quit();
156                         refresh();
157                         break;
158                   case 'w':
159                   case 'W':
160                         Waiting = true;
161                         leaveok(stdscr, true);
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 static bool
198 must_telep(void)
199 {
200         int x, y;
201         static COORD newpos;
202
203 #ifdef FANCY
204         if (Stand_still && Num_robots > 1 && eaten(&My_pos))
205                 return true;
206 #endif
207
208         for (y = -1; y <= 1; y++) {
209                 newpos.y = My_pos.y + y;
210                 if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE)
211                         continue;
212                 for (x = -1; x <= 1; x++) {
213                         newpos.x = My_pos.x + x;
214                         if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE)
215                                 continue;
216                         if (Field[newpos.y][newpos.x] > 0)
217                                 continue;
218                         if (!eaten(&newpos))
219                                 return false;
220                 }
221         }
222         return true;
223 }
224
225 /*
226  * do_move:
227  *      Execute a move
228  */
229 static bool
230 do_move(int dy, int dx)
231 {
232         static COORD newpos;
233
234         newpos.y = My_pos.y + dy;
235         newpos.x = My_pos.x + dx;
236         if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE ||
237             newpos.x <= 0 || newpos.x >= X_FIELDSIZE ||
238             Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) {
239                 if (Running) {
240                         Running = false;
241                         leaveok(stdscr, false);
242                         move(My_pos.y, My_pos.x);
243                         refresh();
244                 }
245                 else {
246                         putchar(CTRL('G'));
247                         reset_count();
248                 }
249                 return false;
250         }
251         else if (dy == 0 && dx == 0)
252                 return true;
253         mvaddch(My_pos.y, My_pos.x, ' ');
254         My_pos = newpos;
255         mvaddch(My_pos.y, My_pos.x, PLAYER);
256         if (!jumping())
257                 refresh();
258         return true;
259 }
260
261 /*
262  * eaten:
263  *      Player would get eaten at this place
264  */
265 static bool
266 eaten(COORD *pos)
267 {
268         int x, y;
269
270         for (y = pos->y - 1; y <= pos->y + 1; y++) {
271                 if (y <= 0 || y >= Y_FIELDSIZE)
272                         continue;
273                 for (x = pos->x - 1; x <= pos->x + 1; x++) {
274                         if (x <= 0 || x >= X_FIELDSIZE)
275                                 continue;
276                         if (Field[y][x] == 1)
277                                 return true;
278                 }
279         }
280         return false;
281 }
282
283 /*
284  * reset_count:
285  *      Reset the count variables
286  */
287 void
288 reset_count(void)
289 {
290         Count = 0;
291         Running = false;
292         leaveok(stdscr, false);
293         refresh();
294 }
295
296 /*
297  * jumping:
298  *      See if we are jumping, i.e., we should not refresh.
299  */
300 bool
301 jumping(void)
302 {
303         return (Jump && (Count || Running || Waiting));
304 }