aboutsummaryrefslogtreecommitdiff
path: root/internal/game/core_course_test.go
blob: 93f49f5a546cba1a4340f35ed0632534e44a403b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package game

import (
	"os"
	"path/filepath"
	"testing"
)

func TestResolvePhases(t *testing.T) {
	obs := ObstacleDef{
		RoomID: 5,
		Verb:   "climb",
		Phases: []ObstaclePhase{
			{Message: "start", Delay: 0},
			{Message: "middle", Delay: 2, FailCheck: true},
			{Message: "end", Delay: 1.5},
		},
	}
	got := resolvePhases(obs)
	if len(got) != 3 {
		t.Fatalf("expected 3 phases, got %d", len(got))
	}
	if got[0].Message != "start" || got[0].Delay != 0 || got[0].FailCheck {
		t.Errorf("phase 0 wrong: %+v", got[0])
	}
	if got[1].Message != "middle" || got[1].Delay != 2 || !got[1].FailCheck {
		t.Errorf("phase 1 (fail check) wrong: %+v", got[1])
	}
	if got[2].Message != "end" || got[2].Delay != 1.5 {
		t.Errorf("phase 2 wrong: %+v", got[2])
	}
}

func TestCourseStoreLoadsWithExplicitFailChance(t *testing.T) {
	dir := t.TempDir()
	coursesDir := filepath.Join(dir, "courses")
	if err := os.MkdirAll(coursesDir, 0755); err != nil {
		t.Fatal(err)
	}
	yaml := []byte(`
name: "Test Course"
required_level: 10
start_room: 100
completion_xp: 50
obstacles:
  - room_id: 101
    verb: climb
    xp: 12
    fail_damage: [2, 5]
    fail_chance: 0.20
    phases:
      - message: "begin"
        delay: 0
      - message: "mid"
        delay: 2
        fail_check: true
      - message: "done"
        delay: 2
  - room_id: 102
    verb: jump
    xp: 14
    fail_damage: [1, 3]
    phases:
      - message: "p0"
        delay: 0
      - message: "p1"
        delay: 1
        fail_check: true
      - message: "p2"
        delay: 1
`)
	if err := os.WriteFile(filepath.Join(coursesDir, "testcourse.yaml"), yaml, 0644); err != nil {
		t.Fatal(err)
	}

	cs := NewCourseStore(dir)
	cs.LoadAll()

	// Obstacle 1: explicit phases + explicit fail_chance
	o1 := cs.GetObstacle(101)
	if o1 == nil {
		t.Fatal("expected obstacle for room 101")
	}
	if len(o1.Phases) != 3 || o1.Phases[1].FailCheck != true {
		t.Errorf("obstacle 1 phases wrong: %+v", o1.Phases)
	}
	if o1.FailChance == nil || *o1.FailChance != 0.20 {
		t.Errorf("expected explicit fail_chance 0.20, got %v", o1.FailChance)
	}
	if o1.ObstacleIndex != 0 || o1.TotalObstacles != 2 {
		t.Errorf("index/total wrong: %d/%d", o1.ObstacleIndex, o1.TotalObstacles)
	}
	if o1.NextRoom != 102 {
		t.Errorf("expected next room 102, got %d", o1.NextRoom)
	}
	if o1.CompletionXP != 0 {
		t.Errorf("first obstacle should have no completion xp, got %d", o1.CompletionXP)
	}

	// Obstacle 2: explicit phases, derived fail chance (nil)
	o2 := cs.GetObstacle(102)
	if o2 == nil {
		t.Fatal("expected obstacle for room 102")
	}
	if len(o2.Phases) != 3 || !o2.Phases[1].FailCheck {
		t.Errorf("obstacle 2 phases wrong: %+v", o2.Phases)
	}
	if o2.FailChance != nil {
		t.Errorf("obstacle 2 should have nil (derived) fail_chance, got %v", *o2.FailChance)
	}
	if o2.CompletionXP != 50 {
		t.Errorf("last obstacle should carry completion_xp, got %d", o2.CompletionXP)
	}
	if o2.NextRoom != 100 {
		t.Errorf("last obstacle with no exit_dir should fall back to start_room 100, got %d", o2.NextRoom)
	}

	if cs.GetObstacle(999) != nil {
		t.Error("expected nil for unrelated room")
	}
}