Files
Catacombs/entity/player_test.go
tolelom f28160d4da feat: localize all UI text to Korean
Translate all user-facing strings to Korean across 25 files:
- UI screens: title, nickname, lobby, class select, waiting, game,
  shop, result, help, leaderboard, achievements, codex, stats
- Game logic: combat logs, events, achievements, mutations, emotes,
  lobby errors, session messages
- Keep English for: class names, monster names, item names, relic names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:47:27 +09:00

242 lines
6.5 KiB
Go

package entity
import (
"strings"
"testing"
)
func TestNewPlayer(t *testing.T) {
p := NewPlayer("testuser", ClassWarrior)
if p.HP != 120 || p.MaxHP != 120 {
t.Errorf("Warrior HP: got %d, want 120", p.HP)
}
if p.ATK != 12 {
t.Errorf("Warrior ATK: got %d, want 12", p.ATK)
}
if p.DEF != 8 {
t.Errorf("Warrior DEF: got %d, want 8", p.DEF)
}
if p.Gold != 0 {
t.Errorf("Initial gold: got %d, want 0", p.Gold)
}
}
func TestAllClasses(t *testing.T) {
tests := []struct {
class Class
hp, atk, def int
}{
{ClassWarrior, 120, 12, 8},
{ClassMage, 70, 20, 3},
{ClassHealer, 90, 8, 5},
{ClassRogue, 85, 15, 4},
}
for _, tt := range tests {
p := NewPlayer("test", tt.class)
if p.HP != tt.hp || p.ATK != tt.atk || p.DEF != tt.def {
t.Errorf("Class %v: got HP=%d ATK=%d DEF=%d, want HP=%d ATK=%d DEF=%d",
tt.class, p.HP, p.ATK, p.DEF, tt.hp, tt.atk, tt.def)
}
}
}
func TestRelicEffects(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
p.Relics = append(p.Relics, Relic{Name: "Power Amulet", Effect: RelicATKBoost, Value: 3})
if p.EffectiveATK() != 15 {
t.Errorf("ATK with relic: got %d, want 15", p.EffectiveATK())
}
p.Relics = append(p.Relics, Relic{Name: "Iron Ward", Effect: RelicDEFBoost, Value: 2})
if p.EffectiveDEF() != 10 {
t.Errorf("DEF with relic: got %d, want 10", p.EffectiveDEF())
}
}
func TestPlayerTakeDamage(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
p.TakeDamage(30)
if p.HP != 90 {
t.Errorf("HP after 30 dmg: got %d, want 90", p.HP)
}
p.TakeDamage(200)
if p.HP != 0 {
t.Errorf("HP should not go below 0: got %d", p.HP)
}
if !p.IsDead() {
t.Error("Player should be dead")
}
}
func TestIsOut(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
if p.IsOut() {
t.Error("alive player should not be out")
}
p.Dead = true
if !p.IsOut() {
t.Error("dead player should be out")
}
p.Dead = false
p.Fled = true
if !p.IsOut() {
t.Error("fled player should be out")
}
}
func TestRevive(t *testing.T) {
p := NewPlayer("test", ClassWarrior) // 120 MaxHP
p.TakeDamage(200)
if !p.IsDead() {
t.Error("should be dead")
}
p.Revive(0.30)
if p.IsDead() {
t.Error("should be alive after revive")
}
if p.HP != 36 { // 120 * 0.30
t.Errorf("HP should be 36, got %d", p.HP)
}
}
func TestHealCap(t *testing.T) {
p := NewPlayer("test", ClassWarrior) // 120 HP
p.HP = 100
p.Heal(50) // should cap at 120
if p.HP != 120 {
t.Errorf("HP should cap at 120, got %d", p.HP)
}
}
func TestEffectiveATKWithItems(t *testing.T) {
p := NewPlayer("test", ClassWarrior) // base ATK 12
p.Inventory = append(p.Inventory, Item{Name: "Sword", Type: ItemWeapon, Bonus: 5})
p.Inventory = append(p.Inventory, Item{Name: "Sword2", Type: ItemWeapon, Bonus: 3})
if p.EffectiveATK() != 20 { // 12 + 5 + 3
t.Errorf("ATK should be 20, got %d", p.EffectiveATK())
}
}
func TestEffectiveDEFWithItems(t *testing.T) {
p := NewPlayer("test", ClassWarrior) // base DEF 8
p.Inventory = append(p.Inventory, Item{Name: "Shield", Type: ItemArmor, Bonus: 4})
if p.EffectiveDEF() != 12 { // 8 + 4
t.Errorf("DEF should be 12, got %d", p.EffectiveDEF())
}
}
func TestStatusEffectPoison(t *testing.T) {
p := NewPlayer("test", ClassWarrior) // 120 HP
p.AddEffect(ActiveEffect{Type: StatusPoison, Duration: 2, Value: 10})
if !p.HasEffect(StatusPoison) {
t.Error("should have poison")
}
msgs := p.TickEffects()
if len(msgs) != 1 {
t.Errorf("expected 1 message, got %d", len(msgs))
}
if p.HP != 110 {
t.Errorf("HP should be 110 after poison tick, got %d", p.HP)
}
// Poison can't kill
p.HP = 5
p.TickEffects() // duration expires after this tick
if p.HP != 1 {
t.Errorf("poison should leave at 1 HP, got %d", p.HP)
}
if p.IsDead() {
t.Error("poison should not kill")
}
if p.HasEffect(StatusPoison) {
t.Error("poison should have expired")
}
}
func TestStatusEffectBurn(t *testing.T) {
p := NewPlayer("test", ClassMage) // 70 HP
p.AddEffect(ActiveEffect{Type: StatusBurn, Duration: 1, Value: 100})
p.TickEffects()
if !p.IsDead() {
t.Error("burn should be able to kill")
}
}
func TestRelicPoisonImmunity(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
p.Relics = append(p.Relics, Relic{Name: "Antidote", Effect: RelicPoisonImmunity})
p.AddEffect(ActiveEffect{Type: StatusPoison, Duration: 3, Value: 10})
if p.HasEffect(StatusPoison) {
t.Error("should be immune to poison")
}
}
func TestRelicBurnResist(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
p.Relics = append(p.Relics, Relic{Name: "Flame Guard", Effect: RelicBurnResist})
p.AddEffect(ActiveEffect{Type: StatusBurn, Duration: 2, Value: 10})
// Burn value should be halved to 5
if len(p.Effects) == 0 {
t.Fatal("should have burn effect (resisted, not immune)")
}
if p.Effects[0].Value != 5 {
t.Errorf("burn value should be halved to 5, got %d", p.Effects[0].Value)
}
}
func TestEffectOverwrite(t *testing.T) {
p := NewPlayer("test", ClassWarrior)
p.AddEffect(ActiveEffect{Type: StatusPoison, Duration: 1, Value: 5})
p.AddEffect(ActiveEffect{Type: StatusPoison, Duration: 3, Value: 10}) // should overwrite
if len(p.Effects) != 1 {
t.Errorf("should have 1 effect, got %d", len(p.Effects))
}
if p.Effects[0].Duration != 3 || p.Effects[0].Value != 10 {
t.Error("should have overwritten with new values")
}
}
func TestBleedEffect(t *testing.T) {
p := NewPlayer("Test", ClassWarrior)
startHP := p.HP
p.AddEffect(ActiveEffect{Type: StatusBleed, Duration: 3, Value: 2})
msgs := p.TickEffects()
if len(msgs) == 0 || !strings.Contains(msgs[0], "출혈") {
t.Error("expected bleed damage message")
}
if p.HP != startHP-2 {
t.Errorf("expected HP %d, got %d", startHP-2, p.HP)
}
// After tick, remaining bleed should have value 3 (increased by 1)
if len(p.Effects) == 0 || p.Effects[0].Value != 3 {
t.Error("expected bleed value to increase to 3")
}
}
func TestCurseReducesHealing(t *testing.T) {
p := NewPlayer("Test", ClassHealer)
p.HP = 50
p.AddEffect(ActiveEffect{Type: StatusCurse, Duration: 3, Value: 50})
p.Heal(100)
// Curse reduces by 50%, so heal 50 from HP 50 -> 100, capped at MaxHP
expected := p.MaxHP
if 50+50 < p.MaxHP {
expected = 50 + 50
}
if p.HP != expected {
t.Errorf("expected HP %d, got %d", expected, p.HP)
}
}
func TestFreezeTickMessage(t *testing.T) {
p := NewPlayer("Test", ClassMage)
p.AddEffect(ActiveEffect{Type: StatusFreeze, Duration: 1, Value: 0})
msgs := p.TickEffects()
if len(msgs) == 0 || !strings.Contains(msgs[0], "동결") {
t.Error("expected freeze message")
}
// Freeze duration 1 -> removed after tick
if len(p.Effects) != 0 {
t.Error("expected freeze to be removed after 1 tick")
}
}