1 /* $NetBSD: move.c,v 1.10 2002/01/31 17:35:52 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)move.c 8.1 (Berkeley) 5/31/93"; 40 #else 41 __RCSID("$NetBSD: move.c,v 1.10 2002/01/31 17:35:52 christos Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include "robots.h" 46 47 # define ESC '\033' 48 49 /* 50 * get_move: 51 * Get and execute a move from the player 52 */ 53 void 54 get_move() 55 { 56 int c; 57 #ifdef FANCY 58 int lastmove; 59 #endif /*FANCY*/ 60 61 if (Waiting) 62 return; 63 64 #ifdef FANCY 65 if (Pattern_roll) { 66 if (Next_move >= Move_list) 67 lastmove = *Next_move; 68 else 69 lastmove = -1; /* flag for "first time in" */ 70 } else 71 lastmove = 0; /* Shut up gcc */ 72 #endif 73 for (;;) { 74 if (Teleport && must_telep()) 75 goto teleport; 76 if (Running) 77 c = Run_ch; 78 else if (Count != 0) 79 c = Cnt_move; 80 #ifdef FANCY 81 else if (Num_robots > 1 && Stand_still) 82 c = '>'; 83 else if (Num_robots > 1 && Pattern_roll) { 84 if (*++Next_move == '\0') { 85 if (lastmove < 0) 86 goto over; 87 Next_move = Move_list; 88 } 89 c = *Next_move; 90 mvaddch(0, 0, c); 91 if (c == lastmove) 92 goto over; 93 } 94 #endif 95 else { 96 over: 97 if (Auto_bot) 98 c = automove(); 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 wrefresh(curscr); 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