Files
clawgo/pkg/world/engine_test.go
2026-03-15 23:46:06 +08:00

104 lines
3.2 KiB
Go

package world
import "testing"
func TestVisibleEventsForNPCIncludesNeighborLocationsWithinScope(t *testing.T) {
engine := NewEngine()
state := DefaultWorldState()
npc := NPCState{NPCID: "keeper", CurrentLocation: "commons"}
events := []WorldEvent{
{ID: "a", Type: "noise", LocationID: "square", Content: "neighbor event"},
{ID: "b", Type: "noise", LocationID: "far", Content: "far event"},
}
state.Locations["far"] = Location{ID: "far", Neighbors: []string{}}
out := engine.VisibleEventsForNPC(state, npc, events, 1)
if len(out) != 1 || out[0].ID != "a" {
t.Fatalf("expected only neighbor event, got %+v", out)
}
}
func TestApplyIntentInteractUpdatesEntityState(t *testing.T) {
engine := NewEngine()
state := DefaultWorldState()
state.Entities["fountain"] = Entity{
ID: "fountain",
Name: "Fountain",
LocationID: "square",
State: map[string]interface{}{},
}
npc := &NPCState{NPCID: "merchant", CurrentLocation: "square"}
delta := engine.ApplyIntent(&state, npc, ActionIntent{
ActorID: "merchant",
Action: "interact",
TargetEntity: "fountain",
Speech: "inspects the fountain",
})
if !delta.Applied || delta.Event == nil {
t.Fatalf("expected interact delta to apply, got %+v", delta)
}
entity := state.Entities["fountain"]
if entity.State["last_actor"] != "merchant" {
t.Fatalf("expected entity last_actor updated, got %+v", entity.State)
}
if entity.State["interaction_count"] == nil {
t.Fatalf("expected interaction_count, got %+v", entity.State)
}
}
func TestApplyIntentInteractRejectsDistantEntity(t *testing.T) {
engine := NewEngine()
state := DefaultWorldState()
state.Locations["far"] = Location{ID: "far", Neighbors: []string{}}
state.Entities["orb"] = Entity{
ID: "orb",
LocationID: "far",
}
npc := &NPCState{NPCID: "sage", CurrentLocation: "commons"}
delta := engine.ApplyIntent(&state, npc, ActionIntent{
ActorID: "sage",
Action: "interact",
TargetEntity: "orb",
})
if delta.Applied {
t.Fatalf("expected distant interact to be rejected, got %+v", delta)
}
if delta.Reason != "entity_not_reachable" {
t.Fatalf("unexpected rejection reason: %+v", delta)
}
}
func TestApplyIntentInteractAppliesQuestAndResourceEffects(t *testing.T) {
engine := NewEngine()
state := DefaultWorldState()
state.Entities["chest"] = Entity{
ID: "chest",
LocationID: "square",
State: map[string]interface{}{},
}
npc := &NPCState{NPCID: "rogue", CurrentLocation: "square"}
delta := engine.ApplyIntent(&state, npc, ActionIntent{
ActorID: "rogue",
Action: "interact",
TargetEntity: "chest",
ProposedEffects: map[string]interface{}{
"resource_delta": map[string]interface{}{"gold": 3},
"quest_update": map[string]interface{}{
"id": "find-chest",
"title": "Find The Chest",
"status": "completed",
},
},
})
if !delta.Applied {
t.Fatalf("expected interact to apply, got %+v", delta)
}
resources, ok := state.Entities["chest"].State["resources"].(map[string]int)
if !ok || resources["gold"] != 3 {
t.Fatalf("expected gold resource delta, got %+v", state.Entities["chest"].State)
}
quest := state.ActiveQuests["find-chest"]
if quest.Status != "completed" {
t.Fatalf("expected quest completion, got %+v", quest)
}
}