package main import "math/rand" // WayfarerEncounterType — вид случайной встречи во время перелёта. type WayfarerEncounterType int const ( EncounterNone WayfarerEncounterType = iota EncounterPirate EncounterPoliceScan EncounterDistress EncounterDerelict ) // wayfarerBaseEncounterChance — базовая вероятность хоть какой-то // встречи за один прыжок при "нейтральном" (danger factor = 1) // уровне опасности системы назначения. const wayfarerBaseEncounterChance = 0.18 // RollEncounter решает, произойдёт ли что-то во время перелёта в // систему dest, и если да — что именно. func RollEncounter(dest WayfarerSystem, rnd *rand.Rand) WayfarerEncounterType { chance := wayfarerBaseEncounterChance * dest.DangerFactor() if chance > 0.9 { chance = 0.9 } if rnd.Float64() > chance { return EncounterNone } roll := rnd.Float64() switch { case roll < 0.45: return EncounterPirate case roll < 0.65: return EncounterPoliceScan case roll < 0.85: return EncounterDistress default: return EncounterDerelict } } // GeneratePirateStats создаёт статы вражеского корабля, // отмасштабированные под опасность системы dest — в более опасных // (например, анархических) системах пираты в среднем крепче и злее. func GeneratePirateStats(dest WayfarerSystem, rnd *rand.Rand) (hull, laser int) { baseHull := 15 + rnd.Intn(20) baseLaser := 4 + rnd.Intn(6) hull = int(float64(baseHull) * dest.DangerFactor()) laser = int(float64(baseLaser) * dest.DangerFactor()) if hull < 5 { hull = 5 } if laser < 1 { laser = 1 } return hull, laser } // HasIllegalCargo проверяет, везёт ли корабль хоть что-то из // незаконных товаров (WayfarerCommodities[i].Illegal). func (s *WayfarerShip) HasIllegalCargo() bool { for i, c := range WayfarerCommodities { if c.Illegal && s.Cargo[i] > 0 { return true } } return false } // ConfiscateIllegalCargo изымает весь незаконный груз и возвращает // его условную стоимость (для отображения игроку, что он потерял). func (s *WayfarerShip) ConfiscateIllegalCargo() float64 { lost := 0.0 for i, c := range WayfarerCommodities { if c.Illegal && s.Cargo[i] > 0 { lost += float64(s.Cargo[i]) * c.BasePrice s.Cargo[i] = 0 } } return lost } // wayfarerDerelictMin/Max — диапазон случайной находки на обломках. const ( wayfarerDerelictMin = 50.0 wayfarerDerelictMax = 250.0 ) // DerelictFind начисляет игроку случайную находку с обломков // корабля и возвращает её размер. func (s *WayfarerShip) DerelictFind(rnd *rand.Rand) float64 { found := wayfarerDerelictMin + rnd.Float64()*(wayfarerDerelictMax-wayfarerDerelictMin) s.Credits += found return found } // wayfarerQuestOfferChance — с такой вероятностью прибытие в // систему (если сейчас нет активного задания и остались // невыполненные/непровальные квесты) заканчивается предложением // одного из них — вместо свободного выбора квеста из списка когда // угодно, как раньше. const wayfarerQuestOfferChance = 0.25 // RollQuestOffer решает, предлагается ли игроку квест по прибытии в // систему. Возвращает (ключ квеста, true), если да. func RollQuestOffer(ship *WayfarerShip, rnd *rand.Rand) (string, bool) { if ship.ActiveQuest != nil { return "", false } var candidates []string for _, q := range WayfarerQuestDefs { if !ship.CompletedQuests[q.Key] && !ship.FailedQuests[q.Key] { candidates = append(candidates, q.Key) } } if len(candidates) == 0 { return "", false } if rnd.Float64() > wayfarerQuestOfferChance { return "", false } return candidates[rnd.Intn(len(candidates))], true } // wayfarerDistressTrapChance — с такой вероятностью сигнал бедствия // на самом деле окажется засадой (тогда вызывающий код должен // начать бой) вместо честной просьбы о помощи. const wayfarerDistressTrapChance = 0.25 const ( wayfarerDistressRewardMin = 100.0 wayfarerDistressRewardMax = 400.0 ) // HelpDistressed разрешает решение "откликнуться на сигнал // бедствия": либо это оказывается ловушка (wasTrap == true — бой // должен запустить вызывающий код отдельно, начисление тут не // происходит), либо честная награда за помощь. func (s *WayfarerShip) HelpDistressed(rnd *rand.Rand) (reward float64, wasTrap bool) { if rnd.Float64() < wayfarerDistressTrapChance { return 0, true } reward = wayfarerDistressRewardMin + rnd.Float64()*(wayfarerDistressRewardMax-wayfarerDistressRewardMin) s.Credits += reward return reward, false }