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.3 2006/08/27 21:45:07 pavalos Exp $ 36 */ 37 38 #include <sys/ttydefaults.h> 39 #include <ctype.h> 40 #include "robots.h" 41 42 # define ESC '\033' 43 44 static bool must_telep(void); 45 static bool do_move(int, int); 46 static bool eaten(COORD *); 47 48 /* 49 * get_move: 50 * Get and execute a move from the player 51 */ 52 void 53 get_move(void) 54 { 55 int c; 56 #ifdef FANCY 57 int lastmove; 58 #endif 59 if (Waiting) 60 return; 61 62 #ifdef FANCY 63 if (Pattern_roll) { 64 if (Next_move >= Move_list) 65 lastmove = *Next_move; 66 else 67 lastmove = -1; /* flag for "first time in" */ 68 } else 69 lastmove = 0; /* Shut up gcc */ 70 #endif 71 for (;;) { 72 if (Teleport && must_telep()) 73 goto teleport; 74 if (Running) 75 c = Run_ch; 76 else if (Count != 0) 77 c = Cnt_move; 78 #ifdef FANCY 79 else if (Num_robots > 1 && Stand_still) 80 c = '>'; 81 else if (Num_robots > 1 && Pattern_roll) { 82 if (*++Next_move == '\0') { 83 if (lastmove < 0) 84 goto over; 85 Next_move = Move_list; 86 } 87 c = *Next_move; 88 mvaddch(0, 0, c); 89 if (c == lastmove) 90 goto over; 91 } 92 #endif 93 else { 94 over: 95 c = getchar(); 96 if (isdigit(c)) { 97 Count = (c - '0'); 98 while (isdigit(c = getchar())) 99 Count = Count * 10 + (c - '0'); 100 if (c == ESC) 101 goto over; 102 Cnt_move = c; 103 if (Count) 104 leaveok(stdscr, TRUE); 105 } 106 } 107 108 switch (c) { 109 case ' ': 110 case '.': 111 if (do_move(0, 0)) 112 goto ret; 113 break; 114 case 'y': 115 if (do_move(-1, -1)) 116 goto ret; 117 break; 118 case 'k': 119 if (do_move(-1, 0)) 120 goto ret; 121 break; 122 case 'u': 123 if (do_move(-1, 1)) 124 goto ret; 125 break; 126 case 'h': 127 if (do_move(0, -1)) 128 goto ret; 129 break; 130 case 'l': 131 if (do_move(0, 1)) 132 goto ret; 133 break; 134 case 'b': 135 if (do_move(1, -1)) 136 goto ret; 137 break; 138 case 'j': 139 if (do_move(1, 0)) 140 goto ret; 141 break; 142 case 'n': 143 if (do_move(1, 1)) 144 goto ret; 145 break; 146 case 'Y': case 'U': case 'H': case 'J': 147 case 'K': case 'L': case 'B': case 'N': 148 case '>': 149 Running = TRUE; 150 if (c == '>') 151 Run_ch = ' '; 152 else 153 Run_ch = tolower(c); 154 leaveok(stdscr, TRUE); 155 break; 156 case 'q': 157 case 'Q': 158 if (query("Really quit?")) 159 quit(); 160 refresh(); 161 break; 162 case 'w': 163 case 'W': 164 Waiting = TRUE; 165 leaveok(stdscr, TRUE); 166 goto ret; 167 case 't': 168 case 'T': 169 teleport: 170 Running = FALSE; 171 mvaddch(My_pos.y, My_pos.x, ' '); 172 My_pos = *rnd_pos(); 173 mvaddch(My_pos.y, My_pos.x, PLAYER); 174 leaveok(stdscr, FALSE); 175 refresh(); 176 flush_in(); 177 goto ret; 178 case CTRL('L'): 179 wrefresh(curscr); 180 break; 181 case EOF: 182 break; 183 default: 184 putchar(CTRL('G')); 185 reset_count(); 186 fflush(stdout); 187 break; 188 } 189 } 190 ret: 191 if (Count > 0) 192 if (--Count == 0) 193 leaveok(stdscr, FALSE); 194 } 195 196 /* 197 * must_telep: 198 * Must I teleport; i.e., is there anywhere I can move without 199 * being eaten? 200 */ 201 static bool 202 must_telep(void) 203 { 204 int x, y; 205 static COORD newpos; 206 207 #ifdef FANCY 208 if (Stand_still && Num_robots > 1 && eaten(&My_pos)) 209 return TRUE; 210 #endif 211 212 for (y = -1; y <= 1; y++) { 213 newpos.y = My_pos.y + y; 214 if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE) 215 continue; 216 for (x = -1; x <= 1; x++) { 217 newpos.x = My_pos.x + x; 218 if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE) 219 continue; 220 if (Field[newpos.y][newpos.x] > 0) 221 continue; 222 if (!eaten(&newpos)) 223 return FALSE; 224 } 225 } 226 return TRUE; 227 } 228 229 /* 230 * do_move: 231 * Execute a move 232 */ 233 static bool 234 do_move(int dy, int dx) 235 { 236 static COORD newpos; 237 238 newpos.y = My_pos.y + dy; 239 newpos.x = My_pos.x + dx; 240 if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE || 241 newpos.x <= 0 || newpos.x >= X_FIELDSIZE || 242 Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) { 243 if (Running) { 244 Running = FALSE; 245 leaveok(stdscr, FALSE); 246 move(My_pos.y, My_pos.x); 247 refresh(); 248 } 249 else { 250 putchar(CTRL('G')); 251 reset_count(); 252 } 253 return FALSE; 254 } 255 else if (dy == 0 && dx == 0) 256 return TRUE; 257 mvaddch(My_pos.y, My_pos.x, ' '); 258 My_pos = newpos; 259 mvaddch(My_pos.y, My_pos.x, PLAYER); 260 if (!jumping()) 261 refresh(); 262 return TRUE; 263 } 264 265 /* 266 * eaten: 267 * Player would get eaten at this place 268 */ 269 static bool 270 eaten(COORD *pos) 271 { 272 int x, y; 273 274 for (y = pos->y - 1; y <= pos->y + 1; y++) { 275 if (y <= 0 || y >= Y_FIELDSIZE) 276 continue; 277 for (x = pos->x - 1; x <= pos->x + 1; x++) { 278 if (x <= 0 || x >= X_FIELDSIZE) 279 continue; 280 if (Field[y][x] == 1) 281 return TRUE; 282 } 283 } 284 return FALSE; 285 } 286 287 /* 288 * reset_count: 289 * Reset the count variables 290 */ 291 void 292 reset_count(void) 293 { 294 Count = 0; 295 Running = FALSE; 296 leaveok(stdscr, FALSE); 297 refresh(); 298 } 299 300 /* 301 * jumping: 302 * See if we are jumping, i.e., we should not refresh. 303 */ 304 bool 305 jumping(void) 306 { 307 return (Jump && (Count || Running || Waiting)); 308 } 309