public void Show(PlayerTurnEvent e, CharacterScreen screen)
        {
            CharacterScreen?nextScreen = screen;

            MapRenderer.HideMap();
            do
            {
                if (nextScreen == CharacterScreen.Inventory)
                {
                    nextScreen = ShowInventory(e);
                }
                else if (nextScreen == CharacterScreen.Equipment)
                {
                    nextScreen = ShowEquipment(e);
                }
                else if (nextScreen == CharacterScreen.Actions)
                {
                    nextScreen = ShowActions(e);
                }
                else if (nextScreen == CharacterScreen.AdventureLog)
                {
                    nextScreen = ShowAdventureLog(e);
                }
                else
                {
                    return;
                }
            }while(nextScreen != null && !GameUniverse.Suspend && !GameUniverse.GameOver);            // Escape menu might end game, so check
        }
Exemple #2
0
        private CharacterScreen?ShowInventory(PlayerTurnEvent e)
        {
            while (true)
            {
                const int rowOffset = 3;
                int       colOffset = MapUI.ColOffset;
                Screen.HoldUpdates();
                Screen.Clear(0, colOffset, ScreenUIMain.Rows, MapUI.MapDisplayWidth);
                DrawCommonSections(CharacterScreen.Inventory);

                Screen.Write(rowOffset, colOffset, "In your pack: ");
                //todo...i think the lines are good to set the section apart, but it's possible that i don't need both:
                Screen.Write(rowOffset + 1, colOffset, SeparatorBar);
                Screen.Write(rowOffset + 2, colOffset, "[a] a potion of haste");                 //todo
                Screen.Write(rowOffset + 2, colOffset + 1, 'a', Color.Cyan);
                Screen.Write(rowOffset + 3, colOffset, "[b] a slender wand");
                Screen.Write(rowOffset + 3, colOffset + 1, 'b', Color.Cyan);
                Screen.Write(rowOffset + 4, colOffset, "[c] an iridescent orb");
                Screen.Write(rowOffset + 4, colOffset + 1, 'c', Color.Cyan);
                Screen.Write(rowOffset + 5, colOffset, SeparatorBar);                 //todo, count?
                Screen.ResumeUpdates();
                Screen.SetCursorPosition(rowOffset, colOffset + 14);
                ConsoleKeyInfo key   = Input.ReadKey();
                bool           shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
                switch (key.Key)
                {
                case ConsoleKey.Tab:
                    if (shift)
                    {
                        return(CharacterScreen.AdventureLog);
                    }
                    else
                    {
                        return(CharacterScreen.Equipment);
                    }

                case ConsoleKey.Escape:
                case ConsoleKey.Spacebar:
                    return(null);

                case ConsoleKey.Oem2:                         //todo check
                    //todo help
                    break;

                default:
                    int letterIndex = key.KeyChar - 'a';
                    if (letterIndex >= 0 && letterIndex < 3)                             //todo, inv count here
                    //
                    {
                    }
                    break;
                }
            }
        }
        private CharacterScreen?ShowActions(PlayerTurnEvent e)
        {
            while (true)
            {
                const int rowOffset = 3;
                int       colOffset = MapUI.ColOffset;
                Screen.HoldUpdates();
                Screen.Clear(0, colOffset, ScreenUIMain.Rows, MapUI.MapDisplayWidth);
                DrawCommonSections(CharacterScreen.Actions);

                Screen.Write(rowOffset, colOffset, "Available actions: ");
                Screen.Write(rowOffset + 1, colOffset, SeparatorBar);
                string[] actions = new[] {                 //todo
                    "Rest to recover health and repair equipment",
                    "Descend staircase",
                    "Close a door"
                };
                Screen.WriteListOfChoices(rowOffset + 2, colOffset, actions);
                Screen.Write(rowOffset + 5, colOffset, SeparatorBar);                 //todo, count?
                Screen.ResumeUpdates();
                Screen.SetCursorPosition(rowOffset, colOffset + 19);
                ConsoleKeyInfo key   = Input.ReadKey();
                bool           shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
                switch (key.Key)
                {
                case ConsoleKey.Tab:                         //todo, what about adding Insert as an alternative to Tab, so you can easily access this screen and switch with the numpad?
                    if (shift)
                    {
                        return(CharacterScreen.Equipment);
                    }
                    else
                    {
                        return(CharacterScreen.AdventureLog);
                    }

                case ConsoleKey.Escape:
                case ConsoleKey.Spacebar:
                    return(null);

                case ConsoleKey.Oem2:                         //todo check
                    //todo help
                    break;

                default:
                    int letterIndex = key.KeyChar - 'a';
                    if (letterIndex >= 0 && letterIndex < 3)                             //todo
                    //
                    //remember to check whether the PlayerTurnEvent is null - that should be allowed.
                    {
                    }
                    break;
                }
            }
        }
Exemple #4
0
        private void ChooseActionFromDirection(PlayerTurnEvent e, Dir8 dir, bool shift)
        {
            Point    targetPoint    = Player.Position.PointInDir(dir);
            Creature targetCreature = CreatureAt(targetPoint);

            if (targetCreature != null)
            {
                e.ChosenAction = new MeleeAttackAction(Player, targetCreature);
                return;
            }
            // Check for wall sliding:
            bool wallSliding = false;

            if (!TileDefinition.IsPassable(TileTypeAt(targetPoint)))
            {
                Point cwPoint  = Player.Position.PointInDir(dir.Rotate(true));
                Point ccwPoint = Player.Position.PointInDir(dir.Rotate(false));
                if (TileDefinition.IsPassable(TileTypeAt(cwPoint)) && !TileDefinition.IsPassable(TileTypeAt(ccwPoint)))
                {
                    wallSliding    = true;
                    dir            = dir.Rotate(true);
                    targetPoint    = Player.Position.PointInDir(dir);
                    targetCreature = CreatureAt(targetPoint);
                }
                else if (!TileDefinition.IsPassable(TileTypeAt(cwPoint)) && TileDefinition.IsPassable(TileTypeAt(ccwPoint)))
                {
                    wallSliding    = true;
                    dir            = dir.Rotate(false);
                    targetPoint    = Player.Position.PointInDir(dir);
                    targetCreature = CreatureAt(targetPoint);
                }
            }
            if (targetCreature != null)
            {
                e.ChosenAction = new MeleeAttackAction(Player, targetCreature);
            }
            else
            {
                e.ChosenAction = new WalkAction(Player, targetPoint);
                if (shift && !wallSliding)
                {
                    walkDir = dir;                                       // Don't set walkDir for attacks or wall slides
                }
            }
        }
    public CharacterTurnEvent GetNextCharacterTurn()
    {
        if (m_PrecalculatedTurnOrder[0].CharacterControlType == CombatCharacterController.ControlType.NPC)
        {
            EnemyTurnEvent beginCharacterTurnEvent = new EnemyTurnEvent();
            beginCharacterTurnEvent.Character = m_PrecalculatedTurnOrder[0];
            m_PrecalculatedTurnOrder[0].TurnsGiven++;
            CalculateTurnOrder();
            return beginCharacterTurnEvent;
        }
        else if (m_PrecalculatedTurnOrder[0].CharacterControlType == CombatCharacterController.ControlType.PC)
        {
            Debug.Log("Player turn.");

            PlayerTurnEvent beginCharacterTurnEvent = new PlayerTurnEvent();
            beginCharacterTurnEvent.Character = m_PrecalculatedTurnOrder[0];
            m_PrecalculatedTurnOrder[0].TurnsGiven++;
            CalculateTurnOrder();
            return beginCharacterTurnEvent;
        }
        else
            return null;
    }
		private CharacterScreen? ShowEquipment(PlayerTurnEvent e){
			while(true){
				const int rowOffset = 3;
				int colOffset = MapUI.ColOffset;
				Screen.HoldUpdates();
				Screen.Clear(0, colOffset, ScreenUIMain.Rows, MapUI.MapDisplayWidth);
				DrawCommonSections(CharacterScreen.Equipment);

				Screen.Write(rowOffset, colOffset, "Your equipment: ");
				Screen.Write(rowOffset + 1, colOffset, SeparatorBar); //todo
				//todo, use WriteListOfChoices here
				Screen.Write(rowOffset + 2, colOffset, "[a] Sword");
				Screen.Write(rowOffset + 2, colOffset + 1, 'a', Color.Cyan);
				Screen.Write(rowOffset + 3, colOffset, "[b] Another sword");
				Screen.Write(rowOffset + 3, colOffset + 1, 'b', Color.Cyan);
				Screen.Write(rowOffset + 4, colOffset, "[c] Third sword");
				Screen.Write(rowOffset + 4, colOffset + 1, 'c', Color.Cyan);
				Screen.Write(rowOffset + 5, colOffset, SeparatorBar);
				Screen.ResumeUpdates();
				Screen.SetCursorPosition(rowOffset, colOffset + 16);
				ConsoleKeyInfo key = Input.ReadKey();
				bool shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
				switch(key.Key){
					case ConsoleKey.Tab:
						if(shift) return CharacterScreen.Inventory;
						else return CharacterScreen.Actions;
					case ConsoleKey.Escape:
					case ConsoleKey.Spacebar:
						return null;
					case ConsoleKey.Oem2: //todo check
						//todo help
						break;
					default:
						break;
				}
			}
		}
Exemple #7
0
        private void ChooseAutoexploreAction(PlayerTurnEvent e)
        {
            var potentiallyReachable = FloodFill.ScanToArray(Player.Position, point => !point.IsMapEdge() && (!Map.Seen[point] || TileDefinition.IsPassable(TileTypeAt(point))));
            var distanceToKnown      = new DijkstraMap(p => (Map.Seen[p] || p.IsMapEdge())? -1 : 1)
            {
                IsSource = p => (Map.Seen[p] || p.IsMapEdge())
            };

            distanceToKnown.Scan();
            foreach (Point p in Map.GetAllPoints(false))
            {
                if (distanceToKnown[p] == DijkstraMap.Unexplored || distanceToKnown[p] == DijkstraMap.Blocked)
                {
                    continue;
                }
                distanceToKnown[p] = -(distanceToKnown[p] * distanceToKnown[p]);
            }
            distanceToKnown.RescanWithCurrentValues();
            var exploreMap = new DijkstraMap(p => (!Map.Seen[p] || !TileDefinition.IsPassable(TileTypeAt(p)))? -1 : 1)              // todo, needs items, shrines, etc. eventually
            {
                IsSource       = p => !Map.Seen[p] && potentiallyReachable[p],
                GetSourceValue = p => - (distanceToKnown[p])
            };

            exploreMap.Scan();
            List <Point> playerPath = exploreMap.GetDownhillPath(Player.Position, true, earlyStopCondition: p => true);

            if (playerPath.Count == 0)
            {
                return;
            }
            else
            {
                e.ChosenAction = new WalkAction(Player, playerPath[0]);
            }
        }
Exemple #8
0
        private void ChooseAction(PlayerTurnEvent e)
        {
            do
            {
                GameRunUI.DrawGameUI(
                    sidebar: DrawOption.Normal,
                    messages: DrawOption.Normal,
                    environmentalDesc: DrawOption.Normal,
                    commands: DrawOption.Normal
                    );
                MapRenderer.UpdateAllSettings(Player.Position);
                MapRenderer.DrawMap(e);
                //window update, set suspend if false...

                /*if(!Screen.Update()){
                 *      GameUniverse.Suspend = true;
                 *      return;
                 * }*/
                //
                //
                if (walkDir != null)
                {
                    if (Input.KeyIsAvailable)
                    {
                        Interrupt();
                    }
                    else
                    {
                        Point targetPoint = Player.Position.PointInDir(walkDir.Value);
                        if (!TileDefinition.IsPassable(TileTypeAt(targetPoint)) || CreatureAt(targetPoint) != null)
                        {
                            walkDir = null;
                        }
                        else
                        {
                            if (!Screen.WindowUpdate())
                            {
                                Program.Quit();
                            }
                            Thread.Sleep(10);                             //todo, make configurable
                            e.ChosenAction = new WalkAction(Player, Player.Position.PointInDir(walkDir.Value));
                            return;
                        }
                    }
                }
                else if (Autoexplore)
                {
                    if (Input.KeyIsAvailable)
                    {
                        Interrupt();
                    }
                    else
                    {
                        ChooseAutoexploreAction(e);
                        if (e.ChosenAction != null)
                        {
                            if (!Screen.WindowUpdate())
                            {
                                Program.Quit();
                            }
                            Thread.Sleep(10);                             //todo, make configurable
                        }
                        else
                        {
                            Interrupt("You don't see a path for further exploration. ");
                        }
                        return;
                    }
                }
                else if (Path != null && NextPathIndex < Path.Count)
                {
                    if (Input.KeyIsAvailable)
                    {
                        Interrupt();
                    }
                    else
                    {
                        Point next = Path[NextPathIndex];
                        //todo check distance, walkable, etc.?
                        Dir8  dir        = Player.Position.GetDirectionOfNeighbor(next);
                        Point pointInDir = Player.Position.PointInDir(dir);
                        if (CreatureAt(pointInDir) != null)
                        {
                            Interrupt();
                        }
                        else if (!TileDefinition.IsPassable(TileTypeAt(pointInDir)))
                        {
                            Interrupt();
                            // There's still more to consider regarding autoexplore AND travel destination calculation:
                            //	-do I want to make it weigh AGAINST the stairs, once they're known?
                            //	-it seems like I might want to allow some of the 'avoid this area' to _cross_ narrow bridges of known space, because
                            //		currently exploration is happy to go into a room because of ONE small unknown area, even if the OTHER side of the room is touching the large unknown area.
                            //		(that COULD be a tricky problem to solve...not sure.)
                            //		(this happens on one of the premade levels near the bottom of the map)
                        }
                        else
                        {
                            e.ChosenAction = new WalkAction(Player, Player.Position.PointInDir(dir));
                            NextPathIndex++;
                            //todo, interruptedPath? (and index?)
                            if (!Screen.WindowUpdate())
                            {
                                Program.Quit();
                            }
                            Thread.Sleep(10);                             //todo, make configurable
                            return;
                        }
                    }
                }
                ConsoleKeyInfo key   = Input.ReadKey();
                bool           shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
                switch (key.Key)
                {
                case ConsoleKey.NumPad8:
                    ChooseActionFromDirection(e, Dir8.N, shift);
                    break;

                case ConsoleKey.NumPad6:
                    ChooseActionFromDirection(e, Dir8.E, shift);
                    break;

                case ConsoleKey.NumPad4:
                    ChooseActionFromDirection(e, Dir8.W, shift);
                    break;

                case ConsoleKey.NumPad2:
                    ChooseActionFromDirection(e, Dir8.S, shift);
                    break;

                case ConsoleKey.NumPad9:
                    ChooseActionFromDirection(e, Dir8.NE, shift);
                    break;

                case ConsoleKey.NumPad3:
                    ChooseActionFromDirection(e, Dir8.SE, shift);
                    break;

                case ConsoleKey.NumPad1:
                    ChooseActionFromDirection(e, Dir8.SW, shift);
                    break;

                case ConsoleKey.NumPad7:
                    ChooseActionFromDirection(e, Dir8.NW, shift);
                    break;

                case ConsoleKey.D:                         //todo, 'd' is definitely not 'descend'
                    e.ChosenAction = new DescendAction(Player);
                    break;

                case ConsoleKey.Escape:
                    EscapeMenu.Open();
                    break;

                case ConsoleKey.I:
                    CharacterScreens.Show(e, CharacterScreen.Inventory);
                    break;

                case ConsoleKey.E:
                    CharacterScreens.Show(e, CharacterScreen.Equipment);
                    break;

                case ConsoleKey.Enter:
                    CharacterScreens.Show(e, CharacterScreen.Actions);
                    break;

                case ConsoleKey.V:
                    CharacterScreens.Show(e, CharacterScreen.AdventureLog);
                    break;

                case ConsoleKey.Tab:
                    MapUI.LookMode(e);
                    break;

                case ConsoleKey.X:
                    MapUI.LookMode(e, true);
                    break;
                }
            } while(e.ChosenAction == null);
        }
 public abstract void DrawMap(PlayerTurnEvent e);
Exemple #10
0
        private CharacterScreen?ShowAdventureLog(PlayerTurnEvent e)
        {
            while (true)
            {
                const int rowOffset = 3;
                int       colOffset = MapUI.ColOffset;
                Screen.HoldUpdates();
                Screen.Clear(0, colOffset, ScreenUIMain.Rows, MapUI.MapDisplayWidth);
                DrawCommonSections(CharacterScreen.AdventureLog);

                Screen.Write(rowOffset, colOffset, "Adventure log of Charname III: ");
                Screen.Write(rowOffset + 1, colOffset, SeparatorBar);
                Screen.Write(rowOffset + 2, colOffset, "Entered the mountain pass 571 turns ago");
                Screen.Write(rowOffset + 3, colOffset, "Skills: (none)");                 //todo
                Screen.WriteListOfChoices(rowOffset + 5, colOffset, new[] {
                    "Discovered locations", "Discovered items", "Recent messages", "Pause adventure, change options, or get help"
                });
                Screen.Write(rowOffset + 9, colOffset, SeparatorBar);                 //todo, count?
                Screen.ResumeUpdates();
                Screen.SetCursorPosition(rowOffset, colOffset + 31);
                ConsoleKeyInfo key   = Input.ReadKey();
                bool           shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
                switch (key.Key)
                {
                case ConsoleKey.Tab:
                    if (shift)
                    {
                        return(CharacterScreen.Actions);
                    }
                    else
                    {
                        return(CharacterScreen.Inventory);
                    }

                case ConsoleKey.Escape:
                case ConsoleKey.Spacebar:
                    return(null);

                case ConsoleKey.Oem2:                         //todo check
                    //todo help
                    break;

                case ConsoleKey.A:
                    RunDijkstraTest();
                    break;

                case ConsoleKey.B:
                {                        //todo
                    for (int i = 0; i < GameUniverse.MapHeight; ++i)
                    {
                        for (int j = 0; j < GameUniverse.MapWidth; ++j)
                        {
                            if (dm[j, i] == DijkstraMap.Blocked || dm[j, i] == DijkstraMap.Unexplored)
                            {
                                continue;
                            }
                            dm[j, i] = (int)(-(dm[j, i]) * 1.4);
                        }
                    }
                    //Map.Tiles[44, 20] = TileType.Staircase;
                    //dm[44, 20] = 50;
                    dm.RescanWithCurrentValues();
                    int min = 99999;
                    for (int i = 0; i < GameUniverse.MapHeight; ++i)
                    {
                        for (int j = 0; j < GameUniverse.MapWidth; ++j)
                        {
                            if (dm[j, i] == DijkstraMap.Blocked || dm[j, i] == DijkstraMap.Unexplored)
                            {
                                continue;
                            }
                            if (dm[j, i] < min)
                            {
                                min = dm[j, i];
                            }
                        }
                    }
                    for (int i = 0; i < GameUniverse.MapHeight; ++i)
                    {
                        for (int j = 0; j < GameUniverse.MapWidth; ++j)
                        {
                            if (dm[j, i] == DijkstraMap.Blocked || dm[j, i] == DijkstraMap.Unexplored)
                            {
                                continue;
                            }
                            dm[j, i] -= min;
                        }
                    }
                    //PrintDijkstraTest();
                }
                break;

                case ConsoleKey.C:
                    break;

                case ConsoleKey.D:
                    EscapeMenu.Open(false);
                    if (GameUniverse.Suspend || GameUniverse.GameOver)
                    {
                        return(null);
                    }
                    break;
                }
            }
        }
 public override void DrawMap(PlayerTurnEvent e)
 {
     e.CalculateVisibility();
     for (int i = 0; i < GameUniverse.MapHeight; i++)
     {
         for (int j = 0; j < GameUniverse.MapWidth; j++)
         {
             Point    p        = new Point(j, i);
             Creature creature = CreatureAt(p);
             ItemType?item     = ItemAt(p)?.Type;                  //todo check ID
             if (drawEnemies && creature != null && e.CreaturesVisibleThisTurn.Contains(creature))
             {
                 DrawToMap(i, j, DetermineCreatureColorGlyph(creature.OriginalType, TileTypeAt(p), FeaturesAt(p), item));
                 //todo, need to consider inverting colors when colors are the same.
                 MapUI.RecordMapMemory(p);
             }
             else if (e.CellsVisibleThisTurn[p])
             {
                 MapUI.RecordMapMemory(p);                         //todo, can I avoid calling RecordMapMemory more than once per turn?
                 ColorGlyph cg = DetermineVisibleColorGlyph(TileTypeAt(p), FeaturesAt(p), item, Map.CurrentDepthSeed, p);
                 if (!e.CellsLitThisTurn[p])
                 {
                     DrawToMap(i, j, cg.GlyphIndex, Color.DarkCyan, cg.BackgroundColor);                             //todo, only some tiles get darkened this way, right?
                 }
                 else
                 {
                     DrawToMap(i, j, cg);
                 }
             }
             else if (false)                     // todo, this is where the dcss-style option for seeing previous monster locations will be added
             {
             }
             else if (Map.Seen[p])
             {
                 if (memoryFullyVisible)
                 {
                     if (false)
                     {
                         //todo, if this tile type is unknown until seen in light...
                     }
                     else
                     {
                         ColorGlyph cg = DetermineVisibleColorGlyph(TileTypeAt(p), FeaturesAt(p), item, Map.CurrentDepthSeed, p);
                         DrawToMap(i, j, cg);
                     }
                 }
                 DrawToMap(i, j, GetLastSeenColorGlyph(p, true));
             }
             else
             {
                 DrawToMap(i, j, ' ', Color.White);
             }
         }
     }
     if (highlight != null)
     {
         DrawHighlight(highlight);
     }
     if (cursor != null)
     {
         SetCursorPositionOnMap(cursor.Value.Y, cursor.Value.X);
     }
 }
Exemple #12
0
 public void NextTurn()
 {
     PlayerTurnEvent?.Invoke(this, new PlayerEventArgs(player.Name));
 }
Exemple #13
0
        public void LookMode(PlayerTurnEvent e, bool startInTravelMode = false, TravelDestinationPriority travelPriority = TravelDestinationPriority.Explore)
        {
            bool         travelMode         = startInTravelMode;
            List <Point> travelDestinations = GetTravelDestinations(travelPriority);            //todo, start this as null or not?
            DijkstraMap  playerMovementMap  = new DijkstraMap(point => (!Map.Seen[point] || !TileDefinition.IsPassable(TileTypeAt(point)))? -1 : 10);

            playerMovementMap.Scan(Player.Position);
            PointArray <bool> knownReachable           = null;
            DijkstraMap       distanceToKnownReachable = null;
            int   travelIndex = 0;
            Point p           = travelDestinations[0];

            while (true)
            {
                Screen.HoldUpdates();
                Screen.Clear(MessageBuffer.RowOffset, ColOffset, 4, MapDisplayWidth);
                Screen.Clear(GameRunUI.EnviromentalDescriptionRow, ColOffset, 1, MapDisplayWidth);
                Screen.Clear(GameRunUI.CommandListRow, ColOffset, 1, MapDisplayWidth);
                GameRunUI.DrawGameUI(
                    sidebar: DrawOption.Normal,
                    messages: DrawOption.DoNotDraw,
                    environmentalDesc: DrawOption.DoNotDraw,
                    commands: DrawOption.DoNotDraw
                    );
                string moveCursorMsg = travelMode? "Travel mode -- Move cursor to choose destination." : "Move cursor to look around.";
                Screen.Write(MessageBuffer.RowOffset, ColOffset, moveCursorMsg);
                Screen.Write(MessageBuffer.RowOffset + 2, ColOffset, "[Tab] to cycle between interesting targets          [m]ore details");
                Screen.Write(MessageBuffer.RowOffset + 2, ColOffset + 1, "Tab", Color.Cyan);
                Screen.Write(MessageBuffer.RowOffset + 2, ColOffset + 53, 'm', Color.Cyan);
                if (travelMode)
                {
                    Screen.Write(MessageBuffer.RowOffset + 3, ColOffset, "[x] to confirm destination           [Space] to cancel travel mode");
                    Screen.Write(MessageBuffer.RowOffset + 3, ColOffset + 1, 'x', Color.Cyan);
                    Screen.Write(MessageBuffer.RowOffset + 3, ColOffset + 38, "Space", Color.Cyan);
                }
                else
                {
                    Screen.Write(MessageBuffer.RowOffset + 3, ColOffset, "[x] to enter travel mode");
                    Screen.Write(MessageBuffer.RowOffset + 3, ColOffset + 1, 'x', Color.Cyan);
                }
                Highlight highlight;
                if (travelMode)
                {
                    List <Point> path = GetPathToNearbyReachable(p, playerMovementMap, ref knownReachable, ref distanceToKnownReachable);
                    highlight = new Highlight(MapHighlightType.Path)
                    {
                        Source      = Player.Position,
                        Destination = p,
                        LineOrPath  = path
                    };
                }
                else
                {
                    highlight = new Highlight(MapHighlightType.SinglePoint)
                    {
                        Destination = p
                    };
                }
                MapRenderer.UpdateAllSettings(p, highlight);
                MapRenderer.DrawMap(e);
                bool   hasLOS          = e.CellsVisibleThisTurn[p];
                bool   seen            = Map.Seen[p];
                string lookDescription = hasLOS? GetDescriptionAtCell(p)
                                        : seen?GetLastKnownDescriptionAtCell(p)
                                             : "";

                if (lookDescription.Length > MapDisplayWidth)
                {
                    int splitIdx = 0;
                    for (int idx = MapDisplayWidth - 1; idx >= 0; --idx)
                    {
                        if (lookDescription[idx] == ' ')
                        {
                            splitIdx = idx;
                            break;
                        }
                    }
                    int firstLineRow = Option.IsSet(BoolOptionType.MessagesAtBottom)? GameRunUI.CommandListRow
                                                : GameRunUI.EnviromentalDescriptionRow; // Start printing at whichever is higher onscreen
                    string firstLine  = lookDescription.Substring(0, splitIdx);
                    string secondLine = lookDescription.Substring(splitIdx + 1);        // Remove the space
                    if (secondLine.Length > MapDisplayWidth)
                    {
                        firstLine = hasLOS? "You see many things here."
                                                        : "You remember seeing many things here."; //todo, what should this say?
                        secondLine = "(Press 'm' for more details)";
                        //secondLine = "(Use the '[m]ore details' command for the full list)"; todo...any better options?
                    }
                    Screen.Write(firstLineRow, ColOffset, firstLine, Color.Green);
                    Screen.Write(firstLineRow + 1, ColOffset, secondLine, Color.Green);
                }
                else
                {
                    Screen.Write(GameRunUI.EnviromentalDescriptionRow, ColOffset, lookDescription, Color.Green);
                }
                Screen.ResumeUpdates();
                bool needsRedraw = false;
                while (!needsRedraw)
                {
                    ConsoleKeyInfo key   = Input.ReadKey();
                    bool           shift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift;
                    switch (key.Key)
                    {
                    case ConsoleKey.Tab:
                        if (shift)
                        {
                            travelIndex--;
                        }
                        else
                        {
                            travelIndex++;
                        }
                        if (travelIndex < 0)
                        {
                            travelIndex = travelDestinations.Count - 1;
                        }
                        else if (travelIndex >= travelDestinations.Count)
                        {
                            travelIndex = 0;
                        }
                        p           = travelDestinations[travelIndex];
                        needsRedraw = true;
                        break;

                    case ConsoleKey.Escape:
                        return;                                 // Done

                    case ConsoleKey.Spacebar:
                        if (travelMode)
                        {
                            travelMode  = false;
                            needsRedraw = true;
                        }
                        else
                        {
                            return;
                        }
                        break;

                    case ConsoleKey.Enter:
                        if (travelMode)
                        {
                            goto case ConsoleKey.X;                                            // Allow Enter to confirm travel destination, or cancel look mode.
                        }
                        else
                        {
                            goto case ConsoleKey.Escape;
                        }

                    case ConsoleKey.X:
                        if (travelMode)
                        {
                            List <Point> path = GetPathToNearbyReachable(p, playerMovementMap, ref knownReachable, ref distanceToKnownReachable);
                            if (path.Count > 0)
                            {
                                GameEventHandler.Path          = path;
                                GameEventHandler.NextPathIndex = 0;
                            }
                            //if(false) GameEventHandler.Autoexplore = true; //todo, option here
                            return;
                        }
                        else
                        {
                            travelMode  = true;
                            needsRedraw = true;
                        }
                        break;

                    case ConsoleKey.NumPad8:
                        p           = p.PointInDir(Dir8.N, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad6:
                        p           = p.PointInDir(Dir8.E, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad4:
                        p           = p.PointInDir(Dir8.W, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad2:
                        p           = p.PointInDir(Dir8.S, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad9:
                        p           = p.PointInDir(Dir8.NE, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad3:
                        p           = p.PointInDir(Dir8.SE, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad1:
                        p           = p.PointInDir(Dir8.SW, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    case ConsoleKey.NumPad7:
                        p           = p.PointInDir(Dir8.NW, shift? 6 : 1);
                        needsRedraw = true;
                        break;

                    default:
                        break;
                    }
                    if (!p.ExistsOnMap())
                    {
                        int newX, newY;
                        if (p.X < 0)
                        {
                            newX = 0;
                        }
                        else if (p.X >= GameUniverse.MapWidth)
                        {
                            newX = GameUniverse.MapWidth - 1;
                        }
                        else
                        {
                            newX = p.X;
                        }
                        if (p.Y < 0)
                        {
                            newY = 0;
                        }
                        else if (p.Y >= GameUniverse.MapHeight)
                        {
                            newY = GameUniverse.MapHeight - 1;
                        }
                        else
                        {
                            newY = p.Y;
                        }
                        p = new Point(newX, newY);
                    }
                }
            }
        }