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 } 305