go_games_collection/wayfarer_encounters.go

153 lines
5.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, shield int) {
baseHull := 15 + rnd.Intn(20)
baseLaser := 4 + rnd.Intn(6)
baseShield := rnd.Intn(20) // некоторые пираты вообще без щита — это нормально, не форсируем минимум
hull = int(float64(baseHull) * dest.DangerFactor())
laser = int(float64(baseLaser) * dest.DangerFactor())
shield = int(float64(baseShield) * dest.DangerFactor())
if hull < 5 {
hull = 5
}
if laser < 1 {
laser = 1
}
if shield < 0 {
shield = 0
}
return hull, laser, shield
}
// 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
}