feat(command): route use X on Y to the combination engine

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 17:31:07 +02:00
parent 6eabebff00
commit 9152aded4b
2 changed files with 71 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
package thb.jeanluc.adventure.command.impl;
import thb.jeanluc.adventure.command.Command;
import thb.jeanluc.adventure.game.Combinations;
import thb.jeanluc.adventure.game.GameContext;
import thb.jeanluc.adventure.model.item.Item;
@@ -20,6 +21,10 @@ public class UseCommand implements Command {
ctx.getIo().write("Use what?");
return;
}
if (args.size() >= 2) {
Combinations.tryUse(ctx, args.get(0), args.get(1));
return;
}
String itemId = args.getFirst();
Optional<Item> item = ctx.getPlayer().findItem(itemId);
if (item.isEmpty()) {
@@ -34,6 +39,6 @@ public class UseCommand implements Command {
@Override
public String help() {
return "use <item> - use an item (read it, switch it on/off, ...)";
return "use <item> - use an item; or use <item> on <item> to combine them";
}
}

View File

@@ -0,0 +1,65 @@
package thb.jeanluc.adventure.command.impl;
import org.junit.jupiter.api.Test;
import thb.jeanluc.adventure.game.GameContext;
import thb.jeanluc.adventure.io.TestIO;
import thb.jeanluc.adventure.model.Combination;
import thb.jeanluc.adventure.model.Player;
import thb.jeanluc.adventure.model.Room;
import thb.jeanluc.adventure.model.World;
import thb.jeanluc.adventure.model.item.Item;
import thb.jeanluc.adventure.model.item.PlainItem;
import thb.jeanluc.adventure.model.item.SwitchableItem;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class UseCommandComboTest {
private GameContext ctx() {
Map<String, Item> items = new LinkedHashMap<>();
items.put("matches", PlainItem.builder().id("matches").name("Matches").description("d").light(false).build());
items.put("torch", PlainItem.builder().id("torch").name("Torch").description("d").light(false).build());
items.put("lit_torch", PlainItem.builder().id("lit_torch").name("Lit Torch").description("d").light(true).build());
SwitchableItem lamp = SwitchableItem.builder()
.id("lamp").name("Lamp").description("d").light(true)
.onText("The lamp glows.").offText("off").state(false).effects(List.of()).build();
items.put("lamp", lamp);
Combination recipe = new Combination("matches", "torch", List.of(),
List.of("matches", "torch"), "lit_torch", List.of(), "You light the torch.", null);
Room start = new Room("start", "Start", "d");
World w = new World(Map.of("start", start), items, Map.of(), "t", "w",
Map.of(), List.of(), Map.of(recipe.key(), recipe));
GameContext ctx = new GameContext(w, new Player(start, 0), new TestIO());
ctx.getPlayer().addItem(items.get("matches"));
ctx.getPlayer().addItem(items.get("torch"));
ctx.getPlayer().addItem(lamp);
return ctx;
}
@Test
void emptyArgsAsksWhat() {
GameContext ctx = ctx();
new UseCommand().execute(ctx, List.of());
assertThat(((TestIO) ctx.getIo()).allOutput()).contains("Use what?");
}
@Test
void twoArgsRoutesToCombination() {
GameContext ctx = ctx();
new UseCommand().execute(ctx, List.of("matches", "torch"));
assertThat(ctx.getPlayer().hasItem("lit_torch")).isTrue();
assertThat(((TestIO) ctx.getIo()).allOutput()).contains("light the torch");
}
@Test
void oneArgUsesItemDirectly() {
GameContext ctx = ctx();
new UseCommand().execute(ctx, List.of("lamp"));
assertThat(((SwitchableItem) ctx.getWorld().getItems().get("lamp")).isOn()).isTrue();
assertThat(((TestIO) ctx.getIo()).allOutput()).contains("lamp glows");
}
}