feat(game): world-state engine (GameState, Condition/Effect, evaluator/applier)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package thb.jeanluc.adventure.game;
|
||||
|
||||
import thb.jeanluc.adventure.model.Condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Evaluates {@link Condition}s against a {@link GameContext}. */
|
||||
public final class Conditions {
|
||||
|
||||
private Conditions() {
|
||||
}
|
||||
|
||||
public static boolean holds(Condition c, GameContext ctx) {
|
||||
return switch (c.type()) {
|
||||
case FLAG -> ctx.getState().isSet(c.arg());
|
||||
case NOT_FLAG -> !ctx.getState().isSet(c.arg());
|
||||
case HAS_ITEM -> ctx.getPlayer().hasItem(c.arg());
|
||||
};
|
||||
}
|
||||
|
||||
/** True iff every condition holds. A null or empty list is vacuously true. */
|
||||
public static boolean all(List<Condition> conditions, GameContext ctx) {
|
||||
if (conditions == null) {
|
||||
return true;
|
||||
}
|
||||
for (Condition c : conditions) {
|
||||
if (!holds(c, ctx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package thb.jeanluc.adventure.game;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import thb.jeanluc.adventure.model.Effect;
|
||||
import thb.jeanluc.adventure.model.item.Item;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Applies {@link Effect}s to a {@link GameContext}. */
|
||||
@Slf4j
|
||||
public final class Effects {
|
||||
|
||||
private Effects() {
|
||||
}
|
||||
|
||||
public static void apply(Effect e, GameContext ctx) {
|
||||
switch (e.type()) {
|
||||
case SET_FLAG -> ctx.getState().set(e.arg());
|
||||
case CLEAR_FLAG -> ctx.getState().clear(e.arg());
|
||||
case GIVE_ITEM -> {
|
||||
Item it = ctx.getWorld().getItems().get(e.arg());
|
||||
if (it == null) {
|
||||
log.warn("Effect GIVE_ITEM references unknown item '{}'", e.arg());
|
||||
} else {
|
||||
ctx.getPlayer().addItem(it);
|
||||
}
|
||||
}
|
||||
case REMOVE_ITEM -> ctx.getPlayer().removeItem(e.arg());
|
||||
case SAY -> ctx.getIo().write(e.arg());
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies each effect in order. A null list is a no-op. */
|
||||
public static void applyAll(List<Effect> effects, GameContext ctx) {
|
||||
if (effects == null) {
|
||||
return;
|
||||
}
|
||||
for (Effect e : effects) {
|
||||
apply(e, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,4 +23,7 @@ public class GameContext {
|
||||
|
||||
/** IO channel for reading input and writing output. */
|
||||
private final GameIO io;
|
||||
|
||||
/** Mutable world flags. Created fresh per context; not a constructor arg. */
|
||||
private final GameState state = new GameState();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package thb.jeanluc.adventure.game;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/** Named world flags. A flag is "set" (true) when present in the set. */
|
||||
public class GameState {
|
||||
|
||||
private final Set<String> flags = new LinkedHashSet<>();
|
||||
|
||||
public boolean isSet(String flag) {
|
||||
return flags.contains(flag);
|
||||
}
|
||||
|
||||
public void set(String flag) {
|
||||
flags.add(flag);
|
||||
}
|
||||
|
||||
public void clear(String flag) {
|
||||
flags.remove(flag);
|
||||
}
|
||||
|
||||
public Set<String> all() {
|
||||
return Collections.unmodifiableSet(flags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package thb.jeanluc.adventure.model;
|
||||
|
||||
/** A single boolean test evaluated against world state and the player. */
|
||||
public record Condition(Type type, String arg) {
|
||||
public enum Type { FLAG, NOT_FLAG, HAS_ITEM }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package thb.jeanluc.adventure.model;
|
||||
|
||||
/** A single state mutation or message. */
|
||||
public record Effect(Type type, String arg) {
|
||||
public enum Type { SET_FLAG, CLEAR_FLAG, GIVE_ITEM, REMOVE_ITEM, SAY }
|
||||
}
|
||||
Reference in New Issue
Block a user