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