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