aboutsummaryrefslogtreecommitdiff
path: root/internal/game/hardening_craft_menu_skill_test.go
blob: 9b4e8c788045b603fdff0c75021c480a33f42972 (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
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())
		}
	})
}