1 /* $NetBSD: move.c,v 1.15 2009/07/20 06:39:06 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)move.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 __RCSID("$NetBSD: move.c,v 1.15 2009/07/20 06:39:06 dholland Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/types.h> 42 #include <sys/ttydefaults.h> /* for CTRL */ 43 #include <ctype.h> 44 #include <curses.h> 45 #include <unistd.h> 46 #include "robots.h" 47 48 #define ESC '\033' 49 50 /* 51 * get_move: 52 * Get and execute a move from the player 53 */ 54 void 55 get_move(void) 56 { 57 int c; 58 #ifdef FANCY 59 int lastmove; 60 #endif /*FANCY*/ 61 62 if (Waiting) 63 return; 64 65 #ifdef FANCY 66 if (Pattern_roll) { 67 if (Next_move >= Move_list) 68 lastmove = *Next_move; 69 else 70 lastmove = -1; /* flag for "first time in" */ 71 } else 72 lastmove = 0; /* Shut up gcc */ 73 #endif 74 for (;;) { 75 if (Teleport && must_telep()) 76 goto teleport; 77 if (Running) 78 c = Run_ch; 79 else if (Count != 0) 80 c = Cnt_move; 81 #ifdef FANCY 82 else if (Num_robots > 1 && Stand_still) 83 c = '>'; 84 else if (Num_robots > 1 && Pattern_roll) { 85 if (*++Next_move == '\0') { 86 if (lastmove < 0) 87 goto over; 88 Next_move = Move_list; 89 } 90 c = *Next_move; 91 mvaddch(0, 0, c); 92 if (c == lastmove) 93 goto over; 94 } 95 #endif 96 else { 97 over: 98 if (Auto_bot) { 99 c = automove(); 100 if (!Jump) { 101 usleep(10000); 102 refresh(); 103 } 104 } else 105 c = getchar(); 106 if (isdigit(c)) { 107 Count = (c - '0'); 108 while (isdigit(c = getchar())) 109 Count = Count * 10 + (c - '0'); 110 if (c == ESC) 111 goto over; 112 Cnt_move = c; 113 if (Count) 114 leaveok(stdscr, TRUE); 115 } 116 } 117 118 switch (c) { 119 case ' ': 120 case '.': 121 if (do_move(0, 0)) 122 goto ret; 123 break; 124 case 'y': 125 if (do_move(-1, -1)) 126 goto ret; 127 break; 128 case 'k': 129 if (do_move(-1, 0)) 130 goto ret; 131 break; 132 case 'u': 133 if (do_move(-1, 1)) 134 goto ret; 135 break; 136 case 'h': 137 if (do_move(0, -1)) 138 goto ret; 139 break; 140 case 'l': 141 if (do_move(0, 1)) 142 goto ret; 143 break; 144 case 'b': 145 if (do_move(1, -1)) 146 goto ret; 147 break; 148 case 'j': 149 if (do_move(1, 0)) 150 goto ret; 151 break; 152 case 'n': 153 if (do_move(1, 1)) 154 goto ret; 155 break; 156 case 'Y': case 'U': case 'H': case 'J': 157 case 'K': case 'L': case 'B': case 'N': 158 case '>': 159 Running = true; 160 if (c == '>') 161 Run_ch = ' '; 162 else 163 Run_ch = tolower(c); 164 leaveok(stdscr, TRUE); 165 break; 166 case 'q': 167 case 'Q': 168 if (query("Really quit?")) 169 quit(0); 170 refresh(); 171 break; 172 case 'w': 173 case 'W': 174 Waiting = true; 175 leaveok(stdscr, TRUE); 176 goto ret; 177 case 't': 178 case 'T': 179 teleport: 180 Running = false; 181 mvaddch(My_pos.y, My_pos.x, ' '); 182 My_pos = *rnd_pos(); 183 telmsg(1); 184 refresh(); 185 sleep(1); 186 telmsg(0); 187 mvaddch(My_pos.y, My_pos.x, PLAYER); 188 leaveok(stdscr, FALSE); 189 refresh(); 190 flush_in(); 191 goto ret; 192 case CTRL('L'): 193 refresh(); 194 break; 195 case EOF: 196 break; 197 default: 198 putchar(CTRL('G')); 199 reset_count(); 200 fflush(stdout); 201 break; 202 } 203 } 204 ret: 205 if (Count > 0) 206 if (--Count == 0) 207 leaveok(stdscr, FALSE); 208 } 209 210 /* 211 * must_telep: 212 * Must I teleport; i.e., is there anywhere I can move without 213 * being eaten? 214 */ 215 bool 216 must_telep(void) 217 { 218 int x, y; 219 static COORD newpos; 220 221 #ifdef FANCY 222 if (Stand_still && Num_robots > 1 && eaten(&My_pos)) 223 return true; 224 #endif 225 226 for (y = -1; y <= 1; y++) { 227 newpos.y = My_pos.y + y; 228 if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE) 229 continue; 230 for (x = -1; x <= 1; x++) { 231 newpos.x = My_pos.x + x; 232 if (newpos.x <= 0 || newpos.x >= X_FIELDSIZE) 233 continue; 234 if (Field[newpos.y][newpos.x] > 0) 235 continue; 236 if (!eaten(&newpos)) 237 return false; 238 } 239 } 240 return true; 241 } 242 243 /* 244 * do_move: 245 * Execute a move 246 */ 247 bool 248 do_move(int dy, int dx) 249 { 250 static COORD newpos; 251 252 newpos.y = My_pos.y + dy; 253 newpos.x = My_pos.x + dx; 254 if (newpos.y <= 0 || newpos.y >= Y_FIELDSIZE || 255 newpos.x <= 0 || newpos.x >= X_FIELDSIZE || 256 Field[newpos.y][newpos.x] > 0 || eaten(&newpos)) { 257 if (Running) { 258 Running = false; 259 leaveok(stdscr, FALSE); 260 move(My_pos.y, My_pos.x); 261 refresh(); 262 } 263 else { 264 putchar(CTRL('G')); 265 reset_count(); 266 } 267 return false; 268 } 269 else if (dy == 0 && dx == 0) 270 return true; 271 mvaddch(My_pos.y, My_pos.x, ' '); 272 My_pos = newpos; 273 mvaddch(My_pos.y, My_pos.x, PLAYER); 274 if (!jumping()) 275 refresh(); 276 return true; 277 } 278 279 /* 280 * eaten: 281 * Player would get eaten at this place 282 */ 283 bool 284 eaten(const COORD *pos) 285 { 286 int x, y; 287 288 for (y = pos->y - 1; y <= pos->y + 1; y++) { 289 if (y <= 0 || y >= Y_FIELDSIZE) 290 continue; 291 for (x = pos->x - 1; x <= pos->x + 1; x++) { 292 if (x <= 0 || x >= X_FIELDSIZE) 293 continue; 294 if (Field[y][x] == 1) 295 return true; 296 } 297 } 298 return false; 299 } 300 301 /* 302 * reset_count: 303 * Reset the count variables 304 */ 305 void 306 reset_count(void) 307 { 308 Count = 0; 309 Running = false; 310 leaveok(stdscr, FALSE); 311 refresh(); 312 } 313 314 /* 315 * jumping: 316 * See if we are jumping, i.e., we should not refresh. 317 */ 318 bool 319 jumping(void) 320 { 321 return (Jump && (Count || Running || Waiting)); 322 } 323