/* * Request a "movement" direction (1,2,3,4,6,7,8,9) from the user. * * Return true if a direction was chosen, otherwise return false. * * This function should be used for all "repeatable" commands, such as * run, walk, open, close, bash, disarm, spike, tunnel, etc, as well * as all commands which must reference a grid adjacent to the player, * and which may not reference the grid under the player. * * Directions "5" and "0" are illegal and will not be accepted. * * This function tracks and uses the "global direction", and uses * that as the "desired direction", if it is set. */ public static bool get_rep_dir(out int dp) { int dir = 0; ui_event ke; /* Initialize */ dp = 0; /* Get a direction */ while (dir == 0) { /* Paranoia XXX XXX XXX */ Utilities.message_flush(); /* Get first keypress - the first test is to avoid displaying the prompt for direction if there's already a keypress queued up and waiting - this just avoids a flickering prompt if there is a "lazy" movement delay. */ Utilities.inkey_scan = Misc.SCAN_INSTANT; ke = Utilities.inkey_ex(); Utilities.inkey_scan = Misc.SCAN_OFF; if (ke.type == ui_event_type.EVT_NONE || (ke.type == ui_event_type.EVT_KBRD && Utilities.target_dir(ke.key) == 0)) { Utilities.prt("Direction or <click> (Escape to cancel)? ", 0, 0); ke = Utilities.inkey_ex(); } /* Check mouse coordinates */ if (ke.type == ui_event_type.EVT_MOUSE) { /*if (ke.button) */ { int y = Misc.KEY_GRID_Y(ke); int x = Misc.KEY_GRID_X(ke); Loc from = new Loc(Misc.p_ptr.px, Misc.p_ptr.py); Loc to = new Loc(x, y); throw new NotImplementedException(); //dir = pathfind_direction_to(from, to); } } /* Get other keypresses until a direction is chosen. */ else if (ke.type == ui_event_type.EVT_KBRD) { int keypresses_handled = 0; while (ke.type == ui_event_type.EVT_KBRD && ke.key.code != 0) { int this_dir; if (ke.key.code == keycode_t.ESCAPE) { /* Clear the prompt */ Utilities.prt("", 0, 0); return (false); } /* XXX Ideally show and move the cursor here to indicate the currently "Pending" direction. XXX */ this_dir = Utilities.target_dir(ke.key); if (this_dir != 0) dir = dir_transitions[dir][this_dir]; if (Misc.lazymove_delay == 0 || ++keypresses_handled > 1) break; Utilities.inkey_scan = Misc.lazymove_delay; ke = Utilities.inkey_ex(); } /* 5 is equivalent to "escape" */ if (dir == 5) { /* Clear the prompt */ Utilities.prt("", 0, 0); return (false); } } /* Oops */ if (dir == 0) Utilities.bell("Illegal repeatable direction!"); } /* Clear the prompt */ Utilities.prt("", 0, 0); /* Save direction */ dp = dir; /* Success */ return (true); }
/* Compute the direction (in the angband 123456789 sense) from a point to a * point. We decide to use diagonals if dx and dy are within a factor of two of * each other; otherwise we choose a cardinal direction. */ public static Direction direction_to(Loc from, Loc to) { int adx = Math.Abs(to.x - from.x); int ady = Math.Abs(to.y - from.y); int dx = to.x - from.x; int dy = to.y - from.y; if (dx == 0 && dy == 0) return Direction.NONE; if (dx >= 0 && dy >= 0) { if (adx < ady * 2 && ady < adx * 2) return Direction.NE; else if (adx > ady) return Direction.E; else return Direction.N; } else if (dx > 0 && dy < 0) { if (adx < ady * 2 && ady < adx * 2) return Direction.SE; else if (adx > ady) return Direction.E; else return Direction.S; } else if (dx < 0 && dy > 0) { if (adx < ady * 2 && ady < adx * 2) return Direction.NW; else if (adx > ady) return Direction.W; else return Direction.N; } else if (dx <= 0 && dy <= 0) { if (adx < ady * 2 && ady < adx * 2) return Direction.SW; else if (adx > ady) return Direction.W; else return Direction.S; } Misc.assert(false); return Direction.UNKNOWN; }
/* * Sorting hook -- comp function -- by "distance to player" * * We use "u" and "v" to point to arrays of "x" and "y" positions, * and sort the arrays by double-distance to the player. */ static int cmp_distance(Loc a, Loc b) { int py = Misc.p_ptr.py; int px = Misc.p_ptr.px; int da, db, kx, ky; /* Absolute distance components */ kx = a.x; kx -= px; kx = Math.Abs(kx); ky = a.y; ky -= py; ky = Math.Abs(ky); /* Approximate Double Distance to the first point */ da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx)); /* Absolute distance components */ kx = b.x; kx -= px; kx = Math.Abs(kx); ky = b.y; ky -= py; ky = Math.Abs(ky); /* Approximate Double Distance to the first point */ db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx)); /* Compare the distances */ if (da < db) return -1; if (da > db) return 1; return 0; }