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
|
package game
// Regression: the multi-match production menu (craft <name>/mix/construct)
// must pass the real lowercase recipe type as PendingSkill. It previously
// passed the capitalised display label ("Crafting"), which
// handleProductChoice looks up with player.SkillName — a map miss that
// resolves to level 1, so every recipe above level 1 was refused even for a
// level-50 crafter.
import (
"testing"
"thehouseoficarus/internal/net"
"thehouseoficarus/internal/player"
)
const craftMenuIngotYAML = `id: test_ingot
name: test ingot
stackable: true
value: 1
`
const craftMenuSwordYAML = `id: test_iron_sword
name: iron sword
stackable: false
value: 5
craft:
- type: crafting
ingredients:
- items:
- test_ingot
quantity: 1
level: 1
output_qty: 1
`
const craftMenuPlateYAML = `id: test_iron_plate
name: iron plate
stackable: false
value: 50
craft:
- type: crafting
ingredients:
- items:
- test_ingot
quantity: 1
level: 40
output_qty: 1
`
func TestCraftMenuResolvesRealSkillForMultiMatch(t *testing.T) {
dir := t.TempDir()
seedWorld(t, dir)
writeDataFile(t, dir, "items", "test_ingot.yaml", craftMenuIngotYAML)
writeDataFile(t, dir, "items", "test_iron_sword.yaml", craftMenuSwordYAML)
writeDataFile(t, dir, "items", "test_iron_plate.yaml", craftMenuPlateYAML)
g := newHardeningGame(t, dir)
g.RunOnOwner(func() {
p := player.New("alice")
p.RoomID = 1
p.Skills[player.Crafting] = player.XPForLevel(50)
p.SetInvSlot(0, &player.InventorySlot{ItemID: "test_ingot", Quantity: 1})
conn := newChanConn()
sess := &net.Session{Conn: conn, Player: p}
sess.SetState(net.StateGame)
// "iron" matches both products, forcing the multi-match menu path.
g.doCraft(sess, "iron")
if sess.PendingSkill != "crafting" {
t.Fatalf("PendingSkill = %q, want %q (a display label is not a skill)",
sess.PendingSkill, "crafting")
}
if len(sess.PendingMenu) != 2 {
t.Fatalf("menu entries = %d, want 2 (iron sword, iron plate)", len(sess.PendingMenu))
}
// Choice 2 is iron plate (level 40, the only row above level 1).
g.handleProductChoice(sess, "2")
if p.Action == nil {
t.Fatalf("level-50 crafter could not start the level-40 recipe; output=%q", conn.Bytes())
}
if p.Action.TargetID != "test_iron_plate" {
t.Fatalf("started recipe %q, want test_iron_plate; output=%q", p.Action.TargetID, conn.Bytes())
}
})
}
|