public MessageBuffer(GameRunUI ui) : base(ui) { buffer = new StringWrapBuffer(NUM_LINES, MAX_LENGTH, MORE.Length, null, new char[] { ' ' }); buffer.BufferFull += HandleOverflow; log = new List <string>(); sb = new StringBuilder(); }
private static OptionsScreenType?ShowDisplayOptions() { List <OptionEditInfo> options = new List <OptionEditInfo> { GetEditInfo(IntOptionType.LoopDelayMs, "Delay while awaiting input (in milliseconds)"), new OptionEditInfo { Text = "Arrange screen with sidebar on right side instead of left", GetValue = () => Option.IsSet(BoolOptionType.SidebarOnRight)? "yes" : "no", EditValue = (i, j) => { bool newValue = !Option.IsSet(BoolOptionType.SidebarOnRight); Option.Set(BoolOptionType.SidebarOnRight, newValue); GameRunUI.UpdateSidebarOption(newValue); } }, new OptionEditInfo { Text = "Arrange screen with messages at bottom instead of top", GetValue = () => Option.IsSet(BoolOptionType.MessagesAtBottom)? "yes" : "no", EditValue = (i, j) => { bool newValue = !Option.IsSet(BoolOptionType.MessagesAtBottom); Option.Set(BoolOptionType.MessagesAtBottom, newValue); GameRunUI.UpdateMessagesOption(newValue); } }, //todo color options }; IList <OptionEditInfo> additionalOptions = Screen.GetAdditionalDisplayOptions(); if (additionalOptions != null) { options.AddRange(additionalOptions); } return(ShowEditableOptions(OptionsScreenType.Display, "Display options: ", options)); }
public MapUI(GameRunUI ui) : base(ui) { tilesLastSeen = new PointArray <TileType>(GameUniverse.MapWidth, GameUniverse.MapHeight); featuresLastSeen = new PointArray <FeatureType>(GameUniverse.MapWidth, GameUniverse.MapHeight); trapsLastSeen = new Dictionary <Point, TrapType>(); itemsLastSeen = new Dictionary <Point, ItemType>(); }
private void DrawCommonSections(CharacterScreen currentScreen) { GameRunUI.DrawGameUI( sidebar: DrawOption.Darkened, messages: DrawOption.DoNotDraw, environmentalDesc: DrawOption.DoNotDraw, commands: DrawOption.DoNotDraw ); const int rowOffset = 0; int colOffset = MapUI.ColOffset; const Color bgColor = Color.Black; Screen.Write(rowOffset, colOffset, "Inventory Equipment Actions Adventure Log [Tab] to switch", Color.DarkGray, bgColor); Screen.Write(rowOffset, colOffset + 51, "[Tab] to switch", Color.Gray, bgColor); Screen.Write(rowOffset, colOffset + 52, "Tab", Color.Cyan, bgColor); int highlightOffset; string highlightLabel; switch (currentScreen) { case CharacterScreen.Inventory: highlightOffset = 0; highlightLabel = "Inventory"; break; case CharacterScreen.Equipment: highlightOffset = 12; highlightLabel = "Equipment"; break; case CharacterScreen.Actions: highlightOffset = 24; highlightLabel = "Actions"; break; case CharacterScreen.AdventureLog: highlightOffset = 34; highlightLabel = "Adventure Log"; break; default: throw new InvalidOperationException("Invalid screen"); } Screen.Write(rowOffset, colOffset + highlightOffset, highlightLabel, Color.Green, bgColor); }
private static void RunGame(GameUniverse g) { GameRunUI gameUI = new GameRunUI(g); g.Q.BeforeEventExecute = gameUI.GameEventHandler.BeforeGameEvent; g.Q.AfterEventExecute = gameUI.GameEventHandler.AfterGameEvent; (g.Player.CancelDecider as PlayerCancelDecider).DecideCancel = gameUI.GameEventHandler.DecideCancel; g.CreatureRules.OnStatusStart = gameUI.GameEventHandler.OnStatusStart; g.CreatureRules.OnStatusEnd = gameUI.GameEventHandler.OnStatusEnd; //todo, try/catch? do I want a thing where I can get to the exceptions before they reach this point? g.Run(); if (g.GameOver) { //todo } else if (g.Suspend) { //todo } }
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 GameEventHandler(GameRunUI ui) : base(ui) { }
public void Open(bool drawBottomUI = true) { Screen.CursorVisible = false; Screen.HoldUpdates(); DrawOption bottomUI = drawBottomUI? DrawOption.Darkened : DrawOption.DoNotDraw; GameRunUI.DrawGameUI( sidebar: DrawOption.Darkened, messages: DrawOption.DoNotDraw, environmentalDesc: bottomUI, commands: bottomUI ); //todo, probably refactor this into a box-drawing utility: const Color cornerColor = Color.Blue; const Color edgeBgColor = Color.DarkBlue; const char cornerChar = ' '; Screen.Write(RowOffset, ColOffset, cornerChar, cornerColor, edgeBgColor); Screen.Write(RowOffset, ColOffset + Width - 1, cornerChar, cornerColor, edgeBgColor); Screen.Write(RowOffset + Height - 1, ColOffset, cornerChar, cornerColor, edgeBgColor); Screen.Write(RowOffset + Height - 1, ColOffset + Width - 1, cornerChar, cornerColor, edgeBgColor); const Color edgeColor = Color.Gray; const char topBottomChar = ' '; const char sidesChar = ' '; string topBottomBar = "".PadRight(Width - 2, topBottomChar); //todo refactor Screen.Write(RowOffset, ColOffset + 1, topBottomBar, edgeColor, edgeBgColor); Screen.Write(RowOffset + Height - 1, ColOffset + 1, topBottomBar, edgeColor, edgeBgColor); for (int i = RowOffset + 1; i < RowOffset + Height - 1; ++i) { Screen.Write(i, ColOffset, sidesChar, edgeColor, edgeBgColor); Screen.Clear(RowOffset + 1, ColOffset + 1, Height - 2, Width - 2); Screen.Write(i, ColOffset + Width - 1, sidesChar, edgeColor, edgeBgColor); } const int optionOffsetCol = ColOffset + 3; const int optionOffsetRow = RowOffset + 2; string[] menuItems = new[] { "Resume game", "Help", "Options", "Save or quit" }; Screen.WriteListOfChoices(optionOffsetRow, optionOffsetCol, menuItems, linesBetweenEach: 1); Screen.ResumeUpdates(); ConsoleKeyInfo key = Input.ReadKey(false); switch (key.Key) { case ConsoleKey.A: break; case ConsoleKey.B: //todo break; case ConsoleKey.C: OptionsScreen.Show(); //todo break; case ConsoleKey.D: //todo, ask for confirm Program.Quit(); break; } }
public EscapeMenu(GameRunUI ui) : base(ui) { }
public GameUIObject(GameRunUI ui) : base(ui.GameUniverse) { GameRunUI = ui; }
const string SeparatorBar = "------------------------------------------------------------------"; // 66, equal to map display width public CharacterScreens(GameRunUI ui) : base(ui) { }
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); } } } }
public Sidebar(GameRunUI ui) : base(ui) { //todo }