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