diff --git a/NetAF.Tests/Commands/Global/CommandList_Tests.cs b/NetAF.Tests/Commands/Global/CommandList_Tests.cs
new file mode 100644
index 00000000..f143fc64
--- /dev/null
+++ b/NetAF.Tests/Commands/Global/CommandList_Tests.cs
@@ -0,0 +1,45 @@
+using NetAF.Assets;
+using NetAF.Assets.Characters;
+using NetAF.Assets.Locations;
+using NetAF.Commands.Global;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NetAF.Logic;
+using NetAF.Logic.Modes;
+using NetAF.Commands;
+
+namespace NetAF.Tests.Commands.Global
+{
+ [TestClass]
+ public class CommandList_Tests
+ {
+ [TestMethod]
+ public void GivenNullGame_WhenInvoke_ThenError()
+ {
+ var command = new CommandList();
+
+ var result = command.Invoke(null);
+
+ Assert.AreEqual(ReactionResult.Error, result.Result);
+ }
+
+ [TestMethod]
+ public void GivenValidGame_WhenInvoke_ThenGameModeChanged()
+ {
+ var room = new Room(Identifier.Empty, Description.Empty);
+ var character = new PlayableCharacter(Identifier.Empty, Description.Empty);
+ var item = new Item(new Identifier("A"), Description.Empty, true);
+ room.AddItem(item);
+ var region = new Region(string.Empty, string.Empty);
+ region.AddRoom(room, 0, 0, 0);
+ var overworld = new Overworld(string.Empty, string.Empty);
+ overworld.AddRegion(region);
+ var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, character), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+ game.ChangeMode(new AboutMode());
+ var command = new CommandList();
+
+ var result = command.Invoke(game);
+
+ Assert.AreEqual(ReactionResult.GameModeChanged, result.Result);
+ }
+ }
+}
diff --git a/NetAF.Tests/Commands/Global/Help_Tests.cs b/NetAF.Tests/Commands/Global/Help_Tests.cs
index 363249e6..e285f7b0 100644
--- a/NetAF.Tests/Commands/Global/Help_Tests.cs
+++ b/NetAF.Tests/Commands/Global/Help_Tests.cs
@@ -15,7 +15,7 @@ public class Help_Tests
[TestMethod]
public void GivenNullGame_WhenInvoke_ThenError()
{
- var command = new Help();
+ var command = new Help(End.CommandHelp);
var result = command.Invoke(null);
@@ -35,7 +35,7 @@ public void GivenValidGame_WhenInvoke_ThenGameModeChanged()
overworld.AddRegion(region);
var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, character), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
game.ChangeMode(new AboutMode());
- var command = new Help();
+ var command = new Help(End.CommandHelp);
var result = command.Invoke(game);
diff --git a/NetAF.Tests/Extensions/CommandHelpExtensions_Tests.cs b/NetAF.Tests/Extensions/CommandHelpExtensions_Tests.cs
deleted file mode 100644
index b4ebd221..00000000
--- a/NetAF.Tests/Extensions/CommandHelpExtensions_Tests.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using NetAF.Extensions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using NetAF.Commands;
-
-namespace NetAF.Tests.Extensions
-{
- [TestClass]
- public class CommandHelpExtensions_Tests
- {
- [TestMethod]
- public void GivenCommandAShortcutB_WhenFormattedToDisplayShortcut_ThenCommandIsAForwardSlashB()
- {
- var result = new CommandHelp("A", string.Empty, "B").FormattedToDisplayShortcut();
-
- Assert.AreEqual("A/B", result.Command);
- }
-
- [TestMethod]
- public void GivenCommandAShortcutB_FormattedToDisplayShortcutAndVariable_ThenCommandIsAForwardSlashBSpaceUnderscoreUnderscore()
- {
- var result = new CommandHelp("A", string.Empty, "B").FormattedToDisplayShortcutAndVariable();
-
- Assert.AreEqual("A/B __", result.Command);
- }
- }
-}
diff --git a/NetAF.Tests/Interpretation/GlobalCommandInterpreter_Tests.cs b/NetAF.Tests/Interpretation/GlobalCommandInterpreter_Tests.cs
index ffc37f2e..f568b2f8 100644
--- a/NetAF.Tests/Interpretation/GlobalCommandInterpreter_Tests.cs
+++ b/NetAF.Tests/Interpretation/GlobalCommandInterpreter_Tests.cs
@@ -4,6 +4,7 @@
using NetAF.Interpretation;
using NetAF.Logic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NetAF.Logic.Modes;
namespace NetAF.Tests.Interpretation
{
@@ -67,13 +68,59 @@ public void GivenExit_WhenInterpret_ThenReturnTrue()
}
[TestMethod]
- public void GivenHelp_WhenInterpret_ThenReturnTrue()
+ public void GivenHelpWithCommand_WhenInterpret_ThenReturnTrue()
+ {
+ var interpreter = new GlobalCommandInterpreter();
+ var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+ game.ChangeMode(new SceneMode());
+
+ var result = interpreter.Interpret($"{NetAF.Commands.Global.Help.CommandHelp.Command} {NetAF.Commands.Scene.Examine.CommandHelp.Command}", game);
+
+ Assert.IsTrue(result.WasInterpretedSuccessfully);
+ }
+
+ [TestMethod]
+ public void GivenHelpWithShortcut_WhenInterpret_ThenReturnTrue()
+ {
+ var interpreter = new GlobalCommandInterpreter();
+ var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+ game.ChangeMode(new SceneMode());
+
+ var result = interpreter.Interpret($"{NetAF.Commands.Global.Help.CommandHelp.Command} {NetAF.Commands.Scene.Examine.CommandHelp.Shortcut}", game);
+
+ Assert.IsTrue(result.WasInterpretedSuccessfully);
+ }
+
+ [TestMethod]
+ public void GivenHelpWithNoCommand_WhenInterpret_ThenReturnFalse()
{
var interpreter = new GlobalCommandInterpreter();
var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
var result = interpreter.Interpret(NetAF.Commands.Global.Help.CommandHelp.Command, game);
+ Assert.IsFalse(result.WasInterpretedSuccessfully);
+ }
+
+ [TestMethod]
+ public void GivenHelpWithUnknownCommand_WhenInterpret_ThenReturnFalse()
+ {
+ var interpreter = new GlobalCommandInterpreter();
+ var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+
+ var result = interpreter.Interpret($"{NetAF.Commands.Global.Help.CommandHelp.Command} ABC", game);
+
+ Assert.IsFalse(result.WasInterpretedSuccessfully);
+ }
+
+ [TestMethod]
+ public void GivenCommands_WhenInterpret_ThenReturnTrue()
+ {
+ var interpreter = new GlobalCommandInterpreter();
+ var game = Game.Create(new GameInfo(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworld, new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+
+ var result = interpreter.Interpret(NetAF.Commands.Global.CommandList.CommandHelp.Command, game);
+
Assert.IsTrue(result.WasInterpretedSuccessfully);
}
diff --git a/NetAF.Tests/Logic/Game_Tests.cs b/NetAF.Tests/Logic/Game_Tests.cs
index 68043118..9e175cea 100644
--- a/NetAF.Tests/Logic/Game_Tests.cs
+++ b/NetAF.Tests/Logic/Game_Tests.cs
@@ -9,12 +9,28 @@
using NetAF.Logic.Modes;
using NetAF.Logic.Configuration;
using NetAF.Commands;
+using NetAF.Commands.Scene;
namespace NetAF.Tests.Logic
{
[TestClass]
public class Game_Tests
{
+ [TestMethod]
+ public void GivenEmptyRoom_WhenGetContextualCommands_ThenNotNullOrEmpty()
+ {
+ RegionMaker regionMaker = new(string.Empty, string.Empty);
+ Room room = new(string.Empty, string.Empty);
+ regionMaker[0, 0, 0] = room;
+ OverworldMaker overworldMaker = new(string.Empty, string.Empty, regionMaker);
+ var game = Game.Create(new(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworldMaker.Make(), new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+
+ var result = game.GetContextualCommands();
+
+ Assert.IsNotNull(result);
+ Assert.IsTrue(result.Length > 0);
+ }
+
[TestMethod]
public void GivenEmptyRoom_WhenGetAllPlayerVisibleExaminables_ThenNotNull()
{
@@ -165,6 +181,21 @@ public void GivenSimpleGame_WhenChangeModeToAbout_ThenNoExceptionThrown()
});
}
+ [TestMethod]
+ public void GivenSimpleGame_WhenChangeModeToCommandList_ThenNoExceptionThrown()
+ {
+ Assertions.NoExceptionThrown(() =>
+ {
+ RegionMaker regionMaker = new(string.Empty, string.Empty);
+ Room room = new(string.Empty, string.Empty);
+ regionMaker[0, 0, 0] = room;
+ OverworldMaker overworldMaker = new(string.Empty, string.Empty, regionMaker);
+ var game = Game.Create(new(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworldMaker.Make(), new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+
+ game.ChangeMode(new CommandListMode([]));
+ });
+ }
+
[TestMethod]
public void GivenSimpleGame_WhenChangeModeToHelp_ThenNoExceptionThrown()
{
@@ -176,7 +207,7 @@ public void GivenSimpleGame_WhenChangeModeToHelp_ThenNoExceptionThrown()
OverworldMaker overworldMaker = new(string.Empty, string.Empty, regionMaker);
var game = Game.Create(new(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworldMaker.Make(), new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
- game.ChangeMode(new HelpMode([]));
+ game.ChangeMode(new HelpMode(Take.CommandHelp));
});
}
diff --git a/NetAF.Tests/Logic/Modes/CommandListMode_Tests.cs b/NetAF.Tests/Logic/Modes/CommandListMode_Tests.cs
new file mode 100644
index 00000000..65cb4985
--- /dev/null
+++ b/NetAF.Tests/Logic/Modes/CommandListMode_Tests.cs
@@ -0,0 +1,31 @@
+using NetAF.Logic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NetAF.Assets.Characters;
+using NetAF.Assets.Locations;
+using NetAF.Utilities;
+using NetAF.Logic.Modes;
+using NetAF.Commands.Global;
+using NetAF.Commands.Scene;
+
+namespace NetAF.Tests.Logic.Modes
+{
+ [TestClass]
+ public class CommandListMode_Tests
+ {
+ [TestMethod]
+ public void GivenNew_WhenRender_ThenNoExceptionThrown()
+ {
+ Assertions.NoExceptionThrown(() =>
+ {
+ RegionMaker regionMaker = new(string.Empty, string.Empty);
+ Room room = new(string.Empty, string.Empty);
+ regionMaker[0, 0, 0] = room;
+ OverworldMaker overworldMaker = new(string.Empty, string.Empty, regionMaker);
+ var game = Game.Create(new(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworldMaker.Make(), new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
+ var mode = new CommandListMode([End.CommandHelp, Take.CommandHelp]);
+
+ mode.Render(game);
+ });
+ }
+ }
+}
diff --git a/NetAF.Tests/Logic/Modes/HelpMode_Tests.cs b/NetAF.Tests/Logic/Modes/HelpMode_Tests.cs
index add422e8..8d8598a8 100644
--- a/NetAF.Tests/Logic/Modes/HelpMode_Tests.cs
+++ b/NetAF.Tests/Logic/Modes/HelpMode_Tests.cs
@@ -4,6 +4,7 @@
using NetAF.Assets.Locations;
using NetAF.Utilities;
using NetAF.Logic.Modes;
+using NetAF.Commands.Global;
namespace NetAF.Tests.Logic.Modes
{
@@ -20,7 +21,7 @@ public void GivenNew_WhenRender_ThenNoExceptionThrown()
regionMaker[0, 0, 0] = room;
OverworldMaker overworldMaker = new(string.Empty, string.Empty, regionMaker);
var game = Game.Create(new(string.Empty, string.Empty, string.Empty), string.Empty, AssetGenerator.Retained(overworldMaker.Make(), new PlayableCharacter(string.Empty, string.Empty)), GameEndConditions.NoEnd, TestGameConfiguration.Default).Invoke();
- var mode = new HelpMode([]);
+ var mode = new HelpMode(End.CommandHelp);
mode.Render(game);
});
diff --git a/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder_Tests.cs b/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder_Tests.cs
new file mode 100644
index 00000000..8aca9833
--- /dev/null
+++ b/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder_Tests.cs
@@ -0,0 +1,24 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NetAF.Assets;
+using NetAF.Commands.Scene;
+using NetAF.Rendering.FrameBuilders;
+using NetAF.Rendering.FrameBuilders.Console;
+
+namespace NetAF.Tests.Rendering.FrameBuilders.Console
+{
+ [TestClass]
+ public class ConsoleCommandListFrameBuilder_Tests
+ {
+ [TestMethod]
+ public void GivenDefaults_WhenBuild_ThenNoException()
+ {
+ Assertions.NoExceptionThrown(() =>
+ {
+ var gridStringBuilder = new GridStringBuilder();
+ var builder = new ConsoleCommandListFrameBuilder(gridStringBuilder);
+
+ builder.Build(string.Empty, string.Empty, [Take.CommandHelp], new Size(80, 50));
+ });
+ }
+ }
+}
diff --git a/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder_Tests.cs b/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder_Tests.cs
index 710ea808..915763ed 100644
--- a/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder_Tests.cs
+++ b/NetAF.Tests/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder_Tests.cs
@@ -9,14 +9,26 @@ namespace NetAF.Tests.Rendering.FrameBuilders.Console
public class ConsoleHelpFrameBuilder_Tests
{
[TestMethod]
- public void GivenDefaults_WhenBuild_ThenNoException()
+ public void GivenDefaultsWithNoInstructions_WhenBuild_ThenNoException()
{
Assertions.NoExceptionThrown(() =>
{
var gridStringBuilder = new GridStringBuilder();
var builder = new ConsoleHelpFrameBuilder(gridStringBuilder);
- builder.Build(string.Empty, string.Empty, [], new Size(80, 50));
+ builder.Build(new NetAF.Commands.CommandHelp("Test", "Test 2"), new Size(80, 50));
+ });
+ }
+
+ [TestMethod]
+ public void GivenDefaultsWithInstructions_WhenBuild_ThenNoException()
+ {
+ Assertions.NoExceptionThrown(() =>
+ {
+ var gridStringBuilder = new GridStringBuilder();
+ var builder = new ConsoleHelpFrameBuilder(gridStringBuilder);
+
+ builder.Build(new NetAF.Commands.CommandHelp("Test", "Test 2", "Test 3."), new Size(80, 50));
});
}
}
diff --git a/NetAF.Tests/Utilities/StringUtilities_Tests.cs b/NetAF.Tests/Utilities/StringUtilities_Tests.cs
index ab17ba0a..c9b6d944 100644
--- a/NetAF.Tests/Utilities/StringUtilities_Tests.cs
+++ b/NetAF.Tests/Utilities/StringUtilities_Tests.cs
@@ -175,5 +175,32 @@ public void GivenTwoAttributes_WhenConstructAttributesAsString_ThenTestColon1Tab
Assert.AreEqual("Test: 1\tTest2: 1", result);
}
+
+ [TestMethod]
+ public void GivenEmptyString_WhenSplitTextToVerbAndNoun_ThenReturnEmptyVerbAndNoun()
+ {
+ StringUtilities.SplitTextToVerbAndNoun(string.Empty, out var verb, out var noun);
+
+ Assert.AreEqual(string.Empty, verb);
+ Assert.AreEqual(string.Empty, noun);
+ }
+
+ [TestMethod]
+ public void GivenABC_WhenSplitTextToVerbAndNoun_TheNounABCVerbEmpty()
+ {
+ StringUtilities.SplitTextToVerbAndNoun("ABC", out var verb, out var noun);
+
+ Assert.AreEqual("ABC", verb);
+ Assert.AreEqual(string.Empty, noun);
+ }
+
+ [TestMethod]
+ public void GivenABCSpaceXYZ_WhenSplitTextToVerbAndNoun_TheNounABCVerbXYZ()
+ {
+ StringUtilities.SplitTextToVerbAndNoun("ABC XYZ", out var verb, out var noun);
+
+ Assert.AreEqual("ABC", verb);
+ Assert.AreEqual("XYZ", noun);
+ }
}
}
\ No newline at end of file
diff --git a/NetAF/Assets/Locations/Matrix.cs b/NetAF/Assets/Locations/Matrix.cs
index 12c4cdf2..21159c16 100644
--- a/NetAF/Assets/Locations/Matrix.cs
+++ b/NetAF/Assets/Locations/Matrix.cs
@@ -1,6 +1,5 @@
using System;
using System.Linq;
-using System.Security.Cryptography.X509Certificates;
namespace NetAF.Assets.Locations
{
diff --git a/NetAF/Commands/CommandHelp.cs b/NetAF/Commands/CommandHelp.cs
index 4e784ae0..7e352e8d 100644
--- a/NetAF/Commands/CommandHelp.cs
+++ b/NetAF/Commands/CommandHelp.cs
@@ -9,7 +9,9 @@ namespace NetAF.Commands
/// The command.
/// The help.
/// A shortcut for the command.
- public sealed class CommandHelp(string command, string description, string shortcut = "") : IEquatable, IEquatable
+ /// A instructions on how to use the command.
+ /// A string overriding how the command should be displayed..
+ public sealed class CommandHelp(string command, string description, string shortcut = "", string instructions = "", string displayAs = "") : IEquatable, IEquatable
{
#region Properties
@@ -28,6 +30,21 @@ public sealed class CommandHelp(string command, string description, string short
///
public string Shortcut { get; } = shortcut;
+ ///
+ /// Get the instructions of the command.
+ ///
+ public string Instructions { get; } = instructions;
+
+ ///
+ /// Get how this command should be displayed.
+ ///
+ public string DisplayAs { get; } = displayAs;
+
+ ///
+ /// Get a string representing the command as it should be displayed to the user.
+ ///
+ public string DisplayCommand => !string.IsNullOrEmpty(DisplayAs) ? DisplayAs : Command;
+
#endregion
#region Implementation of IEquatable
diff --git a/NetAF/Commands/Global/CommandList.cs b/NetAF/Commands/Global/CommandList.cs
new file mode 100644
index 00000000..5f50bb54
--- /dev/null
+++ b/NetAF/Commands/Global/CommandList.cs
@@ -0,0 +1,37 @@
+using NetAF.Logic.Modes;
+
+namespace NetAF.Commands.Global
+{
+ ///
+ /// Represents the Commands command.
+ ///
+ public sealed class CommandList : ICommand
+ {
+ #region StaticProperties
+
+ ///
+ /// Get the command help.
+ ///
+ public static CommandHelp CommandHelp { get; } = new("Commands", "View a list of commands");
+
+ #endregion
+
+ #region Implementation of ICommand
+
+ ///
+ /// Invoke the command.
+ ///
+ /// The game to invoke the command on.
+ /// The reaction.
+ public Reaction Invoke(Logic.Game game)
+ {
+ if (game == null)
+ return new(ReactionResult.Error, "No game specified.");
+
+ game.ChangeMode(new CommandListMode(game.GetContextualCommands()));
+ return new(ReactionResult.GameModeChanged, string.Empty);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NetAF/Commands/Global/Help.cs b/NetAF/Commands/Global/Help.cs
index 96a961a5..8e40ba90 100644
--- a/NetAF/Commands/Global/Help.cs
+++ b/NetAF/Commands/Global/Help.cs
@@ -1,20 +1,19 @@
using NetAF.Logic.Modes;
-using System.Collections.Generic;
-using System.Linq;
namespace NetAF.Commands.Global
{
///
/// Represents the Help command.
///
- public sealed class Help : ICommand
+ /// The command to display help for.
+ public sealed class Help(CommandHelp command) : ICommand
{
#region StaticProperties
///
/// Get the command help.
///
- public static CommandHelp CommandHelp { get; } = new("Help", "View game help");
+ public static CommandHelp CommandHelp { get; } = new("Help", "View detailed help for a command");
#endregion
@@ -30,15 +29,7 @@ public Reaction Invoke(Logic.Game game)
if (game == null)
return new(ReactionResult.Error, "No game specified.");
- List commands =
- [
- .. game.Configuration.Interpreter.SupportedCommands,
- .. game.Configuration.Interpreter.GetContextualCommandHelp(game),
- .. game.Mode.Interpreter?.SupportedCommands ?? [],
- .. game.Mode.Interpreter?.GetContextualCommandHelp(game) ?? [],
- ];
-
- game.ChangeMode(new HelpMode([.. commands.Distinct()]));
+ game.ChangeMode(new HelpMode(command));
return new(ReactionResult.GameModeChanged, string.Empty);
}
diff --git a/NetAF/Commands/RegionMap/Pan.cs b/NetAF/Commands/RegionMap/Pan.cs
index 373208d9..c94111c2 100644
--- a/NetAF/Commands/RegionMap/Pan.cs
+++ b/NetAF/Commands/RegionMap/Pan.cs
@@ -15,32 +15,32 @@ public sealed class Pan(Direction direction) : ICommand
///
/// Get the command help for north.
///
- public static CommandHelp NorthCommandHelp { get; } = new("North", "Pan north", "N");
+ public static CommandHelp NorthCommandHelp { get; } = new("North", "Pan north", "N", displayAs: "North/N");
///
/// Get the command help for south.
///
- public static CommandHelp SouthCommandHelp { get; } = new("South", "Pan south", "S");
+ public static CommandHelp SouthCommandHelp { get; } = new("South", "Pan south", "S", displayAs: "South/S");
///
/// Get the command help for east.
///
- public static CommandHelp EastCommandHelp { get; } = new("East", "Pan east", "E");
+ public static CommandHelp EastCommandHelp { get; } = new("East", "Pan east", "E", displayAs: "East/E");
///
/// Get the command help for west.
///
- public static CommandHelp WestCommandHelp { get; } = new("West", "Pan west", "W");
+ public static CommandHelp WestCommandHelp { get; } = new("West", "Pan west", "W", displayAs: "West/W");
///
/// Get the command help for up.
///
- public static CommandHelp UpCommandHelp { get; } = new("Up", "Pan up", "U");
+ public static CommandHelp UpCommandHelp { get; } = new("Up", "Pan up", "U", displayAs: "Up/U");
///
/// Get the command help for down.
///
- public static CommandHelp DownCommandHelp { get; } = new("Down", "Pan down", "D");
+ public static CommandHelp DownCommandHelp { get; } = new("Down", "Pan down", "D", displayAs: "Down/D");
#endregion
diff --git a/NetAF/Commands/RegionMap/PanReset.cs b/NetAF/Commands/RegionMap/PanReset.cs
index 6624029a..a782acff 100644
--- a/NetAF/Commands/RegionMap/PanReset.cs
+++ b/NetAF/Commands/RegionMap/PanReset.cs
@@ -12,7 +12,7 @@ public sealed class PanReset : ICommand
///
/// Get the command help.
///
- public static CommandHelp CommandHelp { get; } = new("Reset", "Reset pan", "Z");
+ public static CommandHelp CommandHelp { get; } = new("Reset", "Reset pan", "Z", displayAs: "Reset/Z");
#endregion
diff --git a/NetAF/Commands/Scene/Drop.cs b/NetAF/Commands/Scene/Drop.cs
index fe9b3a12..db768f17 100644
--- a/NetAF/Commands/Scene/Drop.cs
+++ b/NetAF/Commands/Scene/Drop.cs
@@ -13,7 +13,7 @@ public sealed class Drop(Item item) : ICommand
///
/// Get the command help.
///
- public static CommandHelp CommandHelp { get; } = new("Drop", "Drop an item", "R");
+ public static CommandHelp CommandHelp { get; } = new("Drop", "Drop an item", "R", displayAs: "Drop/R __");
#endregion
diff --git a/NetAF/Commands/Scene/Examine.cs b/NetAF/Commands/Scene/Examine.cs
index b5cad198..df95905c 100644
--- a/NetAF/Commands/Scene/Examine.cs
+++ b/NetAF/Commands/Scene/Examine.cs
@@ -13,7 +13,7 @@ public sealed class Examine(IExaminable examinable) : ICommand
///
/// Get the command help.
///
- public static CommandHelp CommandHelp { get; } = new("Examine", "Examine something", "X");
+ public static CommandHelp CommandHelp { get; } = new("Examine", "Examine something", "X", displayAs: "Examine/X __");
#endregion
diff --git a/NetAF/Commands/Scene/Move.cs b/NetAF/Commands/Scene/Move.cs
index 07b5d3b3..3fd2203a 100644
--- a/NetAF/Commands/Scene/Move.cs
+++ b/NetAF/Commands/Scene/Move.cs
@@ -1,5 +1,4 @@
-using NetAF.Assets;
-using NetAF.Assets.Locations;
+using NetAF.Assets.Locations;
namespace NetAF.Commands.Scene
{
@@ -14,32 +13,32 @@ public sealed class Move(Direction direction) : ICommand
///
/// Get the command help for north.
///
- public static CommandHelp NorthCommandHelp { get; } = new("North", "Move north", "N");
+ public static CommandHelp NorthCommandHelp { get; } = new("North", "Move north", "N", displayAs: "North/N");
///
/// Get the command help for south.
///
- public static CommandHelp SouthCommandHelp { get; } = new("South", "Move south", "S");
+ public static CommandHelp SouthCommandHelp { get; } = new("South", "Move south", "S", displayAs: "South/S");
///
/// Get the command help for east.
///
- public static CommandHelp EastCommandHelp { get; } = new("East", "Move east", "E");
+ public static CommandHelp EastCommandHelp { get; } = new("East", "Move east", "E", displayAs: "East/E");
///
/// Get the command help for west.
///
- public static CommandHelp WestCommandHelp { get; } = new("West", "Move west", "W");
+ public static CommandHelp WestCommandHelp { get; } = new("West", "Move west", "W", displayAs: "West/W");
///
/// Get the command help for up.
///
- public static CommandHelp UpCommandHelp { get; } = new("Up", "Move up", "U");
+ public static CommandHelp UpCommandHelp { get; } = new("Up", "Move up", "U", displayAs: "Up/U");
///
/// Get the command help for down.
///
- public static CommandHelp DownCommandHelp { get; } = new("Down", "Move down", "D");
+ public static CommandHelp DownCommandHelp { get; } = new("Down", "Move down", "D", displayAs: "Down/D");
#endregion
diff --git a/NetAF/Commands/Scene/Take.cs b/NetAF/Commands/Scene/Take.cs
index 1ad15c3e..fe99411d 100644
--- a/NetAF/Commands/Scene/Take.cs
+++ b/NetAF/Commands/Scene/Take.cs
@@ -13,7 +13,7 @@ public sealed class Take(Item item) : ICommand
///
/// Get the command help.
///
- public static CommandHelp CommandHelp { get; } = new("Take", "Take an item", "T");
+ public static CommandHelp CommandHelp { get; } = new("Take", "Take an item", "T", displayAs: "Take/T __");
#endregion
diff --git a/NetAF/Commands/Scene/Talk.cs b/NetAF/Commands/Scene/Talk.cs
index dfc4b1f6..df43534c 100644
--- a/NetAF/Commands/Scene/Talk.cs
+++ b/NetAF/Commands/Scene/Talk.cs
@@ -14,7 +14,7 @@ public sealed class Talk(IConverser converser) : ICommand
///
/// Get the command help.
///
- public static CommandHelp TalkCommandHelp { get; } = new("Talk", "Talk to a character", "L");
+ public static CommandHelp TalkCommandHelp { get; } = new("Talk", "Talk to a character", "L", displayAs: $"Talk/L to __");
///
/// Get the command help for to.
diff --git a/NetAF/Commands/Scene/UseOn.cs b/NetAF/Commands/Scene/UseOn.cs
index 4af74898..e6713ac1 100644
--- a/NetAF/Commands/Scene/UseOn.cs
+++ b/NetAF/Commands/Scene/UseOn.cs
@@ -19,12 +19,12 @@ public sealed class UseOn(Item item, IInteractWithItem target) : ICommand
///
/// Get the command help.
///
- public static CommandHelp UseCommandHelp { get; } = new("Use", "Use an item on the current room");
+ public static CommandHelp UseCommandHelp { get; } = new("Use", "Use an item on the current room", displayAs: "Use __");
///
/// Get the command help for on.
///
- public static CommandHelp OnCommandHelp { get; } = new("On", "Use an item on another item or character");
+ public static CommandHelp OnCommandHelp { get; } = new("On", "Use an item on another item or character", displayAs: "Use __ on __");
#endregion
diff --git a/NetAF/Extensions/CommandHelpExtensions.cs b/NetAF/Extensions/CommandHelpExtensions.cs
deleted file mode 100644
index 04ac21a6..00000000
--- a/NetAF/Extensions/CommandHelpExtensions.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using NetAF.Commands;
-
-namespace NetAF.Extensions
-{
- ///
- /// Provides extension methods for CommandHelp.
- ///
- public static class CommandHelpExtensions
- {
- #region Extensions
-
- ///
- /// Returns this CommandHelp formatted to display command in the format Command/Shortcut.
- ///
- /// The value.
- /// The formatted CommandHelp.
- public static CommandHelp FormattedToDisplayShortcut(this CommandHelp value)
- {
- return new($"{value.Command}/{value.Shortcut}", value.Description);
- }
-
- ///
- /// Returns this CommandHelp formatted to display command in the format Command/Shortcut __.
- ///
- /// The value.
- /// The formatted CommandHelp.
- public static CommandHelp FormattedToDisplayShortcutAndVariable(this CommandHelp value)
- {
- return new($"{value.Command}/{value.Shortcut} __", value.Description);
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/NetAF/Interpretation/FrameCommandInterpreter.cs b/NetAF/Interpretation/FrameCommandInterpreter.cs
index df85a912..b8b2de54 100644
--- a/NetAF/Interpretation/FrameCommandInterpreter.cs
+++ b/NetAF/Interpretation/FrameCommandInterpreter.cs
@@ -16,8 +16,10 @@ public sealed class FrameCommandInterpreter : IInterpreter
///
public static CommandHelp[] DefaultSupportedCommands { get; } =
[
- new CommandHelp($"{CommandsOn.CommandHelp.Command} / {CommandsOff.CommandHelp.Command}", "Turn commands on/off"),
- new CommandHelp($"{KeyOn.CommandHelp.Command} / {KeyOff.CommandHelp.Command} ", "Turn the key on/off")
+ CommandsOn.CommandHelp,
+ CommandsOff.CommandHelp,
+ KeyOn.CommandHelp,
+ KeyOff.CommandHelp
];
#endregion
diff --git a/NetAF/Interpretation/GlobalCommandInterpreter.cs b/NetAF/Interpretation/GlobalCommandInterpreter.cs
index 3f23b3a9..0140ea2d 100644
--- a/NetAF/Interpretation/GlobalCommandInterpreter.cs
+++ b/NetAF/Interpretation/GlobalCommandInterpreter.cs
@@ -1,6 +1,9 @@
using NetAF.Commands;
using NetAF.Commands.Global;
+using NetAF.Extensions;
using NetAF.Logic;
+using NetAF.Utilities;
+using System;
namespace NetAF.Interpretation
{
@@ -19,7 +22,9 @@ public sealed class GlobalCommandInterpreter : IInterpreter
About.CommandHelp,
Map.CommandHelp,
Exit.CommandHelp,
- New.CommandHelp
+ New.CommandHelp,
+ Help.CommandHelp,
+ CommandList.CommandHelp
];
#endregion
@@ -39,19 +44,33 @@ public sealed class GlobalCommandInterpreter : IInterpreter
/// The result of the interpretation.
public InterpretationResult Interpret(string input, Game game)
{
- if (About.CommandHelp.Equals(input))
+ StringUtilities.SplitTextToVerbAndNoun(input, out var verb, out var noun);
+
+ if (About.CommandHelp.Equals(verb))
return new(true, new About());
- if (Exit.CommandHelp.Equals(input))
+ if (Exit.CommandHelp.Equals(verb))
return new(true, new Exit());
- if (Help.CommandHelp.Equals(input))
- return new(true, new Help());
+ if (Help.CommandHelp.Equals(verb))
+ {
+ if (string.IsNullOrEmpty(noun))
+ return InterpretationResult.Fail;
+
+ var commands = game.GetContextualCommands();
+ var command = Array.Find(commands, x => x.Command.InsensitiveEquals(noun) || x.Shortcut.InsensitiveEquals(noun));
+
+ if (command != null)
+ return new(true, new Help(command));
+ }
+
+ if (CommandList.CommandHelp.Equals(verb))
+ return new(true, new CommandList());
- if (Map.CommandHelp.Equals(input))
+ if (Map.CommandHelp.Equals(verb))
return new(true, new Map());
- if (New.CommandHelp.Equals(input))
+ if (New.CommandHelp.Equals(verb))
return new(true, new New());
return InterpretationResult.Fail;
diff --git a/NetAF/Interpretation/RegionMapCommandInterpreter.cs b/NetAF/Interpretation/RegionMapCommandInterpreter.cs
index 3e0edfdd..d17823ee 100644
--- a/NetAF/Interpretation/RegionMapCommandInterpreter.cs
+++ b/NetAF/Interpretation/RegionMapCommandInterpreter.cs
@@ -2,7 +2,6 @@
using NetAF.Commands;
using NetAF.Commands.Global;
using NetAF.Commands.RegionMap;
-using NetAF.Extensions;
using NetAF.Logic;
using NetAF.Logic.Modes;
using System.Collections.Generic;
@@ -21,13 +20,13 @@ public sealed class RegionMapCommandInterpreter : IInterpreter
///
public static CommandHelp[] DefaultSupportedCommands { get; } =
[
- Pan.NorthCommandHelp.FormattedToDisplayShortcut(),
- Pan.SouthCommandHelp.FormattedToDisplayShortcut(),
- Pan.EastCommandHelp.FormattedToDisplayShortcut(),
- Pan.WestCommandHelp.FormattedToDisplayShortcut(),
- Pan.UpCommandHelp.FormattedToDisplayShortcut(),
- Pan.DownCommandHelp.FormattedToDisplayShortcut(),
- PanReset.CommandHelp.FormattedToDisplayShortcut(),
+ Pan.NorthCommandHelp,
+ Pan.SouthCommandHelp,
+ Pan.EastCommandHelp,
+ Pan.WestCommandHelp,
+ Pan.UpCommandHelp,
+ Pan.DownCommandHelp,
+ PanReset.CommandHelp,
End.CommandHelp,
];
@@ -87,25 +86,25 @@ public CommandHelp[] GetContextualCommandHelp(Game game)
if (game.Mode is RegionMapMode regionMapMode)
{
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.North)))
- commands.Add(Pan.NorthCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.NorthCommandHelp);
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.South)))
- commands.Add(Pan.SouthCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.SouthCommandHelp);
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.East)))
- commands.Add(Pan.EastCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.EastCommandHelp);
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.West)))
- commands.Add(Pan.WestCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.WestCommandHelp);
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.Up)))
- commands.Add(Pan.UpCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.UpCommandHelp);
if (RegionMapMode.CanPanToPosition(game.Overworld.CurrentRegion, Pan.GetPanPosition(regionMapMode.FocusPosition, Direction.Down)))
- commands.Add(Pan.DownCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Pan.DownCommandHelp);
if (!regionMapMode.FocusPosition.Equals(game.Overworld.CurrentRegion.GetPositionOfRoom(game.Overworld.CurrentRegion.CurrentRoom)))
- commands.Add(PanReset.CommandHelp.FormattedToDisplayShortcut());
+ commands.Add(PanReset.CommandHelp);
commands.Add(new CommandHelp(End.CommandHelp.Command, "Finish looking at the map"));
}
diff --git a/NetAF/Interpretation/SceneCommandInterpreter.cs b/NetAF/Interpretation/SceneCommandInterpreter.cs
index 2d721d21..527743b8 100644
--- a/NetAF/Interpretation/SceneCommandInterpreter.cs
+++ b/NetAF/Interpretation/SceneCommandInterpreter.cs
@@ -8,6 +8,7 @@
using NetAF.Extensions;
using NetAF.Logic;
using NetAF.Logic.Modes;
+using NetAF.Utilities;
namespace NetAF.Interpretation
{
@@ -38,11 +39,6 @@ public sealed class SceneCommandInterpreter : IInterpreter
///
public const string Overworld = "Overworld";
- ///
- /// Get a string representing a variable.
- ///
- private const string Variable = "__";
-
#endregion
#region StaticProperties
@@ -52,67 +48,25 @@ public sealed class SceneCommandInterpreter : IInterpreter
///
public static CommandHelp[] DefaultSupportedCommands { get; } =
[
- Move.NorthCommandHelp.FormattedToDisplayShortcut(),
- Move.EastCommandHelp.FormattedToDisplayShortcut(),
- Move.SouthCommandHelp.FormattedToDisplayShortcut(),
- Move.WestCommandHelp.FormattedToDisplayShortcut(),
- Move.UpCommandHelp.FormattedToDisplayShortcut(),
- Move.DownCommandHelp.FormattedToDisplayShortcut(),
- Drop.CommandHelp.FormattedToDisplayShortcutAndVariable(),
- Examine.CommandHelp.FormattedToDisplayShortcutAndVariable(),
- Take.CommandHelp.FormattedToDisplayShortcutAndVariable(),
+ Move.NorthCommandHelp,
+ Move.EastCommandHelp,
+ Move.SouthCommandHelp,
+ Move.WestCommandHelp,
+ Move.UpCommandHelp,
+ Move.DownCommandHelp,
+ Drop.CommandHelp,
+ Examine.CommandHelp,
+ Take.CommandHelp,
TakeAll.CommandHelp,
- GetTalkToCommandHelp(),
- UseOn.UseCommandHelp.FormattedToDisplayShortcutAndVariable(),
- GetUseOnCommandHelp()
+ Talk.TalkCommandHelp,
+ UseOn.UseCommandHelp,
+ UseOn.OnCommandHelp
];
#endregion
#region StaticMethods
- ///
- /// Get a command help for the talk to command.
- ///
- /// The command help.
- private static CommandHelp GetTalkToCommandHelp()
- {
- return new($"{Talk.TalkCommandHelp.Command}/{Talk.TalkCommandHelp.Shortcut} {Talk.ToCommandHelp.Command.ToLower()} {Variable}", Talk.TalkCommandHelp.Description);
- }
-
- ///
- /// Get a command help for the use on command.
- ///
- /// The command help.
- private static CommandHelp GetUseOnCommandHelp()
- {
- return new($"{UseOn.UseCommandHelp.Command} {Variable} {UseOn.OnCommandHelp.Command.ToLower()} {Variable}", UseOn.OnCommandHelp.Description);
- }
-
- ///
- /// Split text in to a verb and a noun.
- ///
- /// The text to split.
- /// The verb.
- /// The noun.
- private static void SplitTextToVerbAndNoun(string text, out string verb, out string noun)
- {
- // if there is a space
- if (text.IndexOf(" ", StringComparison.Ordinal) > -1)
- {
- // verb all text up to space
- verb = text.Substring(0, text.IndexOf(" ", StringComparison.Ordinal)).Trim();
-
- // noun is all text after space
- noun = text.Substring(text.IndexOf(" ", StringComparison.Ordinal)).Trim();
- }
- else
- {
- verb = text;
- noun = string.Empty;
- }
- }
-
///
/// Try and parse the Drop command.
///
@@ -122,7 +76,7 @@ private static void SplitTextToVerbAndNoun(string text, out string verb, out str
/// True if the input could be parsed, else false.
private static bool TryParseDropCommand(string text, Game game, out ICommand command)
{
- SplitTextToVerbAndNoun(text, out var verb, out var noun);
+ StringUtilities.SplitTextToVerbAndNoun(text, out var verb, out var noun);
if (!Drop.CommandHelp.Equals(verb))
{
@@ -144,7 +98,7 @@ private static bool TryParseDropCommand(string text, Game game, out ICommand com
/// True if the input could be parsed, else false.
private static bool TryParseTakeCommand(string text, Game game, out ICommand command)
{
- SplitTextToVerbAndNoun(text, out var verb, out var noun);
+ StringUtilities.SplitTextToVerbAndNoun(text, out var verb, out var noun);
if (!Take.CommandHelp.Equals(verb))
{
@@ -189,7 +143,7 @@ private static bool TryParseTakeCommand(string text, Game game, out ICommand com
/// True if the input could be parsed, else false.
private static bool TryParseTalkCommand(string text, Game game, out ICommand command)
{
- SplitTextToVerbAndNoun(text, out var verb, out var noun);
+ StringUtilities.SplitTextToVerbAndNoun(text, out var verb, out var noun);
if (!Talk.TalkCommandHelp.Equals(verb))
{
@@ -282,7 +236,7 @@ private static bool TryParseExamineCommandLocations(string noun, Game game, out
/// True if the input could be parsed, else false.
private static bool TryParseExamineCommand(string text, Game game, out ICommand command)
{
- SplitTextToVerbAndNoun(text, out var verb, out var noun);
+ StringUtilities.SplitTextToVerbAndNoun(text, out var verb, out var noun);
if (!Examine.CommandHelp.Equals(verb))
{
@@ -350,7 +304,7 @@ private static bool TryParseExamineCommand(string text, Game game, out ICommand
/// True if the input could be parsed, else false.
private static bool TryParseUseOnCommand(string text, Game game, out ICommand command)
{
- SplitTextToVerbAndNoun(text, out var verb, out var noun);
+ StringUtilities.SplitTextToVerbAndNoun(text, out var verb, out var noun);
if (!UseOn.UseCommandHelp.Equals(verb))
{
@@ -505,41 +459,41 @@ public CommandHelp[] GetContextualCommandHelp(Game game)
List commands = [];
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.North))
- commands.Add(Move.NorthCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.NorthCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.East))
- commands.Add(Move.EastCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.EastCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.South))
- commands.Add(Move.SouthCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.SouthCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.West))
- commands.Add(Move.WestCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.WestCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.Up))
- commands.Add(Move.UpCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.UpCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.CanMove(Direction.Down))
- commands.Add(Move.DownCommandHelp.FormattedToDisplayShortcut());
+ commands.Add(Move.DownCommandHelp);
- commands.Add(Examine.CommandHelp.FormattedToDisplayShortcutAndVariable());
+ commands.Add(Examine.CommandHelp);
if (game.Player.Items.Any())
- commands.Add(Drop.CommandHelp.FormattedToDisplayShortcutAndVariable());
+ commands.Add(Drop.CommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.Items.Any())
{
- commands.Add(Take.CommandHelp.FormattedToDisplayShortcutAndVariable());
+ commands.Add(Take.CommandHelp);
commands.Add(TakeAll.CommandHelp);
}
if (game.Player.CanConverse && game.Overworld.CurrentRegion.CurrentRoom.Characters.Any())
- commands.Add(GetTalkToCommandHelp());
+ commands.Add(Talk.TalkCommandHelp);
if (game.Overworld.CurrentRegion.CurrentRoom.Items.Any() || game.Player.Items.Any())
{
- commands.Add(UseOn.UseCommandHelp.FormattedToDisplayShortcutAndVariable());
- commands.Add(GetUseOnCommandHelp());
+ commands.Add(UseOn.UseCommandHelp);
+ commands.Add(UseOn.OnCommandHelp);
}
return [.. commands];
diff --git a/NetAF/Logic/Game.cs b/NetAF/Logic/Game.cs
index f36d35d9..45254a51 100644
--- a/NetAF/Logic/Game.cs
+++ b/NetAF/Logic/Game.cs
@@ -378,6 +378,23 @@ public IExaminable[] GetAllPlayerVisibleExaminables()
return [.. examinables];
}
+ ///
+ /// Get all commands that are valid in the current context.
+ ///
+ /// An array of all commands that are valid in the current context.
+ public CommandHelp[] GetContextualCommands()
+ {
+ List commands =
+ [
+ .. Configuration.Interpreter.SupportedCommands,
+ .. Configuration.Interpreter.GetContextualCommandHelp(this),
+ .. Mode?.Interpreter?.SupportedCommands ?? [],
+ .. Mode?.Interpreter?.GetContextualCommandHelp(this) ?? [],
+ ];
+
+ return [.. commands.Distinct()];
+ }
+
#endregion
#region StaticMethods
diff --git a/NetAF/Logic/Modes/CommandListMode.cs b/NetAF/Logic/Modes/CommandListMode.cs
new file mode 100644
index 00000000..5032ca30
--- /dev/null
+++ b/NetAF/Logic/Modes/CommandListMode.cs
@@ -0,0 +1,36 @@
+using NetAF.Commands;
+using NetAF.Interpretation;
+
+namespace NetAF.Logic.Modes
+{
+ ///
+ /// Provides a display mode for command list.
+ ///
+ /// The commands to display.
+ public sealed class CommandListMode(CommandHelp[] commands) : IGameMode
+ {
+ #region Implementation of IGameMode
+
+ ///
+ /// Get the interpreter.
+ ///
+ public IInterpreter Interpreter { get; }
+
+ ///
+ /// Get the type of mode this provides.
+ ///
+ public GameModeType Type { get; } = GameModeType.Information;
+
+ ///
+ /// Render the current state of a game.
+ ///
+ /// The game.
+ public void Render(Game game)
+ {
+ var frame = game.Configuration.FrameBuilders.CommandListFrameBuilder.Build("Help", string.Empty, commands, game.Configuration.DisplaySize);
+ game.Configuration.Adapter.RenderFrame(frame);
+ }
+
+ #endregion
+ }
+}
diff --git a/NetAF/Logic/Modes/HelpMode.cs b/NetAF/Logic/Modes/HelpMode.cs
index a58f851e..d2dcc42f 100644
--- a/NetAF/Logic/Modes/HelpMode.cs
+++ b/NetAF/Logic/Modes/HelpMode.cs
@@ -6,8 +6,8 @@ namespace NetAF.Logic.Modes
///
/// Provides a display mode for help.
///
- /// The commands to display.
- public sealed class HelpMode(CommandHelp[] commands) : IGameMode
+ /// The command to display.
+ public sealed class HelpMode(CommandHelp command) : IGameMode
{
#region Implementation of IGameMode
@@ -27,7 +27,7 @@ public sealed class HelpMode(CommandHelp[] commands) : IGameMode
/// The game.
public void Render(Game game)
{
- var frame = game.Configuration.FrameBuilders.HelpFrameBuilder.Build("Help", string.Empty, commands, game.Configuration.DisplaySize);
+ var frame = game.Configuration.FrameBuilders.HelpFrameBuilder.Build(command, game.Configuration.DisplaySize);
game.Configuration.Adapter.RenderFrame(frame);
}
diff --git a/NetAF/Logic/Modes/RegionMapMode.cs b/NetAF/Logic/Modes/RegionMapMode.cs
index 6d6f9801..4e7acbbe 100644
--- a/NetAF/Logic/Modes/RegionMapMode.cs
+++ b/NetAF/Logic/Modes/RegionMapMode.cs
@@ -3,7 +3,6 @@
using NetAF.Interpretation;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.InteropServices.ComTypes;
namespace NetAF.Logic.Modes
{
diff --git a/NetAF/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder.cs
new file mode 100644
index 00000000..087060c0
--- /dev/null
+++ b/NetAF/Rendering/FrameBuilders/Console/ConsoleCommandListFrameBuilder.cs
@@ -0,0 +1,98 @@
+using System.Linq;
+using NetAF.Assets;
+using NetAF.Commands;
+using NetAF.Extensions;
+using NetAF.Rendering.Frames;
+
+namespace NetAF.Rendering.FrameBuilders.Console
+{
+ ///
+ /// Provides a builder of command list frames.
+ ///
+ /// A builder to use for the string layout.
+ public sealed class ConsoleCommandListFrameBuilder(GridStringBuilder gridStringBuilder) : ICommandListFrameBuilder
+ {
+ #region Properties
+
+ ///
+ /// Get or set the background color.
+ ///
+ public AnsiColor BackgroundColor { get; set; }
+
+ ///
+ /// Get or set the border color.
+ ///
+ public AnsiColor BorderColor { get; set; } = AnsiColor.BrightBlack;
+
+ ///
+ /// Get or set the title color.
+ ///
+ public AnsiColor TitleColor { get; set; } = AnsiColor.White;
+
+ ///
+ /// Get or set the description color.
+ ///
+ public AnsiColor DescriptionColor { get; set; } = AnsiColor.White;
+
+ ///
+ /// Get or set the command color.
+ ///
+ public AnsiColor CommandColor { get; set; } = AnsiColor.Green;
+
+ ///
+ /// Get or set the description color.
+ ///
+ public AnsiColor CommandDescriptionColor { get; set; } = AnsiColor.Yellow;
+
+ #endregion
+
+ #region Implementation of ICommandListFrameBuilder
+
+ ///
+ /// Build a frame.
+ ///
+ /// The title.
+ /// The description.
+ /// The command help.
+ /// The size of the frame.
+ public IFrame Build(string title, string description, CommandHelp[] commandHelp, Size size)
+ {
+ gridStringBuilder.Resize(size);
+
+ gridStringBuilder.DrawBoundary(BorderColor);
+
+ var availableWidth = size.Width - 4;
+ const int leftMargin = 2;
+ var padding = (commandHelp.Any() ? commandHelp.Max(x => x.DisplayCommand.Length) : 0) + 1;
+
+ gridStringBuilder.DrawWrapped(title, leftMargin, 2, availableWidth, TitleColor, out _, out var lastY);
+ gridStringBuilder.DrawUnderline(leftMargin, lastY + 1, title.Length, TitleColor);
+
+ if (!string.IsNullOrEmpty(description))
+ gridStringBuilder.DrawCentralisedWrapped(description, lastY + 3, availableWidth, DescriptionColor, out _, out lastY);
+
+ lastY += 2;
+
+ foreach (var command in commandHelp)
+ {
+ if (lastY >= size.Height - 1)
+ break;
+
+ if (!string.IsNullOrEmpty(command.DisplayCommand) && !string.IsNullOrEmpty(command.Description))
+ {
+ gridStringBuilder.DrawWrapped(command.DisplayCommand, leftMargin, lastY + 1, availableWidth, CommandColor, out _, out lastY);
+ gridStringBuilder.DrawWrapped("-", leftMargin + padding, lastY, availableWidth, CommandColor, out _, out lastY);
+ gridStringBuilder.DrawWrapped(command.Description.EnsureFinishedSentence(), leftMargin + padding + 2, lastY, availableWidth, CommandDescriptionColor, out _, out lastY);
+ }
+ else if (!string.IsNullOrEmpty(command.DisplayCommand) && string.IsNullOrEmpty(command.Description))
+ {
+ gridStringBuilder.DrawWrapped(command.DisplayCommand, leftMargin, lastY + 1, availableWidth, CommandColor, out _, out lastY);
+ }
+ }
+
+ return new GridTextFrame(gridStringBuilder, 0, 0, BackgroundColor) { ShowCursor = false };
+ }
+
+ #endregion
+ }
+}
diff --git a/NetAF/Rendering/FrameBuilders/Console/ConsoleConversationFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/Console/ConsoleConversationFrameBuilder.cs
index 61d333f5..b7e87b01 100644
--- a/NetAF/Rendering/FrameBuilders/Console/ConsoleConversationFrameBuilder.cs
+++ b/NetAF/Rendering/FrameBuilders/Console/ConsoleConversationFrameBuilder.cs
@@ -156,7 +156,7 @@ public IFrame Build(string title, IConverser converser, CommandHelp[] contextual
gridStringBuilder.DrawHorizontalDivider(lastY + linePadding, BorderColor);
gridStringBuilder.DrawWrapped(CommandTitle, leftMargin, lastY + 4, availableWidth, ResponseColor, out _, out lastY);
- var maxCommandLength = contextualCommands.Max(x => x.Command.Length);
+ var maxCommandLength = contextualCommands.Max(x => x.DisplayCommand.Length);
const int padding = 4;
var dashStartX = leftMargin + maxCommandLength + padding;
var descriptionStartX = dashStartX + 2;
@@ -164,7 +164,7 @@ public IFrame Build(string title, IConverser converser, CommandHelp[] contextual
foreach (var contextualCommand in contextualCommands)
{
- gridStringBuilder.DrawWrapped(contextualCommand.Command, leftMargin, lastY + 1, availableWidth, ResponseColor, out _, out lastY);
+ gridStringBuilder.DrawWrapped(contextualCommand.DisplayCommand, leftMargin, lastY + 1, availableWidth, ResponseColor, out _, out lastY);
gridStringBuilder.DrawWrapped("-", dashStartX, lastY, availableWidth, ResponseColor, out _, out lastY);
gridStringBuilder.DrawWrapped(contextualCommand.Description, descriptionStartX, lastY, availableWidth, ResponseColor, out _, out lastY);
}
diff --git a/NetAF/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder.cs
index 1eb4cb3e..92bd886b 100644
--- a/NetAF/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder.cs
+++ b/NetAF/Rendering/FrameBuilders/Console/ConsoleHelpFrameBuilder.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using NetAF.Assets;
+using NetAF.Assets;
using NetAF.Commands;
using NetAF.Extensions;
using NetAF.Rendering.Frames;
@@ -24,16 +23,6 @@ public sealed class ConsoleHelpFrameBuilder(GridStringBuilder gridStringBuilder)
///
public AnsiColor BorderColor { get; set; } = AnsiColor.BrightBlack;
- ///
- /// Get or set the title color.
- ///
- public AnsiColor TitleColor { get; set; } = AnsiColor.White;
-
- ///
- /// Get or set the description color.
- ///
- public AnsiColor DescriptionColor { get; set; } = AnsiColor.White;
-
///
/// Get or set the command color.
///
@@ -51,11 +40,9 @@ public sealed class ConsoleHelpFrameBuilder(GridStringBuilder gridStringBuilder)
///
/// Build a frame.
///
- /// The title.
- /// The description.
/// The command help.
/// The size of the frame.
- public IFrame Build(string title, string description, CommandHelp[] commandHelp, Size size)
+ public IFrame Build(CommandHelp commandHelp, Size size)
{
gridStringBuilder.Resize(size);
@@ -63,32 +50,18 @@ public IFrame Build(string title, string description, CommandHelp[] commandHelp,
var availableWidth = size.Width - 4;
const int leftMargin = 2;
- var padding = (commandHelp.Any() ? commandHelp.Max(x => x.Command.Length) : 0) + 1;
-
- gridStringBuilder.DrawWrapped(title, leftMargin, 2, availableWidth, TitleColor, out _, out var lastY);
- gridStringBuilder.DrawUnderline(leftMargin, lastY + 1, title.Length, TitleColor);
-
- if (!string.IsNullOrEmpty(description))
- gridStringBuilder.DrawCentralisedWrapped(description, lastY + 3, availableWidth, DescriptionColor, out _, out lastY);
-
- lastY += 2;
-
- foreach (var command in commandHelp)
- {
- if (lastY >= size.Height - 1)
- break;
-
- if (!string.IsNullOrEmpty(command.Command) && !string.IsNullOrEmpty(command.Description))
- {
- gridStringBuilder.DrawWrapped(command.Command, leftMargin, lastY + 1, availableWidth, CommandColor, out _, out lastY);
- gridStringBuilder.DrawWrapped("-", leftMargin + padding, lastY, availableWidth, CommandColor, out _, out lastY);
- gridStringBuilder.DrawWrapped(command.Description.EnsureFinishedSentence(), leftMargin + padding + 2, lastY, availableWidth, CommandDescriptionColor, out _, out lastY);
- }
- else if (!string.IsNullOrEmpty(command.Command) && string.IsNullOrEmpty(command.Description))
- {
- gridStringBuilder.DrawWrapped(command.Command, leftMargin, lastY + 1, availableWidth, CommandColor, out _, out lastY);
- }
- }
+
+ gridStringBuilder.DrawWrapped(commandHelp.Command, leftMargin, 2, availableWidth, CommandColor, out _, out var lastY);
+ gridStringBuilder.DrawUnderline(leftMargin, lastY + 1, commandHelp.Command.Length, CommandColor);
+
+ lastY += 3;
+
+ var description = !string.IsNullOrEmpty(commandHelp.Instructions) ? commandHelp.Instructions : commandHelp.Description;
+
+ gridStringBuilder.DrawWrapped(description.EnsureFinishedSentence(), leftMargin, lastY, availableWidth, CommandDescriptionColor, out _, out _);
+
+ if (!string.IsNullOrEmpty(commandHelp.DisplayAs))
+ gridStringBuilder.DrawWrapped($"Example: {commandHelp.DisplayAs}", leftMargin, lastY + 2, availableWidth, CommandDescriptionColor, out _, out _);
return new GridTextFrame(gridStringBuilder, 0, 0, BackgroundColor) { ShowCursor = false };
}
diff --git a/NetAF/Rendering/FrameBuilders/Console/ConsoleRegionMapFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/Console/ConsoleRegionMapFrameBuilder.cs
index 1298c38b..c8322e72 100644
--- a/NetAF/Rendering/FrameBuilders/Console/ConsoleRegionMapFrameBuilder.cs
+++ b/NetAF/Rendering/FrameBuilders/Console/ConsoleRegionMapFrameBuilder.cs
@@ -97,7 +97,7 @@ public IFrame Build(Region region, Point3D focusPosition, CommandHelp[] contextu
gridStringBuilder.DrawHorizontalDivider(requiredYToFitAllCommands, BorderColor);
gridStringBuilder.DrawWrapped(CommandTitle, leftMargin, requiredYToFitAllCommands + 2, availableWidth, CommandsColor, out _, out lastY);
- var maxCommandLength = contextualCommands.Max(x => x.Command.Length);
+ var maxCommandLength = contextualCommands.Max(x => x.DisplayCommand.Length);
const int padding = 4;
var dashStartX = leftMargin + maxCommandLength + padding;
var descriptionStartX = dashStartX + 2;
@@ -106,7 +106,7 @@ public IFrame Build(Region region, Point3D focusPosition, CommandHelp[] contextu
for (var index = 0; index < contextualCommands.Length; index++)
{
var contextualCommand = contextualCommands[index];
- gridStringBuilder.DrawWrapped(contextualCommand.Command, leftMargin, lastY + 1, availableWidth, CommandsColor, out _, out lastY);
+ gridStringBuilder.DrawWrapped(contextualCommand.DisplayCommand, leftMargin, lastY + 1, availableWidth, CommandsColor, out _, out lastY);
gridStringBuilder.DrawWrapped("-", dashStartX, lastY, availableWidth, CommandsColor, out _, out lastY);
gridStringBuilder.DrawWrapped(contextualCommand.Description.EnsureFinishedSentence(), descriptionStartX, lastY, availableWidth, CommandsColor, out _, out lastY);
}
diff --git a/NetAF/Rendering/FrameBuilders/Console/ConsoleSceneFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/Console/ConsoleSceneFrameBuilder.cs
index a4c1018a..883846fa 100644
--- a/NetAF/Rendering/FrameBuilders/Console/ConsoleSceneFrameBuilder.cs
+++ b/NetAF/Rendering/FrameBuilders/Console/ConsoleSceneFrameBuilder.cs
@@ -126,7 +126,7 @@ public IFrame Build(Room room, ViewPoint viewPoint, PlayableCharacter player, Co
gridStringBuilder.DrawHorizontalDivider(lastY + linePadding, BorderColor);
gridStringBuilder.DrawWrapped(CommandTitle, leftMargin, lastY + 4, availableWidth, CommandsColor, out _, out lastY);
- var maxCommandLength = contextualCommands.Max(x => x.Command.Length);
+ var maxCommandLength = contextualCommands.Max(x => x.DisplayCommand.Length);
const int padding = 4;
var dashStartX = leftMargin + maxCommandLength + padding;
var descriptionStartX = dashStartX + 2;
@@ -135,7 +135,7 @@ public IFrame Build(Room room, ViewPoint viewPoint, PlayableCharacter player, Co
for (var index = 0; index < contextualCommands.Length; index++)
{
var contextualCommand = contextualCommands[index];
- gridStringBuilder.DrawWrapped(contextualCommand.Command, leftMargin, lastY + 1, availableWidth, CommandsColor, out _, out lastY);
+ gridStringBuilder.DrawWrapped(contextualCommand.DisplayCommand, leftMargin, lastY + 1, availableWidth, CommandsColor, out _, out lastY);
gridStringBuilder.DrawWrapped("-", dashStartX, lastY, availableWidth, CommandsColor, out _, out lastY);
gridStringBuilder.DrawWrapped(contextualCommand.Description.EnsureFinishedSentence(), descriptionStartX, lastY, availableWidth, CommandsColor, out _, out lastY);
diff --git a/NetAF/Rendering/FrameBuilders/FrameBuilderCollection.cs b/NetAF/Rendering/FrameBuilders/FrameBuilderCollection.cs
index e9ae3fd0..488a0c99 100644
--- a/NetAF/Rendering/FrameBuilders/FrameBuilderCollection.cs
+++ b/NetAF/Rendering/FrameBuilders/FrameBuilderCollection.cs
@@ -6,13 +6,14 @@
/// The builder to use for building title frames.
/// The builder to use for building scene frames.
/// The builder to use for building region map frames.
+ /// The builder to use for building command list frames.
/// The builder to use for building help frames.
/// The builder to use for building completion frames.
/// The builder to use for building game over frames.
/// The builder to use for building about frames.
/// The builder to use for building reaction frames.
/// The builder to use for building conversation frames.
- public class FrameBuilderCollection(ITitleFrameBuilder titleFrameBuilder, ISceneFrameBuilder sceneFrameBuilder, IRegionMapFrameBuilder regionMapFrameBuilder, IHelpFrameBuilder helpFrameBuilder, ICompletionFrameBuilder completionFrameBuilder, IGameOverFrameBuilder gameOverFrameBuilder, IAboutFrameBuilder aboutFrameBuilder, IReactionFrameBuilder reactionFrameBuilder, IConversationFrameBuilder conversationFrameBuilder)
+ public class FrameBuilderCollection(ITitleFrameBuilder titleFrameBuilder, ISceneFrameBuilder sceneFrameBuilder, IRegionMapFrameBuilder regionMapFrameBuilder, ICommandListFrameBuilder commandListFrameBuilder, IHelpFrameBuilder helpFrameBuilder, ICompletionFrameBuilder completionFrameBuilder, IGameOverFrameBuilder gameOverFrameBuilder, IAboutFrameBuilder aboutFrameBuilder, IReactionFrameBuilder reactionFrameBuilder, IConversationFrameBuilder conversationFrameBuilder)
{
#region Properties
@@ -31,6 +32,11 @@ public class FrameBuilderCollection(ITitleFrameBuilder titleFrameBuilder, IScene
///
public IRegionMapFrameBuilder RegionMapFrameBuilder { get; } = regionMapFrameBuilder;
+ ///
+ /// Get the builder to use for command list frames.
+ ///
+ public ICommandListFrameBuilder CommandListFrameBuilder { get; } = commandListFrameBuilder;
+
///
/// Get the builder to use for help frames.
///
diff --git a/NetAF/Rendering/FrameBuilders/FrameBuilderCollections.cs b/NetAF/Rendering/FrameBuilders/FrameBuilderCollections.cs
index 1e64beb9..acd2a180 100644
--- a/NetAF/Rendering/FrameBuilders/FrameBuilderCollections.cs
+++ b/NetAF/Rendering/FrameBuilders/FrameBuilderCollections.cs
@@ -20,6 +20,7 @@ public static FrameBuilderCollection Default
new ConsoleTitleFrameBuilder(gridLayoutBuilder),
new ConsoleSceneFrameBuilder(gridLayoutBuilder, new ConsoleRoomMapBuilder(gridLayoutBuilder)),
new ConsoleRegionMapFrameBuilder(gridLayoutBuilder, new ConsoleRegionMapBuilder(gridLayoutBuilder)),
+ new ConsoleCommandListFrameBuilder(gridLayoutBuilder),
new ConsoleHelpFrameBuilder(gridLayoutBuilder),
new ConsoleCompletionFrameBuilder(gridLayoutBuilder),
new ConsoleGameOverFrameBuilder(gridLayoutBuilder),
diff --git a/NetAF/Rendering/FrameBuilders/ICommandListFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/ICommandListFrameBuilder.cs
new file mode 100644
index 00000000..2271c515
--- /dev/null
+++ b/NetAF/Rendering/FrameBuilders/ICommandListFrameBuilder.cs
@@ -0,0 +1,21 @@
+using NetAF.Assets;
+using NetAF.Commands;
+using NetAF.Rendering.Frames;
+
+namespace NetAF.Rendering.FrameBuilders
+{
+ ///
+ /// Represents any object that can build command list frames.
+ ///
+ public interface ICommandListFrameBuilder
+ {
+ ///
+ /// Build a frame.
+ ///
+ /// The title.
+ /// The description.
+ /// The command help.
+ /// The size of the frame.
+ IFrame Build(string title, string description, CommandHelp[] commandHelp, Size size);
+ }
+}
diff --git a/NetAF/Rendering/FrameBuilders/IHelpFrameBuilder.cs b/NetAF/Rendering/FrameBuilders/IHelpFrameBuilder.cs
index 384f98f5..e79ff4da 100644
--- a/NetAF/Rendering/FrameBuilders/IHelpFrameBuilder.cs
+++ b/NetAF/Rendering/FrameBuilders/IHelpFrameBuilder.cs
@@ -12,10 +12,8 @@ public interface IHelpFrameBuilder
///
/// Build a frame.
///
- /// The title.
- /// The description.
/// The command help.
/// The size of the frame.
- IFrame Build(string title, string description, CommandHelp[] commandHelp, Size size);
+ IFrame Build(CommandHelp commandHelp, Size size);
}
}
diff --git a/NetAF/Utilities/StringUtilities.cs b/NetAF/Utilities/StringUtilities.cs
index 65c1c726..09eb1edc 100644
--- a/NetAF/Utilities/StringUtilities.cs
+++ b/NetAF/Utilities/StringUtilities.cs
@@ -1,8 +1,8 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetAF.Assets;
-using NetAF.Assets.Attributes;
using NetAF.Extensions;
namespace NetAF.Utilities
@@ -163,7 +163,7 @@ public static string ConstructExaminablesAsSentence(IExaminable[] examinables)
///
/// The attributes.
/// The sentence.
- public static string ConstructAttributesAsString(Dictionary attributes)
+ public static string ConstructAttributesAsString(Dictionary attributes)
{
if (attributes?.Any() != true)
return string.Empty;
@@ -176,6 +176,30 @@ public static string ConstructAttributesAsString(Dictionary attr
return builder.ToString();
}
+ ///
+ /// Split text in to a verb and a noun.
+ ///
+ /// The text to split.
+ /// The verb.
+ /// The noun.
+ public static void SplitTextToVerbAndNoun(string text, out string verb, out string noun)
+ {
+ // if there is a space
+ if (text.IndexOf(" ", StringComparison.Ordinal) > -1)
+ {
+ // verb all text up to space
+ verb = text.Substring(0, text.IndexOf(" ", StringComparison.Ordinal)).Trim();
+
+ // noun is all text after space
+ noun = text.Substring(text.IndexOf(" ", StringComparison.Ordinal)).Trim();
+ }
+ else
+ {
+ verb = text;
+ noun = string.Empty;
+ }
+ }
+
#endregion
}
}