summaryrefslogtreecommitdiffstats
path: root/stone_soup/crawl-ref/source/direct.cc
diff options
context:
space:
mode:
Diffstat (limited to 'stone_soup/crawl-ref/source/direct.cc')
-rw-r--r--stone_soup/crawl-ref/source/direct.cc1503
1 files changed, 0 insertions, 1503 deletions
diff --git a/stone_soup/crawl-ref/source/direct.cc b/stone_soup/crawl-ref/source/direct.cc
deleted file mode 100644
index 753adf3207..0000000000
--- a/stone_soup/crawl-ref/source/direct.cc
+++ /dev/null
@@ -1,1503 +0,0 @@
-/*
- * File: direct.cc
- * Summary: Functions used when picking squares.
- * Written by: Linley Henzell
- *
- * Change History (most recent first):
- *
- * <5> 01/08/01 GDL complete rewrite of direction()
- * <4> 11/23/99 LRH Looking at monsters now
- * displays more info
- * <3> 5/12/99 BWR changes to allow for space selection of target.
- * CR, ESC, and 't' in targeting.
- * <2> 5/09/99 JDJ look_around no longer prints a prompt.
- * <1> -/--/-- LRH Created
- */
-
-#include "AppHdr.h"
-#include "direct.h"
-
-#include <cstdarg>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifdef DOS
-#include <conio.h>
-#endif
-
-#include "externs.h"
-
-#include "debug.h"
-#include "describe.h"
-#include "itemname.h"
-#include "monstuff.h"
-#include "mon-util.h"
-#include "player.h"
-#include "shopping.h"
-#include "stuff.h"
-#include "spells4.h"
-#include "stash.h"
-#include "travel.h"
-#include "view.h"
-
-#ifdef USE_MACROS
-#include "macro.h"
-#endif
-
-enum LOSSelect
-{
- LOS_ANY = 0x00,
-
- // Check only visible squares
- LOS_VISIBLE = 0x01,
-
- // Check only hidden squares
- LOS_HIDDEN = 0x02,
-
- LOS_VISMASK = 0x03,
-
- // Flip from visible to hidden when going forward,
- // or hidden to visible when going backwards.
- LOS_FLIPVH = 0x20,
-
- // Flip from hidden to visible when going forward,
- // or visible to hidden when going backwards.
- LOS_FLIPHV = 0x40,
-
- LOS_NONE = 0xFFFF
-};
-
-// x and y offsets in the following order:
-// SW, S, SE, W, E, NW, N, NE
-static const char xcomp[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
-static const char ycomp[9] = { 1, 1, 1, 0, 0, 0, -1, -1, -1 };
-
-// [dshaligram] Removed . and 5 from dirchars so it's easier to
-// special case them.
-static const char dirchars[19] = { "b1j2n3h4bbl6y7k8u9" };
-static const char DOSidiocy[10] = { "OPQKSMGHI" };
-static const char *aim_prompt = "Aim (move cursor or -/+/=, change mode with CTRL-F, select with . or >)";
-
-static void describe_feature(int mx, int my, bool oos);
-static void describe_cell(int mx, int my);
-
-static bool find_object( int x, int y, int mode );
-static bool find_monster( int x, int y, int mode );
-static bool find_feature( int x, int y, int mode );
-static char find_square( unsigned char xps, unsigned char yps,
- FixedVector<char, 2> &mfp, char direction,
- bool (*targ)(int, int, int),
- int mode = TARG_ANY,
- bool wrap = false,
- int los = LOS_ANY);
-
-static bool is_mapped(int x, int y)
-{
- return (is_player_mapped(x, y));
-}
-
-//---------------------------------------------------------------
-//
-// direction
-//
-// input: restricts : DIR_NONE accepts keypad dir or targetting
-// DIR_TARGET must use targetting.
-// DIR_DIR must use keypad direction
-//
-//
-// outputs: dist structure:
-//
-// isValid a valid target or direction was chosen
-// isCancel player hit 'escape'
-// isTarget targetting was used
-// tx,ty target x,y or logical beam extension to
-// edge of map if keypad direction used.
-// dx,dy direction delta if keypad used {-1,0,1}
-//
-// SYNOPSIS:
-//
-// gets a direction, or any of the follwing:
-//
-// * go to targetting mode
-// +,= go to targetting mode, next monster
-// - " , prev monster
-// t,p auto-select previous target
-//
-//
-// targetting mode is handled by look_around()
-//---------------------------------------------------------------
-void direction( struct dist &moves, int restrict, int mode )
-{
- bool dirChosen = false;
- bool targChosen = false;
- int dir = 0;
-
- // init
- moves.isValid = false;
- moves.isTarget = false;
- moves.isMe = false;
- moves.isCancel = false;
- moves.dx = moves.dy = 0;
- moves.tx = moves.ty = 0;
-
- // XXX. this is ALWAYS in relation to the player. But a bit of a hack
- // nonetheless! --GDL
- gotoxy( VIEW_CX + 1, VIEW_CY );
-
- int keyin = getchm(KC_TARGETING);
-
- if (keyin == 0) // DOS idiocy (emulated by win32 console)
- {
- keyin = getchm(KC_TARGETING); // grrr.
- if (keyin == '*')
- {
- targChosen = true;
- dir = 0;
- }
- else
- {
- if (strchr(DOSidiocy, keyin) == NULL)
- return;
- dirChosen = true;
- dir = (int)(strchr(DOSidiocy, keyin) - DOSidiocy);
- }
- }
- else
- {
- if (strchr( dirchars, keyin ) != NULL)
- {
- dirChosen = true;
- dir = (int)(strchr(dirchars, keyin) - dirchars) / 2;
- }
- else
- {
- switch (keyin)
- {
- case CONTROL('F'):
- mode = (mode + 1) % TARG_NUM_MODES;
-
- snprintf( info, INFO_SIZE, "Targeting mode is now: %s",
- (mode == TARG_ANY) ? "any" :
- (mode == TARG_ENEMY) ? "enemies"
- : "friends" );
-
- mpr( info );
-
- targChosen = true;
- dir = 0;
- break;
-
- case '-':
- targChosen = true;
- dir = -1;
- break;
-
- case '*':
- targChosen = true;
- dir = 0;
- break;
-
- case ';':
- targChosen = true;
- dir = -3;
- break;
-
- case '\'':
- targChosen = true;
- dir = -2;
- break;
-
- case '+':
- case '=':
- targChosen = true;
- dir = 1;
- break;
-
- case 't':
- case 'p':
- targChosen = true;
- dir = 2;
- break;
-
- case '.':
- case '5':
- dirChosen = true;
- dir = 4;
- break;
-
- case ESCAPE:
- moves.isCancel = true;
- return;
-
- default:
- break;
- }
- }
- }
-
- // at this point, we know exactly the input - validate
- if (!(targChosen || dirChosen) || (targChosen && restrict == DIR_DIR))
- {
- mpr("What an unusual direction.");
- return;
- }
-
- // special case: they typed a dir key, but they're in target-only mode
- if (dirChosen && restrict == DIR_TARGET)
- {
- mpr(aim_prompt);
- look_around( moves, false, dir, mode );
- return;
- }
-
- if (targChosen)
- {
- if (dir < 2)
- {
- mpr(aim_prompt);
- moves.prev_target = dir;
- look_around( moves, false, -1, mode );
- if (moves.prev_target != -1) // -1 means they pressed 'p'
- return;
- }
-
- // chose to aim at previous target. do we have one?
- if (you.prev_targ == MHITNOT || you.prev_targ == MHITYOU)
- {
- mpr("You haven't got a target.");
- return;
- }
-
- // we have a valid previous target (maybe)
- struct monsters *montarget = &menv[you.prev_targ];
-
- if (!mons_near(montarget) || !player_monster_visible( montarget ))
- {
- mpr("You can't see that creature any more.");
- return;
- }
- else
- {
- moves.isValid = true;
- moves.isTarget = true;
- moves.tx = montarget->x;
- moves.ty = montarget->y;
- }
- return;
- }
-
- // at this point, we have a direction, and direction is allowed.
- moves.isValid = true;
- moves.isTarget = false;
- moves.dx = xcomp[dir];
- moves.dy = ycomp[dir];
- if (xcomp[dir] == 0 && ycomp[dir] == 0)
- moves.isMe = true;
-
- // now the tricky bit - extend the target x,y out to map edge.
- int mx, my;
- mx = my = 0;
-
- if (moves.dx > 0)
- mx = (GXM - 1) - you.x_pos;
- if (moves.dx < 0)
- mx = you.x_pos;
-
- if (moves.dy > 0)
- my = (GYM - 1) - you.y_pos;
- if (moves.dy < 0)
- my = you.y_pos;
-
- if (!(mx == 0 || my == 0))
- {
- if (mx < my)
- my = mx;
- else
- mx = my;
- }
- moves.tx = you.x_pos + moves.dx * mx;
- moves.ty = you.y_pos + moves.dy * my;
-}
-
-// Attempts to describe a square that's not in line-of-sight. If
-// there's a stash on the square, announces the top item and number
-// of items, otherwise, if there's a stair that's in the travel
-// cache and noted in the Dungeon (O)verview, names the stair.
-static void describe_oos_square(int x, int y)
-{
- if (!is_mapped(x, y))
- return;
-
-#ifdef STASH_TRACKING
- describe_stash(x, y);
-#endif
- describe_feature(x, y, true);
-}
-
-//---------------------------------------------------------------
-//
-// look_around
-//
-// Accessible by the x key and when using cursor aiming. Lets you
-// find out what symbols mean, and is the way to access monster
-// descriptions.
-//
-// input: dist.prev_target : -1 is last monster
-// 0 is no monster selected
-// 1 is next monster
-//
-// input: first_move is -1 if no initial cursor move, otherwise
-// make 1 move in that direction.
-//
-//
-// output: if dist.prev_target is -1 on OUTPUT, it means that
-// player selected 'p' ot 't' for last targetted monster.
-//
-// otherwise, usual dist fields are filled in (dx and dy are
-// always zero coming back from this function)
-//
-//---------------------------------------------------------------
-
-void look_around(struct dist &moves, bool justLooking, int first_move, int mode)
-{
- int keyin = 0;
- bool dirChosen = false;
- bool targChosen = false;
- int dir = 0;
- int cx = VIEW_CX;
- int cy = VIEW_CY;
- int newcx, newcy;
- int mx, my; // actual map x,y (scratch)
- int mid; // monster id (scratch)
- FixedVector < char, 2 > monsfind_pos;
- FixedVector < char, 2 > objfind_pos;
-
- monsfind_pos[0] = objfind_pos[0] = you.x_pos;
- monsfind_pos[1] = objfind_pos[1] = you.y_pos;
-
- message_current_target();
-
- // setup initial keystroke
- if (first_move >= 0)
- keyin = (int)'1' + first_move;
- if (moves.prev_target == -1)
- keyin = '-';
- if (moves.prev_target == 1)
- keyin = '+';
- if (moves.prev_target == -2)
- keyin = '\'';
- if (moves.prev_target == -3)
- keyin = ';';
- // reset
- moves.prev_target = 0;
-
- // loop until some exit criteria reached
- while(true)
- {
- dirChosen = false;
- targChosen = false;
- newcx = cx;
- newcy = cy;
-
- // move cursor to current position
- gotoxy(cx+1, cy);
-
- if (keyin == 0)
- keyin = getchm(KC_TARGETING);
-
- // [dshaligram] Classic Crawl behaviour was to use space to select
- // targets when targeting. The patch changed the meaning of space
- // from 'confirm' to 'cancel', which surprised some folks. I'm now
- // arbitrarily defining space as 'cancel' for look-around, and
- // 'confirm' for targeting.
- if (!justLooking && keyin == ' ')
- keyin = '\r';
-
- // DOS idiocy
- if (keyin == 0)
- {
- // get the extended key
- keyin = getchm(KC_TARGETING);
-
- // look for CR - change to '5' to indicate selection
- if (keyin == 13)
- keyin = 'S';
-
- if (strchr(DOSidiocy, keyin) == NULL)
- break;
- dirChosen = true;
- dir = (int)(strchr(DOSidiocy, keyin) - DOSidiocy);
- }
- else
- {
- if (strchr(dirchars, keyin) != NULL)
- {
- dirChosen = true;
- dir = (int)(strchr(dirchars, keyin) - dirchars) / 2;
- }
- else
- {
- // handle non-directional keys
- switch (keyin)
- {
- case CONTROL('F'):
- mode = (mode + 1) % TARG_NUM_MODES;
-
- snprintf( info, INFO_SIZE, "Targeting mode is now: %s",
- (mode == TARG_ANY) ? "any" :
- (mode == TARG_ENEMY) ? "enemies"
- : "friends" );
-
- mpr( info );
- targChosen = true;
- break;
-
- case '^':
- case '\t':
- case '\\':
- case '_':
- case '<':
- case '>':
- {
- if (find_square( cx, cy, objfind_pos, 1,
- find_feature, keyin, true,
- Options.target_los_first
- ? LOS_FLIPVH : LOS_ANY))
- {
- newcx = objfind_pos[0];
- newcy = objfind_pos[1];
- }
- else
- flush_input_buffer( FLUSH_ON_FAILURE );
- targChosen = true;
- break;
- }
- case ';':
- case '/':
- case '\'':
- case '*':
- {
- dir = keyin == ';' || keyin == '/'? -1 : 1;
- if (find_square( cx, cy, objfind_pos, dir,
- find_object, 0, true,
- Options.target_los_first
- ? (dir == 1? LOS_FLIPVH : LOS_FLIPHV)
- : LOS_ANY))
-
- {
- newcx = objfind_pos[0];
- newcy = objfind_pos[1];
- }
- else
- flush_input_buffer( FLUSH_ON_FAILURE );
- targChosen = true;
- break;
- }
-
- case '-':
- case '+':
- case '=':
- {
- dir = keyin == '-'? -1 : 1;
- if (find_square( cx, cy, monsfind_pos, dir,
- find_monster, mode, Options.target_wrap ))
- {
- newcx = monsfind_pos[0];
- newcy = monsfind_pos[1];
- }
- else
- flush_input_buffer( FLUSH_ON_FAILURE );
- targChosen = true;
- break;
- }
-
- case 't':
- case 'p':
- moves.prev_target = -1;
- break;
-
- case '?':
- targChosen = true;
- mx = you.x_pos + cx - VIEW_CX;
- my = you.y_pos + cy - VIEW_CY;
- mid = mgrd[mx][my];
-
- if (mid == NON_MONSTER)
- break;
-
-#if (!DEBUG_DIAGNOSTICS)
- if (!player_monster_visible( &menv[mid] ))
- break;
-#endif
-
- describe_monsters( menv[ mid ].type, mid );
- redraw_screen();
- mesclr( true );
- // describe the cell again.
- describe_cell(view2gridX(cx), view2gridY(cy));
- break;
-
- case '\r':
- case '\n':
- case '.':
- case '5':
- // If we're in look-around mode, and the cursor is on
- // the character and there's a valid travel target
- // within the viewport, jump to that target.
- if (justLooking && cx == VIEW_CX && cy == VIEW_CY)
- {
- if (you.travel_x > 0 && you.travel_y > 0)
- {
- int nx = grid2viewX(you.travel_x);
- int ny = grid2viewY(you.travel_y);
- if (in_viewport_bounds(nx, ny))
- {
- newcx = nx;
- newcy = ny;
- targChosen = true;
- }
- }
- }
- else
- {
- dirChosen = true;
- dir = 4;
- }
- break;
-
- case ' ':
- case ESCAPE:
- moves.isCancel = true;
- mesclr( true );
- return;
-
- default:
- break;
- }
- }
- }
-
- // now we have parsed the input character completely. Reset & Evaluate:
- keyin = 0;
- if (!targChosen && !dirChosen)
- break;
-
- // check for SELECTION
- if (dirChosen && dir == 4)
- {
- // [dshaligram] We no longer vet the square coordinates if
- // we're justLooking. By not vetting the coordinates, we make 'x'
- // look_around() nicer for travel purposes.
- if (!justLooking)
- {
- // RULE: cannot target what you cannot see
- if (!in_vlos(cx, cy))
- {
- // if (!justLooking)
- mpr("Sorry, you can't target what you can't see.");
- return;
- }
- }
-
- moves.isValid = true;
- moves.isTarget = true;
- moves.tx = you.x_pos + cx - VIEW_CX;
- moves.ty = you.y_pos + cy - VIEW_CY;
-
- if (moves.tx == you.x_pos && moves.ty == you.y_pos)
- moves.isMe = true;
- else
- {
- // try to set you.previous target
- mx = you.x_pos + cx - VIEW_CX;
- my = you.y_pos + cy - VIEW_CY;
- mid = mgrd[mx][my];
-
- if (mid == NON_MONSTER)
- break;
-
- if (!player_monster_visible( &(menv[mid]) ))
- break;
-
- you.prev_targ = mid;
- }
- break;
- }
-
- // check for MOVE
- if (dirChosen)
- {
- newcx = cx + xcomp[dir];
- newcy = cy + ycomp[dir];
- }
-
- // bounds check for newcx, newcy
- if (newcx < VIEW_SX) newcx = VIEW_SX;
- if (newcx > VIEW_EX) newcx = VIEW_EX;
- if (newcy < VIEW_SY) newcy = VIEW_SY;
- if (newcy > VIEW_EY) newcy = VIEW_EY;
-
- // no-op if the cursor doesn't move.
- if (newcx == cx && newcy == cy)
- continue;
-
- // CURSOR MOVED - describe new cell.
- cx = newcx;
- cy = newcy;
- mesclr( true );
- if (!in_vlos(cx, cy))
- {
- mpr("You can't see that place.");
- describe_oos_square(you.x_pos + cx - VIEW_CX,
- you.y_pos + cy - VIEW_CY);
- continue;
- }
- describe_cell(you.x_pos + cx - VIEW_CX, you.y_pos + cy - VIEW_CY);
- } // end WHILE
-
- mesclr( true );
-} // end look_around()
-
-bool in_vlos(int x, int y)
-{
- return in_los_bounds(x, y)
- && (env.show[x - LOS_SX][y] || (x == VIEW_CX && y == VIEW_CY));
-}
-
-bool in_los(int x, int y)
-{
- const int tx = x + VIEW_CX - you.x_pos,
- ty = y + VIEW_CY - you.y_pos;
-
- if (!in_los_bounds(tx, ty))
- return (false);
-
- return (x == you.x_pos && y == you.y_pos) || env.show[tx - LOS_SX][ty];
-}
-
-static bool find_monster( int x, int y, int mode )
-{
- const int targ_mon = mgrd[ x ][ y ];
- return (targ_mon != NON_MONSTER
- && in_los(x, y)
- && player_monster_visible( &(menv[targ_mon]) )
- && !mons_is_mimic( menv[targ_mon].type )
- && (mode == TARG_ANY
- || (mode == TARG_FRIEND && mons_friendly( &menv[targ_mon] ))
- || (mode == TARG_ENEMY
- && !mons_friendly( &menv[targ_mon] )
- &&
- (Options.target_zero_exp ||
- !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )) )));
-}
-
-static bool find_feature( int x, int y, int mode )
-{
- // The stair need not be in LOS if the square is mapped.
- if (!in_los(x, y) && (!Options.target_oos || !is_mapped(x, y)))
- return (false);
-
- return is_feature(mode, x, y);
-}
-
-static bool find_object(int x, int y, int mode)
-{
- const int item = igrd[x][y];
- // The square need not be in LOS if the stash tracker knows this item.
- return (item != NON_ITEM
- && (in_los(x, y)
-#ifdef STASH_TRACKING
- || (Options.target_oos && is_mapped(x, y) && is_stash(x, y))
-#endif
- ));
-}
-
-static int next_los(int dir, int los, bool wrap)
-{
- if (los == LOS_ANY)
- return (wrap? los : LOS_NONE);
-
- bool vis = los & LOS_VISIBLE;
- bool hidden = los & LOS_HIDDEN;
- bool flipvh = los & LOS_FLIPVH;
- bool fliphv = los & LOS_FLIPHV;
-
- if (!vis && !hidden)
- vis = true;
-
- if (wrap)
- {
- if (!flipvh && !fliphv)
- return (los);
-
- // We have to invert flipvh and fliphv if we're wrapping. Here's
- // why:
- //
- // * Say the cursor is on the last item in LOS, there are no
- // items outside LOS, and wrap == true. flipvh is true.
- // * We set wrap false and flip from visible to hidden, but there
- // are no hidden items. So now we need to flip back to visible
- // so we can go back to the first item in LOS. Unless we set
- // fliphv, we can't flip from hidden to visible.
- //
- los = flipvh? LOS_FLIPHV : LOS_FLIPVH;
- }
- else
- {
- if (!flipvh && !fliphv)
- return (LOS_NONE);
-
- if (flipvh && vis != (dir == 1))
- return (LOS_NONE);
-
- if (fliphv && vis == (dir == 1))
- return (LOS_NONE);
- }
-
- los = (los & ~LOS_VISMASK) | (vis? LOS_HIDDEN : LOS_VISIBLE);
- return (los);
-}
-
-bool in_viewport_bounds(int x, int y)
-{
- return (x >= VIEW_SX && x <= VIEW_EX && y >= VIEW_SY && y <= VIEW_EY);
-}
-
-bool in_los_bounds(int x, int y)
-{
- return !(x > LOS_EX || x < LOS_SX || y > LOS_EY || y < LOS_SY);
-}
-
-//---------------------------------------------------------------
-//
-// find_square
-//
-// Finds the next monster/object/whatever (moving in a spiral
-// outwards from the player, so closer targets are chosen first;
-// starts to player's left) and puts its coordinates in mfp.
-// Returns 1 if it found something, zero otherwise. If direction
-// is -1, goes backwards.
-//
-// If the game option target_zero_exp is true, zero experience
-// monsters will be targeted.
-//
-//---------------------------------------------------------------
-static char find_square( unsigned char xps, unsigned char yps,
- FixedVector<char, 2> &mfp, char direction,
- bool (*find_targ)( int x, int y, int mode ),
- int mode, bool wrap, int los )
-{
- int temp_xps = xps;
- int temp_yps = yps;
- char x_change = 0;
- char y_change = 0;
-
- bool onlyVis = false, onlyHidden = false;
-
- int i, j;
-
- if (los == LOS_NONE)
- return (0);
-
- if (los == LOS_FLIPVH || los == LOS_FLIPHV)
- {
- if (in_los_bounds(xps, yps))
- {
- // We've been told to flip between visible/hidden, so we
- // need to find what we're currently on.
- bool vis = (env.show[xps - 8][yps]
- || (xps == VIEW_CX && yps == VIEW_CY));
-
- if (wrap && (vis != (los == LOS_FLIPVH)) == (direction == 1))
- {
- // We've already flipped over into the other direction,
- // so correct the flip direction if we're wrapping.
- los = los == LOS_FLIPHV? LOS_FLIPVH : LOS_FLIPHV;
- }
-
- los = (los & ~LOS_VISMASK) | (vis? LOS_VISIBLE : LOS_HIDDEN);
- }
- else
- {
- if (wrap)
- los = LOS_HIDDEN | (direction == 1? LOS_FLIPHV : LOS_FLIPVH);
- else
- los |= LOS_HIDDEN;
- }
- }
-
- onlyVis = (los & LOS_VISIBLE);
- onlyHidden = (los & LOS_HIDDEN);
-
- const int minx = VIEW_SX, maxx = VIEW_EX,
- miny = VIEW_SY - VIEW_Y_DIFF, maxy = VIEW_EY + VIEW_Y_DIFF,
- ctrx = VIEW_CX, ctry = VIEW_CY;
-
- while (temp_xps >= minx - 1 && temp_xps <= maxx
- && temp_yps <= maxy && temp_yps >= miny - 1)
- {
- if (direction == 1 && temp_xps == minx && temp_yps == maxy)
- {
- return find_square(ctrx, ctry, mfp, direction, find_targ, mode,
- false, next_los(direction, los, wrap));
- }
- if (direction == -1 && temp_xps == ctrx && temp_yps == ctry)
- {
- return find_square(minx, maxy, mfp, direction, find_targ, mode,
- false, next_los(direction, los, wrap));
- }
-
- if (direction == 1)
- {
- if (temp_xps == minx - 1)
- {
- x_change = 0;
- y_change = -1;
- }
- else if (temp_xps == ctrx && temp_yps == ctry)
- {
- x_change = -1;
- y_change = 0;
- }
- else if (abs(temp_xps - ctrx) <= abs(temp_yps - ctry))
- {
- if (temp_xps - ctrx >= 0 && temp_yps - ctry <= 0)
- {
- if (abs(temp_xps - ctrx) > abs(temp_yps - ctry + 1))
- {
- x_change = 0;
- y_change = -1;
- if (temp_xps - ctrx > 0)
- y_change = 1;
- goto finished_spiralling;
- }
- }
- x_change = -1;
- if (temp_yps - ctry < 0)
- x_change = 1;
- y_change = 0;
- }
- else
- {
- x_change = 0;
- y_change = -1;
- if (temp_xps - ctrx > 0)
- y_change = 1;
- }
- } // end if (direction == 1)
- else
- {
- /*
- This part checks all eight surrounding squares to find the
- one that leads on to the present square.
- */
- for (i = -1; i < 2; i++)
- {
- for (j = -1; j < 2; j++)
- {
- if (i == 0 && j == 0)
- continue;
-
- if (temp_xps + i == minx - 1)
- {
- x_change = 0;
- y_change = -1;
- }
- else if (temp_xps + i - ctrx == 0 && temp_yps + j - ctry == 0)
- {
- x_change = -1;
- y_change = 0;
- }
- else if (abs(temp_xps + i - ctrx) <= abs(temp_yps + j - ctry))
- {
- const int xi = temp_xps + i - ctrx;
- const int yj = temp_yps + j - ctry;
-
- if (xi >= 0 && yj <= 0)
- {
- if (abs(xi) > abs(yj + 1))
- {
- x_change = 0;
- y_change = -1;
- if (xi > 0)
- y_change = 1;
- goto finished_spiralling;
- }
- }
-
- x_change = -1;
- if (yj < 0)
- x_change = 1;
- y_change = 0;
- }
- else
- {
- x_change = 0;
- y_change = -1;
- if (temp_xps + i - ctrx > 0)
- y_change = 1;
- }
-
- if (temp_xps + i + x_change == temp_xps
- && temp_yps + j + y_change == temp_yps)
- {
- goto finished_spiralling;
- }
- }
- }
- } // end else
-
-
- finished_spiralling:
- x_change *= direction;
- y_change *= direction;
-
- temp_xps += x_change;
- if (temp_yps + y_change <= maxy) // it can wrap, unfortunately
- temp_yps += y_change;
-
- const int targ_x = you.x_pos + temp_xps - ctrx;
- const int targ_y = you.y_pos + temp_yps - ctry;
-
- // We don't want to be looking outside the bounds of the arrays:
- //if (!in_los_bounds(temp_xps, temp_yps))
- // continue;
-
- if (temp_xps < minx - 1 || temp_xps > maxx
- || temp_yps < VIEW_SY || temp_yps > VIEW_EY)
- continue;
-
- if (targ_x < 1 || targ_x >= GXM || targ_y < 1 || targ_y >= GYM)
- continue;
-
- if ((onlyVis || onlyHidden) && onlyVis != in_los(targ_x, targ_y))
- continue;
-
- if (find_targ(targ_x, targ_y, mode)) {
- mfp[0] = temp_xps;
- mfp[1] = temp_yps;
- return (1);
- }
- }
-
- return (direction == 1?
- find_square(ctrx, ctry, mfp, direction, find_targ, mode, false,
- next_los(direction, los, wrap))
- : find_square(minx, maxy, mfp, direction, find_targ, mode, false,
- next_los(direction, los, wrap)));
-}
-
-static bool is_shopstair(int x, int y)
-{
- return (is_stair(grd[x][y]) || grd[x][y] == DNGN_ENTER_SHOP);
-}
-
-extern unsigned char (*mapch2) (unsigned char);
-static bool is_full_mapped(int x, int y)
-{
- unsigned grid = grd[x][y];
- int envch = env.map[x - 1][y - 1];
- return (envch && envch == mapch2(grid));
-}
-
-static int surround_nonshopstair_count(int x, int y)
-{
- int count = 0;
- for (int ix = -1; ix < 2; ++ix)
- {
- for (int iy = -1; iy < 2; ++iy)
- {
- int nx = x + ix, ny = y + iy;
- if (nx <= 0 || nx >= GXM || ny <= 0 || ny >= GYM)
- continue;
- if (is_full_mapped(nx, ny) && !is_shopstair(nx, ny))
- count++;
- }
- }
- return (count);
-}
-
-// For want of a better name...
-static bool clear_mapped(int x, int y)
-{
- if (!is_full_mapped(x, y))
- return (false);
-
- if (is_shopstair(x, y))
- return (surround_nonshopstair_count(x, y) > 0);
-
- return (true);
-}
-
-static void describe_feature(int mx, int my, bool oos)
-{
- if (oos && !clear_mapped(mx, my))
- return;
-
- unsigned oldfeat = grd[mx][my];
- if (oos && env.map[mx - 1][my - 1] == mapch2(DNGN_SECRET_DOOR))
- grd[mx][my] = DNGN_ROCK_WALL;
-
- std::string desc = feature_description(mx, my);
-
- grd[mx][my] = oldfeat;
-
- if (desc.length())
- {
- if (oos)
- desc = "[" + desc + "]";
- mpr(desc.c_str());
- }
-}
-
-std::string feature_description(int mx, int my)
-{
- int trf; // used for trap type??
- switch (grd[mx][my])
- {
- case DNGN_STONE_WALL:
- return ("A stone wall.");
- case DNGN_ROCK_WALL:
- case DNGN_SECRET_DOOR:
- if (you.level_type == LEVEL_PANDEMONIUM)
- return ("A wall of the weird stuff which makes up Pandemonium.");
- else
- return ("A rock wall.");
- case DNGN_PERMAROCK_WALL:
- return ("An unnaturally hard rock wall.");
- case DNGN_CLOSED_DOOR:
- return ("A closed door.");
- case DNGN_METAL_WALL:
- return ("A metal wall.");
- case DNGN_GREEN_CRYSTAL_WALL:
- return ("A wall of green crystal.");
- case DNGN_ORCISH_IDOL:
- return ("An orcish idol.");
- case DNGN_WAX_WALL:
- return ("A wall of solid wax.");
- case DNGN_SILVER_STATUE:
- return ("A silver statue.");
- case DNGN_GRANITE_STATUE:
- return ("A granite statue.");
- case DNGN_ORANGE_CRYSTAL_STATUE:
- return ("An orange crystal statue.");
- case DNGN_LAVA:
- return ("Some lava.");
- case DNGN_DEEP_WATER:
- return ("Some deep water.");
- case DNGN_SHALLOW_WATER:
- return ("Some shallow water.");
- case DNGN_UNDISCOVERED_TRAP:
- case DNGN_FLOOR:
- return ("Floor.");
- case DNGN_OPEN_DOOR:
- return ("An open door.");
- case DNGN_ROCK_STAIRS_DOWN:
- return ("A rock staircase leading down.");
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- return ("A stone staircase leading down.");
- case DNGN_ROCK_STAIRS_UP:
- return ("A rock staircase leading upwards.");
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- return ("A stone staircase leading up.");
- case DNGN_ENTER_HELL:
- return ("A gateway to hell.");
- case DNGN_TRAP_MECHANICAL:
- case DNGN_TRAP_MAGICAL:
- case DNGN_TRAP_III:
- for (trf = 0; trf < MAX_TRAPS; trf++)
- {
- if (env.trap[trf].x == mx
- && env.trap[trf].y == my)
- {
- break;
- }
-
- if (trf == MAX_TRAPS - 1)
- {
- mpr("Error - couldn't find that trap.");
- error_message_to_player();
- break;
- }
- }
-
- switch (env.trap[trf].type)
- {
- case TRAP_DART:
- return ("A dart trap.");
- case TRAP_ARROW:
- return ("An arrow trap.");
- case TRAP_SPEAR:
- return ("A spear trap.");
- case TRAP_AXE:
- return ("An axe trap.");
- case TRAP_TELEPORT:
- return ("A teleportation trap.");
- case TRAP_AMNESIA:
- return ("An amnesia trap.");
- case TRAP_BLADE:
- return ("A blade trap.");
- case TRAP_BOLT:
- return ("A bolt trap.");
- case TRAP_ZOT:
- return ("A Zot trap.");
- case TRAP_NEEDLE:
- return ("A needle trap.");
- default:
- mpr("An undefined trap. Huh?");
- error_message_to_player();
- break;
- }
- break;
- case DNGN_ENTER_SHOP:
- return (shop_name(mx, my));
- case DNGN_ENTER_LABYRINTH:
- return ("A labyrinth entrance.");
- case DNGN_ENTER_DIS:
- return ("A gateway to the Iron City of Dis.");
- case DNGN_ENTER_GEHENNA:
- return ("A gateway to Gehenna.");
- case DNGN_ENTER_COCYTUS:
- return ("A gateway to the freezing wastes of Cocytus.");
- case DNGN_ENTER_TARTARUS:
- return ("A gateway to the decaying netherworld of Tartarus.");
- case DNGN_ENTER_ABYSS:
- return ("A gateway to the infinite Abyss.");
- case DNGN_EXIT_ABYSS:
- return ("A gateway leading out of the Abyss.");
- case DNGN_STONE_ARCH:
- return ("An empty arch of ancient stone.");
- case DNGN_ENTER_PANDEMONIUM:
- return ("A gate leading to the halls of Pandemonium.");
- case DNGN_EXIT_PANDEMONIUM:
- return ("A gate leading out of Pandemonium.");
- case DNGN_TRANSIT_PANDEMONIUM:
- return ("A gate leading to another region of Pandemonium.");
- case DNGN_ENTER_ORCISH_MINES:
- return ("A staircase to the Orcish Mines.");
- case DNGN_ENTER_HIVE:
- return ("A staircase to the Hive.");
- case DNGN_ENTER_LAIR:
- return ("A staircase to the Lair.");
- case DNGN_ENTER_SLIME_PITS:
- return ("A staircase to the Slime Pits.");
- case DNGN_ENTER_VAULTS:
- return ("A staircase to the Vaults.");
- case DNGN_ENTER_CRYPT:
- return ("A staircase to the Crypt.");
- case DNGN_ENTER_HALL_OF_BLADES:
- return ("A staircase to the Hall of Blades.");
- case DNGN_ENTER_ZOT:
- return ("A gate to the Realm of Zot.");
- case DNGN_ENTER_TEMPLE:
- return ("A staircase to the Ecumenical Temple.");
- case DNGN_ENTER_SNAKE_PIT:
- return ("A staircase to the Snake Pit.");
- case DNGN_ENTER_ELVEN_HALLS:
- return ("A staircase to the Elven Halls.");
- case DNGN_ENTER_TOMB:
- return ("A staircase to the Tomb.");
- case DNGN_ENTER_SWAMP:
- return ("A staircase to the Swamp.");
- case DNGN_RETURN_FROM_ORCISH_MINES:
- case DNGN_RETURN_FROM_HIVE:
- case DNGN_RETURN_FROM_LAIR:
- case DNGN_RETURN_FROM_VAULTS:
- case DNGN_RETURN_FROM_TEMPLE:
- return ("A staircase back to the Dungeon.");
- case DNGN_RETURN_FROM_SLIME_PITS:
- case DNGN_RETURN_FROM_SNAKE_PIT:
- case DNGN_RETURN_FROM_SWAMP:
- return ("A staircase back to the Lair.");
- case DNGN_RETURN_FROM_CRYPT:
- case DNGN_RETURN_FROM_HALL_OF_BLADES:
- return ("A staircase back to the Vaults.");
- case DNGN_RETURN_FROM_ELVEN_HALLS:
- return ("A staircase back to the Mines.");
- case DNGN_RETURN_FROM_TOMB:
- return ("A staircase back to the Crypt.");
- case DNGN_RETURN_FROM_ZOT:
- return ("A gate leading back out of this place.");
- case DNGN_ALTAR_ZIN:
- return ("A glowing white marble altar of Zin.");
- case DNGN_ALTAR_SHINING_ONE:
- return ("A glowing golden altar of the Shining One.");
- case DNGN_ALTAR_KIKUBAAQUDGHA:
- return ("An ancient bone altar of Kikubaaqudgha.");
- case DNGN_ALTAR_YREDELEMNUL:
- return ("A basalt altar of Yredelemnul.");
- case DNGN_ALTAR_XOM:
- return ("A shimmering altar of Xom.");
- case DNGN_ALTAR_VEHUMET:
- return ("A shining altar of Vehumet.");
- case DNGN_ALTAR_OKAWARU:
- return ("An iron altar of Okawaru.");
- case DNGN_ALTAR_MAKHLEB:
- return ("A burning altar of Makhleb.");
- case DNGN_ALTAR_SIF_MUNA:
- return ("A deep blue altar of Sif Muna.");
- case DNGN_ALTAR_TROG:
- return ("A bloodstained altar of Trog.");
- case DNGN_ALTAR_NEMELEX_XOBEH:
- return ("A sparkling altar of Nemelex Xobeh.");
- case DNGN_ALTAR_ELYVILON:
- return ("A silver altar of Elyvilon.");
- case DNGN_BLUE_FOUNTAIN:
- return ("A fountain of clear blue water.");
- case DNGN_SPARKLING_FOUNTAIN:
- return ("A fountain of sparkling water.");
- case DNGN_DRY_FOUNTAIN_I:
- case DNGN_DRY_FOUNTAIN_II:
- case DNGN_DRY_FOUNTAIN_IV:
- case DNGN_DRY_FOUNTAIN_VI:
- case DNGN_DRY_FOUNTAIN_VIII:
- case DNGN_PERMADRY_FOUNTAIN:
- return ("A dry fountain.");
- }
- return ("");
-}
-
-static void describe_cell(int mx, int my)
-{
- char str_pass[ ITEMNAME_SIZE ];
- bool mimic_item = false;
-
- if (mgrd[mx][my] != NON_MONSTER)
- {
- int i = mgrd[mx][my];
-
- if (grd[mx][my] == DNGN_SHALLOW_WATER)
- {
- if (!player_monster_visible(&menv[i]) && !mons_flies(&menv[i]))
- {
- mpr("There is a strange disturbance in the water here.");
- }
- }
-
-#if DEBUG_DIAGNOSTICS
- if (!player_monster_visible( &menv[i] ))
- mpr( "There is a non-visible monster here.", MSGCH_DIAGNOSTICS );
-#else
- if (!player_monster_visible( &menv[i] ))
- goto look_clouds;
-#endif
-
- const int mon_wep = menv[i].inv[MSLOT_WEAPON];
- const int mon_arm = menv[i].inv[MSLOT_ARMOUR];
-
- strcpy(info, ptr_monam( &(menv[i]), DESC_CAP_A ));
- strcat(info, ".");
- mpr(info);
-
- if (menv[i].type != MONS_DANCING_WEAPON && mon_wep != NON_ITEM)
- {
- snprintf( info, INFO_SIZE, "%s is wielding ", mons_pronoun( menv[i].type,
- PRONOUN_CAP ));
- it_name(mon_wep, DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
-
- // 2-headed ogres can wield 2 weapons
- if ((menv[i].type == MONS_TWO_HEADED_OGRE
- || menv[i].type == MONS_ETTIN)
- && menv[i].inv[MSLOT_MISSILE] != NON_ITEM)
- {
- strcat( info, " and " );
- it_name(menv[i].inv[MSLOT_MISSILE], DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
- strcat(info, ".");
-
- mpr(info);
- }
- else
- {
- strcat(info, ".");
- mpr(info);
- }
- }
-
- if (mon_arm != NON_ITEM)
- {
- it_name( mon_arm, DESC_NOCAP_A, str_pass );
- snprintf( info, INFO_SIZE, "%s is wearing %s.",
- mons_pronoun( menv[i].type, PRONOUN_CAP ),
- str_pass );
-
- mpr( info );
- }
-
-
- if (menv[i].type == MONS_HYDRA)
- {
- snprintf( info, INFO_SIZE, "It has %d head%s.",
- menv[i].number, (menv[i].number > 1? "s" : "") );
- mpr( info );
- }
-
- print_wounds(&menv[i]);
-
-
- if (mons_is_mimic( menv[i].type ))
- mimic_item = true;
- else if (!mons_class_flag(menv[i].type, M_NO_EXP_GAIN))
- {
- if (menv[i].behaviour == BEH_SLEEP)
- {
- strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- strcat(info, " doesn't appear to have noticed you.");
- mpr(info);
- }
- // Applies to both friendlies and hostiles
- else if (menv[i].behaviour == BEH_FLEE)
- {
- strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- strcat(info, " is fleeing in terror.");
- mpr(info);
- }
- // hostile with target != you
- else if (!mons_friendly(&menv[i]) && menv[i].foe != MHITYOU)
- {
- // special case: batty monsters get set to BEH_WANDER as
- // part of their special behaviour.
- if (!testbits(menv[i].flags, MF_BATTY))
- {
- strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- strcat(info, " doesn't appear to be interested in you.");
- mpr(info);
- }
- }
- }
-
- if (menv[i].attitude == ATT_FRIENDLY)
- {
- strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- strcat(info, " is friendly.");
- mpr(info);
- }
-
- for (int p = 0; p < NUM_MON_ENCHANTS; p++)
- {
- strcpy(info, mons_pronoun(menv[i].type, PRONOUN_CAP));
- switch (menv[i].enchantment[p])
- {
- case ENCH_YOUR_ROT_I:
- case ENCH_YOUR_ROT_II:
- case ENCH_YOUR_ROT_III:
- case ENCH_YOUR_ROT_IV:
- strcat(info, " is rotting away."); //jmf: "covered in sores"?
- break;
- case ENCH_BACKLIGHT_I:
- case ENCH_BACKLIGHT_II:
- case ENCH_BACKLIGHT_III:
- case ENCH_BACKLIGHT_IV:
- strcat(info, " is softly glowing.");
- break;
- case ENCH_SLOW:
- strcat(info, " is moving slowly.");
- break;
- case ENCH_HASTE:
- strcat(info, " is moving very quickly.");
- break;
- case ENCH_CONFUSION:
- strcat(info, " appears to be bewildered and confused.");
- break;
- case ENCH_INVIS:
- strcat(info, " is slightly transparent.");
- break;
- case ENCH_CHARM:
- strcat(info, " is in your thrall.");
- break;
- case ENCH_YOUR_STICKY_FLAME_I:
- case ENCH_YOUR_STICKY_FLAME_II:
- case ENCH_YOUR_STICKY_FLAME_III:
- case ENCH_YOUR_STICKY_FLAME_IV:
- case ENCH_STICKY_FLAME_I:
- case ENCH_STICKY_FLAME_II:
- case ENCH_STICKY_FLAME_III:
- case ENCH_STICKY_FLAME_IV:
- strcat(info, " is covered in liquid flames.");
- break;
- default:
- info[0] = '\0';
- break;
- } // end switch
- if (info[0])
- mpr(info);
- }
-
-#if DEBUG_DIAGNOSTICS
- stethoscope(i);
-#endif
- }
-
-#if (!DEBUG_DIAGNOSTICS)
- // removing warning
- look_clouds:
-#endif
- if (env.cgrid[mx][my] != EMPTY_CLOUD)
- {
- const char cloud_inspected = env.cgrid[mx][my];
-
- const char cloud_type = env.cloud[ cloud_inspected ].type;
-
- strcpy(info, "There is a cloud of ");
- strcat(info,
- (cloud_type == CLOUD_FIRE
- || cloud_type == CLOUD_FIRE_MON) ? "flame" :
- (cloud_type == CLOUD_STINK
- || cloud_type == CLOUD_STINK_MON) ? "noxious fumes" :
- (cloud_type == CLOUD_COLD
- || cloud_type == CLOUD_COLD_MON) ? "freezing vapour" :
- (cloud_type == CLOUD_POISON
- || cloud_type == CLOUD_POISON_MON) ? "poison gases" :
- (cloud_type == CLOUD_GREY_SMOKE
- || cloud_type == CLOUD_GREY_SMOKE_MON) ? "grey smoke" :
- (cloud_type == CLOUD_BLUE_SMOKE
- || cloud_type == CLOUD_BLUE_SMOKE_MON) ? "blue smoke" :
- (cloud_type == CLOUD_PURP_SMOKE
- || cloud_type == CLOUD_PURP_SMOKE_MON) ? "purple smoke" :
- (cloud_type == CLOUD_STEAM
- || cloud_type == CLOUD_STEAM_MON) ? "steam" :
- (cloud_type == CLOUD_MIASMA
- || cloud_type == CLOUD_MIASMA_MON) ? "foul pestilence" :
- (cloud_type == CLOUD_BLACK_SMOKE
- || cloud_type == CLOUD_BLACK_SMOKE_MON) ? "black smoke"
- : "buggy goodness");
- strcat(info, " here.");
- mpr(info);
- }
-
- int targ_item = igrd[ mx ][ my ];
-
- if (targ_item != NON_ITEM)
- {
- // If a mimic is on this square, we pretend its the first item -- bwr
- if (mimic_item)
- mpr("There is something else lying underneath.");
- else
- {
- if (mitm[ targ_item ].base_type == OBJ_GOLD)
- {
- mpr( "A pile of gold coins." );
- }
- else
- {
- strcpy(info, "You see ");
- it_name( targ_item, DESC_NOCAP_A, str_pass);
- strcat(info, str_pass);
- strcat(info, " here.");
- mpr(info);
- }
-
- if (mitm[ targ_item ].link != NON_ITEM)
- mpr("There is something else lying underneath.");
- }
- }
-
- std::string feature_desc = feature_description(mx, my);
- mpr(feature_desc.c_str());
-}