nrelease - fix/improve livecd
[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  */
32
33 #include <sys/ttydefaults.h>
34 #include <ctype.h>
35 #include "robots.h"
36
37 #define ESC     '\033'
38
39 static bool must_telep(void);
40 static bool do_move(int, int);
41 static bool eaten(COORD *);
42
43 /*
44  * get_move:
45  *      Get and execute a move from the player
46  */
47 void
48 get_move(void)
49 {
50         int c;
51 #ifdef FANCY
52         int lastmove;
53 #endif
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(0);
155                         refresh();
156                         break;
157                   case 'w':
158                   case 'W':
159                         Waiting = true;
160                         leaveok(stdscr, true);
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 static bool
197 must_telep(void)
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 static bool
229 do_move(int dy, int 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 static bool
265 eaten(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 void
287 reset_count(void)
288 {
289         Count = 0;
290         Running = false;
291         leaveok(stdscr, false);
292         refresh();
293 }
294
295 /*
296  * jumping:
297  *      See if we are jumping, i.e., we should not refresh.
298  */
299 bool
300 jumping(void)
301 {
302         return (Jump && (Count || Running || Waiting));
303 }