package generator import ( "fmt" "math" "math/rand" "github.com/iliadenisov/galaxy/pkg/bitmap" ) 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 clearFn func() circleFn func(x, y int, r float64) freeCountFn func() int freeNumberToCoordFn func(int) (int, int) } 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) } 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)} result.HomePlanets[player] = PlanetarySystem{HW: planet} } result.plotter.clearFn() 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) } return } func (m Map) newPlanet(deadZoneRaduis float64) Coordinate { fsCount := m.plotter.freeCountFn() if fsCount == 0 { panic("no more space for planets") } next := rand.Intn(fsCount) x, y := m.plotter.freeNumberToCoordFn(next) 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) markNoGoZone(x, y float64, radius float64) { // TODO: test p.markDeadZone(int(x/p.factor), int(y/p.factor), radius) } func (p Plotter) markDeadZone(x, y int, radius float64) { p.circleFn(x, y, radius) } func NewMap(width, height, players uint) Map { var factor float64 = 1.0 sectorsX := uint32(float64(width) / factor) sectorsY := uint32(float64(height) / factor) bm := bitmap.NewBitmap(sectorsX, sectorsY) return Map{ Width: width, Height: height, HomePlanets: make([]PlanetarySystem, players), plotter: Plotter{ factor: factor, clearFn: bm.Clear, circleFn: func(x, y int, r float64) { bm.Circle(x, y, r, true) }, freeCountFn: bm.FreeCount, freeNumberToCoordFn: func(n int) (x int, y int) { x, y, err := bm.GetFreeN(n) if err != nil { panic(err) } return }, }, } }