2026-08-16 00:01:20 +08:00
|
|
|
|
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}
|
2026-08-16 00:01:20 +08:00
|
|
|
|
b := m.Spawn(KindAnimal, 1.5, 63, 0.5)
|
2026-09-19 14:21:08 +08:00
|
|
|
|
b.Data = &Animal{Species: 1}
|
2026-08-16 00:01:20 +08:00
|
|
|
|
|
|
|
|
|
|
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 {
|
2026-08-16 00:01:20 +08:00
|
|
|
|
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}
|
2026-08-16 00:01:20 +08:00
|
|
|
|
b := m.Spawn(KindAnimal, 1.5, 63, 0.5)
|
2026-09-19 14:21:08 +08:00
|
|
|
|
b.Data = &Animal{Species: 0}
|
2026-08-16 00:01:20 +08:00
|
|
|
|
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("异种不应繁殖")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-16 00:01:20 +08:00
|
|
|
|
// 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("羊不能挤奶")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-16 00:01:20 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|