package generator import ( "errors" "fmt" "math" "math/rand" "github.com/iliadenisov/galaxy/pkg/generator/draw" ) type Map struct { Width uint Height uint HomePlanets []PlanetarySystem FreePlanets []Planet plotter Plotter } type Coordinate struct { X, Y float64 } type Planet struct { Position Coordinate Size float64 Resources float64 // Сырьё } type PlanetarySystem struct { HW Planet DW []Planet } type Plotter struct { factor float64 sectors draw.Plane } func Generate(param MapParameter) (result Map) { pl := func(c Coordinate, param UninhabitedPlanetParameters) Planet { return Planet{ Position: c, Size: param.MinSize + rand.Float64()*(param.MaxSize-param.MinSize), Resources: float64(param.MinResource) + rand.Float64()*(param.MaxResource-param.MinResource)} } // mapSize := uint(math.Ceil(math.Sqrt(float64(param.Players)))) * param.HW_MinDistance var mapSize uint = 200 result = NewMap(mapSize, mapSize, param.Players) totalPlanets := param.Players * 10 freePlanets := totalPlanets - param.Players*(param.DW_Count+1) fmt.Println("map:", mapSize, "players:", param.Players, "planets:", totalPlanets, "uninhabited:", freePlanets) giantsNum := int(math.Ceil(float64(freePlanets) * param.GiantPlanets.Probability)) fmt.Println("generating", giantsNum, "giant planets") for i := 0; i < giantsNum; i++ { coord := result.newPlanet(float64(param.GiantPlanets.MinDistanceHW)) planet := pl(coord, param.GiantPlanets) result.addPlanet(planet) // result.FreePlanets = append(result.FreePlanets, planet) } bigsNum := int(math.Ceil(float64(freePlanets) * param.BigPlanets.Probability)) fmt.Println("generating", bigsNum, "big planets") for i := 0; i < bigsNum; i++ { coord := result.newPlanet(float64(param.BigPlanets.MinDistanceHW)) planet := pl(coord, param.BigPlanets) result.addPlanet(planet) // result.FreePlanets = append(result.FreePlanets, planet) } for player := 0; player < int(param.Players); player++ { fmt.Println("generating HW #", player) coord := result.newPlanet(float64(param.HW_MinDistance)) planet := Planet{Position: coord, Size: float64(param.HW_Size), Resources: float64(param.HW_Resources)} // fmt.Println("HW: ", planet) result.HomePlanets[player] = PlanetarySystem{HW: planet} } fmt.Println("free sectors left: ", len(result.plotter.freeSectors())) result.plotter.sectors.Clear() for _, hw := range result.HomePlanets { result.plotter.markNoGoZone(hw.HW.Position.X, hw.HW.Position.Y, 5) for _, dw := range hw.DW { result.plotter.markNoGoZone(dw.Position.X, dw.Position.Y, 5) } } for _, planet := range result.FreePlanets { result.plotter.markNoGoZone(planet.Position.X, planet.Position.Y, 5) } fmt.Println("free sectors after reset: ", len(result.plotter.freeSectors())) return } func (m Map) newPlanet(deadZoneRaduis float64) Coordinate { fs := m.plotter.freeSectors() fmt.Println("free sectors: ", len(fs)) fsCount := len(fs) if fsCount == 0 { panic("no more space for planets") } next := rand.Intn(fsCount) x := fs[next][0] y := fs[next][1] fmt.Println("planet on plot: x =", x, "y =", y) planetX := float64(x)*m.plotter.factor + rand.Float64()*m.plotter.factor planetY := float64(y)*m.plotter.factor + rand.Float64()*m.plotter.factor m.plotter.markDeadZone(int(x), int(y), deadZoneRaduis) return Coordinate{X: planetX, Y: planetY} } func (m *Map) addPlanet(planet Planet) { m.FreePlanets = append(m.FreePlanets, planet) } func (p Plotter) freeSectors() (result [][]uint) { result = make([][]uint, 0) for x := uint(0); x < p.sectors.Width; x++ { for y := uint(0); y < p.sectors.Height; y++ { if !p.sectors.Marked(x, y) { result = append(result, []uint{x, y}) } } } return } func (p Plotter) markDeadZone(x, y int, radius float64) { p.sectors.Circle(x, y, radius) } func (p Plotter) markNoGoZone(x, y float64, radius float64) { // TODO: test p.markDeadZone(int(x/p.factor), int(y/p.factor), radius) } func NewMap(width, height, players uint) Map { var factor float64 = 1.0 sectorsX := uint(float64(width) / factor) sectorsY := uint(float64(height) / factor) return Map{ Width: width, Height: height, HomePlanets: make([]PlanetarySystem, players), plotter: Plotter{ factor: factor, sectors: draw.New(sectorsX, sectorsY)}} } func errfmt(message string) error { return errors.New("generator: " + message) }