Merge from vendor branch BSDTAR:
[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. 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 }