package main import ( "math/rand" "testing" ) func TestApplyDamageAbsorbedByShieldFirst(t *testing.T) { shield, hull := 10, 50 applyDamage(&shield, &hull, 6) if shield != 4 || hull != 50 { t.Errorf("урон должен был полностью уйти в щит: shield=%d hull=%d", shield, hull) } } func TestApplyDamageOverflowsToHull(t *testing.T) { shield, hull := 5, 50 applyDamage(&shield, &hull, 12) if shield != 0 || hull != 43 { t.Errorf("избыток урона должен был перейти в корпус: shield=%d hull=%d", shield, hull) } } func TestApplyDamageHullNeverNegative(t *testing.T) { shield, hull := 0, 5 applyDamage(&shield, &hull, 100) if hull != 0 { t.Errorf("корпус не должен уходить в минус, получено %d", hull) } } func TestAttackCanDefeatEnemy(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 5, 5, 100, 100, 50, 50, 100, true) c.Attack(rnd) if c.Outcome != CombatWon { t.Fatalf("огромный урон игрока должен был сразу уничтожить слабого врага, получен исход %v (EnemyHull=%d)", c.Outcome, c.EnemyHull) } if c.LastEnemyDamage != 0 { t.Errorf("уничтоженный враг не должен успевать ответным ударом") } } func TestAttackEnemySurvivesAndRetaliates(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 1000, 5, 100, 100, 50, 50, 5, true) beforeHull := c.PlayerHull + c.PlayerShield c.Attack(rnd) if c.Outcome != CombatOngoing { t.Fatalf("бой должен был продолжиться, получен исход %v", c.Outcome) } afterHull := c.PlayerHull + c.PlayerShield if afterHull >= beforeHull { t.Errorf("выживший враг должен был нанести ответный урон") } } func TestAttackCanDefeatPlayer(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 1000, 500, 1, 100, 0, 50, 1, true) c.Attack(rnd) if c.Outcome != CombatLost { t.Fatalf("слабый игрок против огромного урона должен был проиграть, получен исход %v (PlayerHull=%d)", c.Outcome, c.PlayerHull) } } func TestFleeEventuallySucceedsOrFails(t *testing.T) { successSeen, failSeen := false, false for seed := int64(0); seed < 200 && !(successSeen && failSeen); seed++ { rnd := rand.New(rand.NewSource(seed)) c := NewWayfarerCombat("enemy.pirate", 1000, 5, 1000, 1000, 100, 100, 5, true) if c.Flee(rnd) { successSeen = true } else { failSeen = true } } if !successSeen || !failSeen { t.Errorf("ожидались оба исхода бегства среди множества попыток: успех=%v неудача=%v", successSeen, failSeen) } } func TestFailedFleeStillTakesDamage(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 1000, 20, 1000, 1000, 0, 0, 5, true) for i := 0; i < 50 && c.Outcome == CombatOngoing; i++ { fled := c.Flee(rnd) if !fled { if c.LastEnemyDamage <= 0 { t.Errorf("неудачное бегство должно было нанести урон игроку") } return } } } func TestNegotiateOnlyAvailableWhenNegotiable(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 1000, 5, 1000, 1000, 100, 100, 5, false) before := *c ok := c.Negotiate(rnd) if ok { t.Errorf("переговоры не должны быть доступны, если Negotiable=false") } if c.Round != before.Round { t.Errorf("недоступная попытка переговоров не должна тратить раунд") } } func TestNegotiateEventuallySucceedsOrFails(t *testing.T) { successSeen, failSeen := false, false for seed := int64(0); seed < 200 && !(successSeen && failSeen); seed++ { rnd := rand.New(rand.NewSource(seed)) c := NewWayfarerCombat("enemy.pirate", 1000, 5, 1000, 1000, 100, 100, 5, true) if c.Negotiate(rnd) { successSeen = true } else { failSeen = true } } if !successSeen || !failSeen { t.Errorf("ожидались оба исхода переговоров среди множества попыток: успех=%v неудача=%v", successSeen, failSeen) } } func TestActionsAfterCombatOverAreNoOps(t *testing.T) { rnd := rand.New(rand.NewSource(1)) c := NewWayfarerCombat("enemy.pirate", 5, 5, 100, 100, 50, 50, 100, true) c.Attack(rnd) if c.Outcome != CombatWon { t.Fatalf("бой должен был завершиться победой для настройки теста") } roundAfter := c.Round c.Attack(rnd) c.Flee(rnd) c.Negotiate(rnd) if c.Round != roundAfter { t.Errorf("действия после завершения боя не должны ничего менять") } }