feat: add skill tree system with 2 branches per class
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
148
entity/skill_tree_test.go
Normal file
148
entity/skill_tree_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package entity
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetBranches(t *testing.T) {
|
||||
classes := []Class{ClassWarrior, ClassMage, ClassHealer, ClassRogue}
|
||||
for _, c := range classes {
|
||||
branches := GetBranches(c)
|
||||
if len(branches) != 2 {
|
||||
t.Errorf("expected 2 branches for %s, got %d", c, len(branches))
|
||||
}
|
||||
for i, b := range branches {
|
||||
if b.Name == "" {
|
||||
t.Errorf("branch %d for %s has empty name", i, c)
|
||||
}
|
||||
for j, node := range b.Nodes {
|
||||
if node.Name == "" {
|
||||
t.Errorf("node %d in branch %d for %s has empty name", j, i, c)
|
||||
}
|
||||
if node.Value <= 0 {
|
||||
t.Errorf("node %d in branch %d for %s has non-positive value %d", j, i, c, node.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateSkillPoint(t *testing.T) {
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 1
|
||||
|
||||
err := ps.Allocate(0, ClassWarrior)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error on first allocation: %v", err)
|
||||
}
|
||||
if ps.BranchIndex != 0 {
|
||||
t.Errorf("expected BranchIndex 0, got %d", ps.BranchIndex)
|
||||
}
|
||||
if ps.Allocated != 1 {
|
||||
t.Errorf("expected Allocated 1, got %d", ps.Allocated)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCannotSwitchBranch(t *testing.T) {
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 2
|
||||
|
||||
err := ps.Allocate(0, ClassWarrior)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = ps.Allocate(1, ClassWarrior)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when switching branch, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCannotAllocateWithoutPoints(t *testing.T) {
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 0
|
||||
|
||||
err := ps.Allocate(0, ClassWarrior)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when no points available, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFullyAllocated(t *testing.T) {
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 4
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
err := ps.Allocate(0, ClassWarrior)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error on allocation %d: %v", i+1, err)
|
||||
}
|
||||
}
|
||||
|
||||
err := ps.Allocate(0, ClassWarrior)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when fully allocated, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkillBonuses(t *testing.T) {
|
||||
// Warrior Tank branch: DEF+3, MaxHP+20, DEF+5
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 3
|
||||
for i := 0; i < 3; i++ {
|
||||
if err := ps.Allocate(0, ClassWarrior); err != nil {
|
||||
t.Fatalf("allocate error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if got := ps.GetDEFBonus(ClassWarrior); got != 8 {
|
||||
t.Errorf("expected DEF bonus 8 (3+5), got %d", got)
|
||||
}
|
||||
if got := ps.GetMaxHPBonus(ClassWarrior); got != 20 {
|
||||
t.Errorf("expected MaxHP bonus 20, got %d", got)
|
||||
}
|
||||
if got := ps.GetATKBonus(ClassWarrior); got != 0 {
|
||||
t.Errorf("expected ATK bonus 0 for Tank, got %d", got)
|
||||
}
|
||||
|
||||
// Warrior Berserker branch: ATK+4, SkillPower+20, ATK+6
|
||||
ps2 := NewPlayerSkills()
|
||||
ps2.Points = 3
|
||||
for i := 0; i < 3; i++ {
|
||||
if err := ps2.Allocate(1, ClassWarrior); err != nil {
|
||||
t.Fatalf("allocate error: %v", err)
|
||||
}
|
||||
}
|
||||
if got := ps2.GetATKBonus(ClassWarrior); got != 10 {
|
||||
t.Errorf("expected ATK bonus 10 (4+6), got %d", got)
|
||||
}
|
||||
if got := ps2.GetSkillPower(ClassWarrior); got != 20 {
|
||||
t.Errorf("expected SkillPower bonus 20, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNilPlayerSkillsBonuses(t *testing.T) {
|
||||
var ps *PlayerSkills
|
||||
if got := ps.GetATKBonus(ClassWarrior); got != 0 {
|
||||
t.Errorf("expected 0 ATK bonus from nil skills, got %d", got)
|
||||
}
|
||||
if got := ps.GetDEFBonus(ClassWarrior); got != 0 {
|
||||
t.Errorf("expected 0 DEF bonus from nil skills, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPartialAllocation(t *testing.T) {
|
||||
// Rogue Assassin: ATK+5, CritChance+15, ATK+8
|
||||
// Allocate only 2 points: should get ATK+5 and CritChance+15
|
||||
ps := NewPlayerSkills()
|
||||
ps.Points = 2
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := ps.Allocate(0, ClassRogue); err != nil {
|
||||
t.Fatalf("allocate error: %v", err)
|
||||
}
|
||||
}
|
||||
if got := ps.GetATKBonus(ClassRogue); got != 5 {
|
||||
t.Errorf("expected ATK bonus 5, got %d", got)
|
||||
}
|
||||
if got := ps.GetCritChance(ClassRogue); got != 15 {
|
||||
t.Errorf("expected CritChance bonus 15, got %d", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user