package main import ( "math/rand" "testing" ) func TestRollEncounterMoreLikelyInDangerousSystems(t *testing.T) { safe := WayfarerSystem{Government: GovCorporateState} dangerous := WayfarerSystem{Government: GovAnarchy} safeCount, dangerousCount := 0, 0 for seed := int64(0); seed < 1000; seed++ { if RollEncounter(safe, rand.New(rand.NewSource(seed))) != EncounterNone { safeCount++ } if RollEncounter(dangerous, rand.New(rand.NewSource(seed))) != EncounterNone { dangerousCount++ } } if dangerousCount <= safeCount { t.Errorf("в опасной системе встреч должно быть заметно больше: dangerous=%d safe=%d", dangerousCount, safeCount) } } func TestRollQuestOfferNoneWhenQuestActive(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) s.StartQuest(WayfarerQuestDefs[0].Key) for seed := int64(0); seed < 200; seed++ { if _, ok := RollQuestOffer(s, rand.New(rand.NewSource(seed))); ok { t.Fatalf("не должно предлагаться заданий, пока уже есть активное") } } } func TestRollQuestOfferNoneWhenAllCompleted(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) for _, q := range WayfarerQuestDefs { s.CompletedQuests[q.Key] = true } for seed := int64(0); seed < 200; seed++ { if _, ok := RollQuestOffer(s, rand.New(rand.NewSource(seed))); ok { t.Fatalf("не должно предлагаться заданий, если все уже выполнены") } } } func TestRollQuestOfferSkipsCompletedAndFailed(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) for i, q := range WayfarerQuestDefs { if i%2 == 0 { s.CompletedQuests[q.Key] = true } else { s.FailedQuests[q.Key] = true } } // оставляем ровно одно доступное задание lastKey := WayfarerQuestDefs[len(WayfarerQuestDefs)-1].Key delete(s.CompletedQuests, lastKey) delete(s.FailedQuests, lastKey) found := false for seed := int64(0); seed < 500 && !found; seed++ { if key, ok := RollQuestOffer(s, rand.New(rand.NewSource(seed))); ok { if key != lastKey { t.Fatalf("предложено завершённое/провальное задание %q вместо единственного доступного %q", key, lastKey) } found = true } } if !found { t.Fatalf("за 500 попыток ни разу не предложилось единственное доступное задание") } } func TestRollQuestOfferHappensSometimesNotAlways(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) offered, skipped := 0, 0 for seed := int64(0); seed < 500; seed++ { if _, ok := RollQuestOffer(s, rand.New(rand.NewSource(seed))); ok { offered++ } else { skipped++ } } if offered == 0 { t.Errorf("за 500 попыток ни разу не предложилось задание — вероятность должна быть больше нуля") } if skipped == 0 { t.Errorf("за 500 попыток задание предлагалось абсолютно всегда — должны быть и тихие прилёты") } } func TestGeneratePirateStatsScaleWithDanger(t *testing.T) { safe := WayfarerSystem{Government: GovCorporateState} dangerous := WayfarerSystem{Government: GovAnarchy} safeSum, dangerousSum := 0, 0 for seed := int64(0); seed < 100; seed++ { h1, _ := GeneratePirateStats(safe, rand.New(rand.NewSource(seed))) h2, _ := GeneratePirateStats(dangerous, rand.New(rand.NewSource(seed))) safeSum += h1 dangerousSum += h2 } if dangerousSum <= safeSum { t.Errorf("пираты в опасных системах должны быть в среднем крепче: dangerous=%d safe=%d", dangerousSum, safeSum) } } func TestHasIllegalCargoDetection(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) if s.HasIllegalCargo() { t.Fatalf("новый корабль не должен везти незаконный груз") } idx := commodityIndexByKey(t, "commodity.contraband") s.Cargo[idx] = 3 if !s.HasIllegalCargo() { t.Errorf("контрабанда в трюме должна была определиться как незаконный груз") } } func TestConfiscateIllegalCargoRemovesItAndReturnsValue(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) idx := commodityIndexByKey(t, "commodity.contraband") s.Cargo[idx] = 4 lost := s.ConfiscateIllegalCargo() if s.Cargo[idx] != 0 { t.Errorf("незаконный груз должен был полностью изыматься") } if lost <= 0 { t.Errorf("должна была вернуться положительная оценка изъятого, получено %v", lost) } legalIdx := commodityIndexByKey(t, "commodity.food") s.Cargo[legalIdx] = 10 s.ConfiscateIllegalCargo() if s.Cargo[legalIdx] != 10 { t.Errorf("законный груз не должен был пострадать при конфискации") } } func TestDerelictFindAddsCredits(t *testing.T) { s := NewWayfarerShip(WayfarerSystemID{}) before := s.Credits rnd := rand.New(rand.NewSource(1)) found := s.DerelictFind(rnd) if found <= 0 { t.Errorf("находка должна быть положительной, получено %v", found) } if s.Credits != before+found { t.Errorf("кредиты должны были вырасти ровно на размер находки") } } func TestHelpDistressedEventuallyTrapsAndRewards(t *testing.T) { trapSeen, rewardSeen := false, false for seed := int64(0); seed < 200 && !(trapSeen && rewardSeen); seed++ { s := NewWayfarerShip(WayfarerSystemID{}) before := s.Credits reward, wasTrap := s.HelpDistressed(rand.New(rand.NewSource(seed))) if wasTrap { trapSeen = true if s.Credits != before { t.Errorf("ловушка не должна была начислять кредиты") } } else { rewardSeen = true if reward <= 0 || s.Credits != before+reward { t.Errorf("честная помощь должна была начислить положительную награду") } } } if !trapSeen || !rewardSeen { t.Errorf("ожидались оба исхода помощи бедствующим: ловушка=%v награда=%v", trapSeen, rewardSeen) } }