feat(command): accept German command and direction aliases
The assignment's examples are German ("Gehe nach Norden", "Nimm Brief",
"Lies Brief", "Benutze Schaufel") but every verb was English-only, so none of
them parsed.
- Register German aliases alongside the English ones (gehe, nimm, lies, benutze,
lege, gib, rede, schau, karte, inventar, hilfe, beenden)
- Direction.fromString accepts norden/sueden/süden/osten/westen and the n/s/e/w
shorthands; YAML exits keep the canonical English names
- Treat "nach", "den", "die", "das" as filler words so "Gehe nach Norden" parses
This commit is contained in:
@@ -47,10 +47,15 @@ import java.util.List;
|
||||
@Slf4j
|
||||
public final class App {
|
||||
|
||||
/** Utility class; not instantiable. */
|
||||
private App() {
|
||||
}
|
||||
|
||||
/** Standard JVM entry point. @param args ignored */
|
||||
/**
|
||||
* Standard JVM entry point.
|
||||
*
|
||||
* @param args ignored
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
GameIO io = new ConsoleIO();
|
||||
try {
|
||||
@@ -62,12 +67,22 @@ public final class App {
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs the menu shell on the given IO until the player quits. */
|
||||
/**
|
||||
* Runs the menu shell on the given IO until the player quits.
|
||||
*
|
||||
* @param io frontend the menu and the game are rendered on
|
||||
*/
|
||||
public static void run(GameIO io) {
|
||||
run(io, new SaveService(), new SettingsStore());
|
||||
}
|
||||
|
||||
/** Runs the menu shell with injectable persistence (for testing). */
|
||||
/**
|
||||
* Runs the menu shell with injectable persistence (for testing).
|
||||
*
|
||||
* @param io frontend the menu and the game are rendered on
|
||||
* @param saves save-slot backend
|
||||
* @param settingsStore settings backend
|
||||
*/
|
||||
static void run(GameIO io, SaveService saves, SettingsStore settingsStore) {
|
||||
Settings settings = settingsStore.load();
|
||||
SettingsMenu.apply(settings, io);
|
||||
@@ -112,27 +127,29 @@ public final class App {
|
||||
}
|
||||
});
|
||||
|
||||
// German aliases mirror the examples in the assignment ("Gehe nach
|
||||
// Norden", "Nimm Brief", "Lies Brief", "Benutze Schaufel").
|
||||
CommandRegistry registry = new CommandRegistry();
|
||||
registry.register(new GoCommand(), "go", "move", "walk");
|
||||
registry.register(new LookCommand(), "look", "l");
|
||||
registry.register(new InventoryCommand(), "inventory", "inv", "i");
|
||||
registry.register(new TakeCommand(), "take", "pick", "get");
|
||||
registry.register(new DropCommand(), "drop", "put");
|
||||
registry.register(new UseCommand(), "use");
|
||||
registry.register(new ReadCommand(), "read");
|
||||
registry.register(new ExamineCommand(), "examine", "x", "inspect");
|
||||
registry.register(new MapCommand(), "map", "m");
|
||||
registry.register(new QuestsCommand(), "quests", "log", "journal");
|
||||
registry.register(new TalkCommand(), "talk", "speak");
|
||||
registry.register(new GiveCommand(), "give");
|
||||
registry.register(new SaveCommand(saves), "save");
|
||||
registry.register(new GoCommand(), "go", "move", "walk", "gehe", "geh");
|
||||
registry.register(new LookCommand(), "look", "l", "umsehen", "schau");
|
||||
registry.register(new InventoryCommand(), "inventory", "inv", "i", "inventar");
|
||||
registry.register(new TakeCommand(), "take", "pick", "get", "nimm", "nehme");
|
||||
registry.register(new DropCommand(), "drop", "put", "lege", "ablegen");
|
||||
registry.register(new UseCommand(), "use", "benutze", "benutz");
|
||||
registry.register(new ReadCommand(), "read", "lies", "lese");
|
||||
registry.register(new ExamineCommand(), "examine", "x", "inspect", "untersuche");
|
||||
registry.register(new MapCommand(), "map", "m", "karte");
|
||||
registry.register(new QuestsCommand(), "quests", "log", "journal", "aufgaben");
|
||||
registry.register(new TalkCommand(), "talk", "speak", "rede", "sprich");
|
||||
registry.register(new GiveCommand(), "give", "gib");
|
||||
registry.register(new SaveCommand(saves), "save", "speichern");
|
||||
|
||||
Game game = new Game(ctx, registry, new CommandParser());
|
||||
|
||||
MenuCommand menu = new MenuCommand(saves);
|
||||
menu.bind(game);
|
||||
registry.register(menu, "menu", "quit", "exit");
|
||||
registry.register(new HelpCommand(registry), "help", "?");
|
||||
registry.register(menu, "menu", "quit", "exit", "beenden");
|
||||
registry.register(new HelpCommand(registry), "help", "?", "hilfe");
|
||||
|
||||
if (withTutorial) {
|
||||
Tutorial tutorial = new TutorialLoader().load();
|
||||
|
||||
@@ -16,7 +16,8 @@ public class CommandParser {
|
||||
* small — when adding more, watch out for words that might be valid
|
||||
* item ids ({@code key}, {@code lamp}, etc.).
|
||||
*/
|
||||
private static final Set<String> FILLERS = Set.of("to", "with", "at", "the", "a", "an", "on");
|
||||
private static final Set<String> FILLERS =
|
||||
Set.of("to", "with", "at", "the", "a", "an", "on", "nach", "den", "die", "das");
|
||||
|
||||
/**
|
||||
* Parses an input line into a verb and its arguments.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package thb.jeanluc.adventure.model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Compass directions used for navigating between rooms.
|
||||
* Each direction has an opposite, which is used when describing
|
||||
@@ -7,9 +9,13 @@ package thb.jeanluc.adventure.model;
|
||||
* entering the next room from the SOUTH).
|
||||
*/
|
||||
public enum Direction {
|
||||
/** Towards the top of the map; opposite of {@link #SOUTH}. */
|
||||
NORTH,
|
||||
/** Towards the bottom of the map; opposite of {@link #NORTH}. */
|
||||
SOUTH,
|
||||
/** Towards the right of the map; opposite of {@link #WEST}. */
|
||||
EAST,
|
||||
/** Towards the left of the map; opposite of {@link #EAST}. */
|
||||
WEST;
|
||||
|
||||
/**
|
||||
@@ -38,13 +44,40 @@ public enum Direction {
|
||||
if (s == null) {
|
||||
throw new IllegalArgumentException("Direction must not be null");
|
||||
}
|
||||
String key = s.trim().toLowerCase();
|
||||
Direction alias = ALIASES.get(key);
|
||||
if (alias != null) {
|
||||
return alias;
|
||||
}
|
||||
try {
|
||||
return Direction.valueOf(s.trim().toUpperCase());
|
||||
return Direction.valueOf(key.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Unknown direction: '" + s + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative spellings accepted from player input: single-letter
|
||||
* shorthands and the German direction names used in the assignment's
|
||||
* examples ("Gehe nach Norden"). YAML exits still use the canonical
|
||||
* English names.
|
||||
*/
|
||||
private static final Map<String, Direction> ALIASES = Map.ofEntries(
|
||||
Map.entry("n", NORTH),
|
||||
Map.entry("s", SOUTH),
|
||||
Map.entry("e", EAST),
|
||||
Map.entry("w", WEST),
|
||||
Map.entry("norden", NORTH),
|
||||
Map.entry("sueden", SOUTH),
|
||||
Map.entry("süden", SOUTH),
|
||||
Map.entry("osten", EAST),
|
||||
Map.entry("westen", WEST),
|
||||
Map.entry("nord", NORTH),
|
||||
Map.entry("sued", SOUTH),
|
||||
Map.entry("süd", SOUTH),
|
||||
Map.entry("ost", EAST),
|
||||
Map.entry("west", WEST));
|
||||
|
||||
/**
|
||||
* Returns the human-readable lowercase label, suitable for display
|
||||
* to the player (e.g. "north"). Intentionally not a toString override
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package thb.jeanluc.adventure.command;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import thb.jeanluc.adventure.model.Direction;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The assignment's examples are German ("Gehe nach Norden", "Nimm Brief"), so
|
||||
* those inputs must parse. English stays the canonical form used in YAML.
|
||||
*/
|
||||
class GermanAliasTest {
|
||||
|
||||
private final CommandParser parser = new CommandParser();
|
||||
|
||||
@Test
|
||||
void parse_gehNachNorden_yieldsGoNorth() {
|
||||
ParsedCommand c = parser.parse("Gehe nach Norden");
|
||||
|
||||
assertThat(c.verb()).isEqualTo("gehe");
|
||||
assertThat(c.args()).containsExactly("norden");
|
||||
assertThat(Direction.fromString(c.args().getFirst())).isEqualTo(Direction.NORTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
void parse_nimmBrief_yieldsTakeWithItemArg() {
|
||||
ParsedCommand c = parser.parse("Nimm Brief");
|
||||
|
||||
assertThat(c.verb()).isEqualTo("nimm");
|
||||
assertThat(c.args()).containsExactly("brief");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromString_withGermanDirectionNames_resolves() {
|
||||
assertThat(Direction.fromString("norden")).isEqualTo(Direction.NORTH);
|
||||
assertThat(Direction.fromString("sueden")).isEqualTo(Direction.SOUTH);
|
||||
assertThat(Direction.fromString("süden")).isEqualTo(Direction.SOUTH);
|
||||
assertThat(Direction.fromString("osten")).isEqualTo(Direction.EAST);
|
||||
assertThat(Direction.fromString("westen")).isEqualTo(Direction.WEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromString_withEnglishNames_stillResolves() {
|
||||
assertThat(Direction.fromString("north")).isEqualTo(Direction.NORTH);
|
||||
assertThat(Direction.fromString("n")).isEqualTo(Direction.NORTH);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user