code cleanup
This commit is contained in:
@@ -2,13 +2,11 @@ package game
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/iliadenisov/galaxy/pkg/generator"
|
"github.com/iliadenisov/galaxy/pkg/generator"
|
||||||
"github.com/iliadenisov/galaxy/pkg/model/game"
|
"github.com/iliadenisov/galaxy/pkg/model/game"
|
||||||
"github.com/iliadenisov/galaxy/pkg/number"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Repo interface {
|
type Repo interface {
|
||||||
@@ -126,132 +124,3 @@ func newPlanet(num uint, name string, owner uuid.UUID, x, y, size, pop, ind, res
|
|||||||
Production: prod,
|
Production: prod,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Race) FlightDistance() float64 {
|
|
||||||
return r.Drive * 40
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Race) VisibilityDistance() float64 {
|
|
||||||
return r.Drive * 30
|
|
||||||
}
|
|
||||||
|
|
||||||
// Производственный потенциал (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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Грузоподъёмность
|
|
||||||
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 number.Fixed3(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
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[RaceIdentifier]RaceIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
type Race struct {
|
|
||||||
Id RaceIdentifier
|
|
||||||
Name string
|
|
||||||
Drive float64
|
|
||||||
Weapons float64
|
|
||||||
Shields float64
|
|
||||||
Cargo float64
|
|
||||||
}
|
|
||||||
|
|
||||||
type PlanetProduction string
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProductionMaterial PlanetProduction = "MAT"
|
|
||||||
ProductionCapital PlanetProduction = "CAP"
|
|
||||||
ProductionDrive PlanetProduction = "DRIVE"
|
|
||||||
ProductionWeapons PlanetProduction = "WEAPONS"
|
|
||||||
ProductionShields PlanetProduction = "SHIELDS"
|
|
||||||
ProductionCargo PlanetProduction = "CARGO"
|
|
||||||
|
|
||||||
ProductionScience PlanetProduction = "SCIENCE"
|
|
||||||
ProductionShip PlanetProduction = "SHIP"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProductionType struct {
|
|
||||||
Production PlanetProduction
|
|
||||||
SubjectName string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Planet struct {
|
|
||||||
Number uint
|
|
||||||
Name string
|
|
||||||
Position Coordinate
|
|
||||||
Size float64
|
|
||||||
|
|
||||||
Owner RaceIdentifier
|
|
||||||
Production ProductionType
|
|
||||||
Resources float64 // Сырьё
|
|
||||||
Industry float64 // Промышленность
|
|
||||||
Population float64 // Население
|
|
||||||
|
|
||||||
Capital float64 // CAP $ - Запасы промышленности
|
|
||||||
Material float64 // MAT M - Запасы сырья
|
|
||||||
Colonists float64 // COL C - Количество колонистов
|
|
||||||
// Параметр "L" означает количество свободных производственных единиц.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Planet) setOwner(id RaceIdentifier) {
|
|
||||||
p.Owner = id
|
|
||||||
}
|
|
||||||
|
|
||||||
type Coordinate struct {
|
|
||||||
X, Y float64
|
|
||||||
}
|
|
||||||
|
|
||||||
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...]
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
type Fleet struct {
|
|
||||||
ShipGroups []ShipGroup
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package game
|
|
||||||
|
|
||||||
func CreateGame(id GameIdentifier, name string, races []Race, planets []Planet) Game {
|
|
||||||
return Game{
|
|
||||||
Id: id,
|
|
||||||
Name: name,
|
|
||||||
Turn: 0,
|
|
||||||
Races: races,
|
|
||||||
Planets: planets,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateRace(id RaceIdentifier, name string) Race {
|
|
||||||
return Race{
|
|
||||||
Id: id,
|
|
||||||
Name: name,
|
|
||||||
Drive: 1.0,
|
|
||||||
Weapons: 1.0,
|
|
||||||
Shields: 1.0,
|
|
||||||
Cargo: 1.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreatePlanet(number uint, name string, position Coordinate, size float64, res float64, pop float64) Planet {
|
|
||||||
return Planet{
|
|
||||||
Number: number,
|
|
||||||
Name: name,
|
|
||||||
Position: position,
|
|
||||||
Size: size,
|
|
||||||
Production: ProductionType{ProductionDrive, ""},
|
|
||||||
Resources: res,
|
|
||||||
Population: pop,
|
|
||||||
|
|
||||||
Industry: 0,
|
|
||||||
Capital: 0,
|
|
||||||
Material: 0,
|
|
||||||
Colonists: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+7
-20
@@ -3,7 +3,8 @@ package game_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/iliadenisov/galaxy/pkg/game"
|
"github.com/iliadenisov/galaxy/pkg/model/game"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_ShipType(t *testing.T) {
|
func Test_ShipType(t *testing.T) {
|
||||||
@@ -14,10 +15,7 @@ func Test_ShipType(t *testing.T) {
|
|||||||
Shields: 4,
|
Shields: 4,
|
||||||
Cargo: 0,
|
Cargo: 0,
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, Gunship.EmptyMass(), 11.)
|
||||||
if Gunship.EmptyMass() != 11. {
|
|
||||||
t.Errorf("Cruiser mass expected %.3f but %.3f given", 11., Gunship.EmptyMass())
|
|
||||||
}
|
|
||||||
|
|
||||||
Cruiser := game.ShipType{
|
Cruiser := game.ShipType{
|
||||||
Drive: 15,
|
Drive: 15,
|
||||||
@@ -26,10 +24,7 @@ func Test_ShipType(t *testing.T) {
|
|||||||
Shields: 15,
|
Shields: 15,
|
||||||
Cargo: 0,
|
Cargo: 0,
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, Cruiser.EmptyMass(), 45.)
|
||||||
if Cruiser.EmptyMass() != 45. {
|
|
||||||
t.Errorf("Cruiser mass expected %.3f but %.3f given", 45., Cruiser.EmptyMass())
|
|
||||||
}
|
|
||||||
|
|
||||||
sg := game.ShipGroup{
|
sg := game.ShipGroup{
|
||||||
Type: Cruiser,
|
Type: Cruiser,
|
||||||
@@ -40,15 +35,11 @@ func Test_ShipType(t *testing.T) {
|
|||||||
Shields: 1.0,
|
Shields: 1.0,
|
||||||
Cargo: 1.0,
|
Cargo: 1.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeCost := sg.UpgradeDriveCost(2.0) +
|
upgradeCost := sg.UpgradeDriveCost(2.0) +
|
||||||
sg.UpgradeWeaponsCost(2.0) +
|
sg.UpgradeWeaponsCost(2.0) +
|
||||||
sg.UpgradeShieldsCost(2.0) +
|
sg.UpgradeShieldsCost(2.0) +
|
||||||
sg.UpgradeCargoCost(2.0)
|
sg.UpgradeCargoCost(2.0)
|
||||||
|
assert.Equal(t, upgradeCost, 225.)
|
||||||
if upgradeCost != 225. {
|
|
||||||
t.Errorf("Cruiser upgrade cost expected %.3f but %.3f given", 225., upgradeCost)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_CargoCapacity(t *testing.T) {
|
func Test_CargoCapacity(t *testing.T) {
|
||||||
@@ -69,9 +60,7 @@ func Test_CargoCapacity(t *testing.T) {
|
|||||||
Shields: 1.0,
|
Shields: 1.0,
|
||||||
Cargo: 1.0,
|
Cargo: 1.0,
|
||||||
}
|
}
|
||||||
if sg.CargoCapacity() != expectCapacity {
|
assert.Equal(t, expectCapacity, sg.CargoCapacity())
|
||||||
t.Errorf("expected CargoCapacity=%.3f but %.3f given", expectCapacity, sg.CargoCapacity())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
test(1, 1.05)
|
test(1, 1.05)
|
||||||
test(5, 6.25)
|
test(5, 6.25)
|
||||||
@@ -99,7 +88,5 @@ func Test_BombingPower(t *testing.T) {
|
|||||||
}
|
}
|
||||||
expectedBombingPower := 139.295
|
expectedBombingPower := 139.295
|
||||||
result := sg.BombingPower()
|
result := sg.BombingPower()
|
||||||
if result != expectedBombingPower {
|
assert.Equal(t, expectedBombingPower, result)
|
||||||
t.Errorf("expected BombingPower=%.3f but %.3f given", expectedBombingPower, result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
type Science struct {
|
||||||
|
Name string
|
||||||
|
Drive float64
|
||||||
|
Weapons float64
|
||||||
|
Shields float64
|
||||||
|
Cargo float64
|
||||||
|
}
|
||||||
@@ -6,10 +6,6 @@ import (
|
|||||||
"github.com/iliadenisov/galaxy/pkg/number"
|
"github.com/iliadenisov/galaxy/pkg/number"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Ship struct {
|
|
||||||
TypeName string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ShipType struct {
|
type ShipType struct {
|
||||||
Name string
|
Name string
|
||||||
Drive float64 // [0], [1...]
|
Drive float64 // [0], [1...]
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package number
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFixed(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
precision int
|
||||||
|
source, expected float64
|
||||||
|
}{
|
||||||
|
{3, 0, 0},
|
||||||
|
{3, -1, -1},
|
||||||
|
{3, 1.5, 1.5},
|
||||||
|
{3, 2.25, 2.25},
|
||||||
|
{3, 3.275, 3.275},
|
||||||
|
{3, 4.0004, 4.000},
|
||||||
|
{5, 5.000005, 5.00001},
|
||||||
|
{4, -6.00004, -6.},
|
||||||
|
{4, -6.00005, -6.0001},
|
||||||
|
} {
|
||||||
|
t.Run(fmt.Sprintf("%f", tc.source), func(t *testing.T) {
|
||||||
|
if tc.precision == 3 {
|
||||||
|
assert.Equal(t, tc.expected, Fixed3(tc.source))
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, tc.expected, fixed(tc.source, tc.precision))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user