package server import "math" type GameIdentifier string type RaceIdentifier string type Game struct { Id GameIdentifier Name string Schedule string // TODO: implement somehow Turn uint Races []Race Planets []Planet warState map[uint]uint } type Race struct { Id RaceIdentifier Name string Drive float64 Weapons float64 Shields float64 Cargo float64 Planets []Planet } func (r Race) FlightDistance() float64 { return r.Drive * 40 } func (r Race) VisibilityDistance() float64 { return r.Drive * 30 } type Coordinate struct { X, Y float64 } type Planet struct { Number uint Name string Position Coordinate Size float64 Production string // TODO: kinda enum Resources float64 // Сырьё Industry float64 // Промышленность Population float64 // Население Capital float64 // CAP $ - Запасы промышленности Material float64 // MAT M - Запасы сырья Colonists float64 // COL C - Количество колонистов // Параметр "L" означает количество свободных производственных единиц. } // Производственный потенциал (I) // промышленность * 0.75 + население * 0.25 func (p Planet) ProductionCapacity() float64 { return p.Industry*0.75 + p.Population*0.25 } // Производство промышленности // TODO: test on real values func (p *Planet) IncreaseIndustry() { prod := p.ProductionCapacity() / 5 industryIncrement := math.Min(prod, p.Material) p.Industry += industryIncrement if p.Industry > p.Population { p.Industry = p.Population p.Capital += p.Population - p.Industry } } // Производство материалов // TODO: test on real values func (p *Planet) IncreaseMaterial() { p.Material += p.ProductionCapacity() * p.Industry } // Автоматическое увеличение населения на каждом ходу func (p *Planet) IncreasePopulation() { p.Population *= 1.08 var extraPopulation = p.Size - p.Population if extraPopulation > 0 { p.Colonists += extraPopulation / 8 p.Population -= extraPopulation } } type Science struct { Name string Drive float64 Weapons float64 Shields float64 Cargo float64 } type ShipType struct { Name string Drive float64 // [0], [1...] Armament uint Weapons float64 // [0], [1...] Shields float64 // [0], [1...] Cargo float64 // [0], [1...] } // TODO: test on real values func (st ShipType) EmptyMass() float64 { shipMass := st.DriveMass() + st.ShieldsMass() + st.CargoMass() + st.WeaponsMass() return shipMass } func (st ShipType) DriveMass() float64 { return st.Drive } func (st ShipType) ShieldsMass() float64 { return st.Shields } func (st ShipType) CargoMass() float64 { return st.Cargo } func (st ShipType) WeaponsMass() float64 { return float64(st.Armament)*(st.Weapons/2) + st.Weapons/2 } type ShipGroup struct { Type ShipType Number uint State string // TODO: kinda enum: In_Orbit, In_Space, Transfer_State, Upgrade Load float64 // Cargo loaded - "Масса груза" Drive float64 Weapons float64 Shields float64 Cargo float64 } // Грузоподъёмность func (sg ShipGroup) CargoCapacity() float64 { return sg.Drive * (sg.Type.Cargo + (sg.Type.Cargo*sg.Type.Cargo)/20) } // "Масса перевозимого груза" func (sg ShipGroup) CarryingMass() float64 { return sg.Load / sg.Cargo } func (sg ShipGroup) FullMass() float64 { return sg.Type.EmptyMass() + sg.CarryingMass() } // "Эффективность двигателя" // равна мощности Двигателей умноженной на текущий технологический уровень блока Двигателей func (sg ShipGroup) DriveEffective() float64 { return sg.Type.Drive * sg.Drive } // TODO: test this func (sg ShipGroup) Speed() float64 { return sg.DriveEffective() * 20 / sg.FullMass() } func (sg ShipGroup) UpgradeDriveCost(drive float64) float64 { return (1 - sg.Drive/drive) * 10 * sg.Type.Drive } // TODO: test on other values func (sg ShipGroup) UpgradeWeaponsCost(weapons float64) float64 { return (1 - sg.Weapons/weapons) * 10 * sg.Type.WeaponsMass() } func (sg ShipGroup) UpgradeShieldsCost(shields float64) float64 { return (1 - sg.Shields/shields) * 10 * sg.Type.Shields } func (sg ShipGroup) UpgradeCargoCost(cargo float64) float64 { return (1 - sg.Cargo/cargo) * 10 * sg.Type.Cargo } // Мощность бомбардировки // TODO: maybe rounding must be done only for display? func (sg ShipGroup) BombingPower() float64 { // return math.Sqrt(sg.Type.Weapons * sg.Weapons) result := (math.Sqrt(sg.Type.Weapons*sg.Weapons)/10. + 1.) * sg.Type.Weapons * sg.Weapons * float64(sg.Type.Armament) * float64(sg.Number) return toFixed3(result) } type Fleet struct { ShipGroups []ShipGroup } // TODO: test this func (fl Fleet) Speed() float64 { result := math.MaxFloat64 for _, sg := range fl.ShipGroups { if sg.Speed() < result { result = sg.Speed() } } return result } func round(num float64) int { return int(num + math.Copysign(0.5, num)) } // TODO: move to more common place func toFixed(num float64, precision int) float64 { output := math.Pow(10, float64(precision)) return float64(round(num*output)) / output } func toFixed3(num float64) float64 { return toFixed(num, 3) }