Files
ngzz-mc/internal/entity/breeding_test.go

124 lines
3.2 KiB
Go
Raw Permalink Normal View History

package entity
import (
"path/filepath"
"testing"
)
// TestBreed 动物繁殖:成年+冷却完成 → 幼崽;冷却中拒绝;上限拒绝(动物体系.md §3)。
func TestBreed(t *testing.T) {
m := NewManager()
w := flatWorld{}
a := m.Spawn(KindAnimal, 0.5, 63, 0.5)
2026-09-19 14:21:08 +08:00
a.Data = &Animal{Species: 1}
b := m.Spawn(KindAnimal, 1.5, 63, 0.5)
2026-09-19 14:21:08 +08:00
b.Data = &Animal{Species: 1}
baby := m.Breed(a, b, w)
if baby == nil {
t.Fatal("应繁殖出幼崽")
}
2026-09-19 14:21:08 +08:00
if d, ok := baby.Data.(*Animal); !ok || d.GrowthTicks == 0 || d.Species != 1 {
t.Fatalf("幼崽数据异常: %+v", baby.Data)
}
// 冷却中:拒绝
if m.Breed(a, b, w) != nil {
t.Fatal("冷却中不应繁殖")
}
// 冷却恢复后可再次繁殖
ad := a.Data.(*Animal)
ad.BreedCooldown = 0
bd := b.Data.(*Animal)
bd.BreedCooldown = 0
if m.Breed(a, b, w) == nil {
t.Fatal("冷却结束后应能繁殖")
}
}
// TestBreedCap 每区块上限(动物体系.md §7 防无限繁殖)。
func TestBreedCap(t *testing.T) {
m := NewManager()
w := flatWorld{}
a := m.Spawn(KindAnimal, 0.5, 63, 0.5)
2026-09-19 14:21:08 +08:00
a.Data = &Animal{Species: 0}
b := m.Spawn(KindAnimal, 1.5, 63, 0.5)
2026-09-19 14:21:08 +08:00
b.Data = &Animal{Species: 0}
for i := 0; i < 12; i++ {
m.Spawn(KindAnimal, 2.5, 63, 2.5+float64(i))
}
if m.Breed(a, b, w) != nil {
t.Fatal("超上限不应繁殖")
}
}
2026-09-19 14:21:08 +08:00
func TestAnimalSpeciesFallback(t *testing.T) {
e := &Entity{ID: 6, Kind: KindAnimal}
if AnimalSpecies(e) != 2 {
t.Fatalf("无 Data 应回退 ID%%4=2,实际 %d", AnimalSpecies(e))
}
e.Data = &Animal{Species: 3}
if AnimalSpecies(e) != 3 {
t.Fatalf("应读 Species 字段,实际 %d", AnimalSpecies(e))
}
}
func TestBreedCrossSpecies(t *testing.T) {
m := NewManager()
w := flatWorld{}
a := m.Spawn(KindAnimal, 0.5, 63, 0.5)
a.Data = &Animal{Species: 0}
b := m.Spawn(KindAnimal, 1.5, 63, 0.5)
b.Data = &Animal{Species: 2}
if m.Breed(a, b, w) != nil {
t.Fatal("异种不应繁殖")
}
}
// TestLoadTrades 交易表解析与职业查询(村民系统.md §7)。
2026-09-19 14:21:08 +08:00
func TestFeedAndLove(t *testing.T) {
e := &Entity{Kind: KindAnimal, Data: &Animal{Species: 0}}
if !Feed(e) {
t.Fatal("成年牛应能喂食")
}
if e.Data.(*Animal).LoveTicks <= 0 {
t.Fatal("喂食应进入 love")
}
baby := &Entity{Kind: KindAnimal, Data: &Animal{Species: 0, GrowthTicks: 10}}
if Feed(baby) {
t.Fatal("幼崽不应进入繁殖")
}
}
func TestShearAndMilk(t *testing.T) {
sheep := &Entity{Kind: KindAnimal, Data: &Animal{Species: 2}}
if !ShearSheep(sheep, 2) {
t.Fatal("羊应能剪毛")
}
if !sheep.Data.(*Animal).Sheared {
t.Fatal("剪后应标记 Sheared")
}
if ShearSheep(sheep, 1) {
t.Fatal("已剪不应再剪")
}
cow := &Entity{Kind: KindAnimal, Data: &Animal{Species: 0}}
if !MilkCow(cow) {
t.Fatal("牛应能挤奶")
}
if MilkCow(sheep) {
t.Fatal("羊不能挤奶")
}
}
func TestLoadTrades(t *testing.T) {
tbl, err := LoadTrades(filepath.Join("..", "..", "assets", "config", "villager_trades.json"))
if err != nil {
t.Fatalf("加载交易表失败: %v", err)
}
if offers := tbl.OffersFor(0); len(offers) != 2 {
t.Fatalf("农民交易期望 2 条,实际 %d", len(offers))
}
if offers := tbl.OffersFor(2); len(offers) != 2 || offers[0].Buy != "coal" {
t.Fatalf("铁匠交易异常: %+v", offers)
}
}