210 lines
4.9 KiB
Go
210 lines
4.9 KiB
Go
package mapgens
|
|
|
|
import (
|
|
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
|
|
"lab.zaar.be/thefish/alchemyst-go/engine/types"
|
|
"lab.zaar.be/thefish/alchemyst-go/util"
|
|
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
|
|
)
|
|
|
|
//fixme move to config
|
|
var minRoomSize = 8
|
|
var maxRoomSize = 22
|
|
var maxrooms = 100
|
|
|
|
var fges = map[int]types.RectFill{
|
|
1: {
|
|
Top: gamemap.NewWall,
|
|
Bottom: gamemap.NewWall,
|
|
Left: gamemap.NewWall,
|
|
Right: gamemap.NewWall,
|
|
BottomLeft: gamemap.NewWall,
|
|
BottomRight: gamemap.NewWall,
|
|
TopLeft: gamemap.NewWall,
|
|
TopRight: gamemap.NewWall,
|
|
Body: gamemap.NewFloor,
|
|
},
|
|
|
|
2: {
|
|
Top: gamemap.NewWaterTile,
|
|
Bottom: gamemap.NewWaterTile,
|
|
Left: gamemap.NewWaterTile,
|
|
Right: gamemap.NewWaterTile,
|
|
BottomLeft: gamemap.NewWaterTile,
|
|
BottomRight: gamemap.NewWaterTile,
|
|
TopLeft: gamemap.NewWaterTile,
|
|
TopRight: gamemap.NewWaterTile,
|
|
Body: gamemap.NewDeepWaterTile,
|
|
},
|
|
}
|
|
|
|
func GetRandomRoomList(rng *util.RNG, l *gamemap.Level, maxRooms, minRoomSize, maxRoomSize int, ) []gamemap.Room{
|
|
rooms := make([]gamemap.Room, 0)
|
|
pfLoader := gamemap.NewPrefabLoader()
|
|
pfRooms := pfLoader.PrefabRoomsList()
|
|
|
|
var fillage types.RectFill
|
|
prefabUsed := false
|
|
|
|
for i := 0; i < maxRooms; i++ {
|
|
failed := false
|
|
fillage = fges[rng.GetWeightedEntity(map[int]int{1: 10, 2: 1})]
|
|
|
|
|
|
|
|
var newRoom = gamemap.Room{}
|
|
if prefabUsed && rng.Range(0, 5) <= 3 {
|
|
newRoom = gamemap.NewRandomRectRoom(
|
|
rng,
|
|
rng.Range(minRoomSize, maxRoomSize),
|
|
rng.Range(minRoomSize, maxRoomSize),
|
|
fillage,
|
|
)
|
|
} else {
|
|
//if prefabUsed {
|
|
//prefab
|
|
prefabUsed = true
|
|
|
|
r := pfRooms[rng.Range(0, len(pfRooms))] //copy to local scope
|
|
newRoom = gamemap.Room{
|
|
Rect: r.Rect,
|
|
Center: r.Center,
|
|
Geometry: r.Geometry,
|
|
Items: r.Items,
|
|
Mobs: r.Mobs,
|
|
Connectors: make([]types.Coords,0),
|
|
}
|
|
newRoom.Connectors = append(newRoom.Connectors, r.Connectors...)
|
|
// for _, coord := range r.Connectors {
|
|
// newRoom.Connectors = append(newRoom.Connectors, coord)
|
|
// }
|
|
}
|
|
where := types.Coords{
|
|
X: rng.Range(1, l.W-2-newRoom.W),
|
|
Y: rng.Range(1, l.H-2-newRoom.H),
|
|
}
|
|
|
|
newRoom.MoveToCoords(where)
|
|
|
|
for _, otherRoom := range rooms {
|
|
if otherRoom.Intersects(newRoom.Rect) {
|
|
failed = true
|
|
break
|
|
}
|
|
}
|
|
if failed {
|
|
continue
|
|
}
|
|
if len(newRoom.Connectors) > 0 {
|
|
rooms = append(rooms, newRoom)
|
|
}
|
|
}
|
|
return rooms
|
|
}
|
|
|
|
//fixme overlapping rooms
|
|
func BlitToLevel (l *gamemap.Level, rooms[]gamemap.Room) {
|
|
for _, room := range rooms {
|
|
err := room.BlitToLevel(l)
|
|
if err != nil {
|
|
appctx.Logger().Err(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
//delaunay helper funcs
|
|
func MedianStraight(rng *util.RNG, l *gamemap.Level, rooms []gamemap.Room, centers []types.Coords, edge types.Edge) {
|
|
//find connected rooms
|
|
var fromRoom, toRoom gamemap.Room
|
|
for _, room := range rooms {
|
|
if room.Center == edge.From {
|
|
fromRoom = room
|
|
continue
|
|
}
|
|
if room.Center == edge.To {
|
|
toRoom = room
|
|
continue
|
|
}
|
|
if len(fromRoom.Connectors) > 0 && len(toRoom.Connectors) > 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
midpoint := edge.Midpoint()
|
|
fromConnector := FindNearestConnector(midpoint, fromRoom)
|
|
toConnector := FindNearestConnector(midpoint, toRoom)
|
|
ConnectStraight(rng, l, fromConnector, toConnector, midpoint)
|
|
}
|
|
|
|
func FindNearestConnector(midpoint types.Coords, room gamemap.Room) types.Coords {
|
|
var nearest types.Coords
|
|
for _, con := range room.Connectors {
|
|
if nearest.X == 0 {
|
|
nearest = con
|
|
continue
|
|
}
|
|
if midpoint.DistanceTo(con) < midpoint.DistanceTo(nearest) {
|
|
nearest = con
|
|
}
|
|
}
|
|
return nearest
|
|
}
|
|
|
|
func ConnectStraight(rng *util.RNG, l *gamemap.Level, from, to, midpoint types.Coords) {
|
|
toss := rng.Range(1, 2)
|
|
if toss > 1 {
|
|
DigHTunnel(l, from.X, midpoint.X, from.Y)
|
|
DigVTunnel(l, from.Y, to.Y, midpoint.X)
|
|
DigHTunnel(l, midpoint.X, to.X, to.Y)
|
|
} else {
|
|
DigVTunnel(l, from.Y, midpoint.Y, from.X)
|
|
DigHTunnel(l, from.X, to.X, midpoint.Y)
|
|
DigVTunnel(l, midpoint.Y, to.Y, to.X)
|
|
}
|
|
}
|
|
|
|
func DigHTunnel(l *gamemap.Level, x1, x2, y int) {
|
|
var start, finish int
|
|
if x1 < x2 {
|
|
start = x1
|
|
finish = x2
|
|
} else {
|
|
start = x2
|
|
finish = x1
|
|
}
|
|
for i := start; i <= finish; i++ {
|
|
if l.InBounds(types.Coords{X: i, Y: y}) {
|
|
l.MakePassByXY(i, y, gamemap.NewFloor())
|
|
//l.Tiles[i][y] = gamemap.NewFloor()
|
|
}
|
|
}
|
|
}
|
|
|
|
func DigVTunnel(l *gamemap.Level, y1, y2, x int) {
|
|
var start, finish int
|
|
if y1 < y2 {
|
|
start = y1
|
|
finish = y2
|
|
} else {
|
|
start = y2
|
|
finish = y1
|
|
}
|
|
for i := start; i <= finish; i++ {
|
|
if l.InBounds(types.Coords{X: x, Y: i}) {
|
|
l.MakePassByXY(x, i, gamemap.NewFloor())
|
|
}
|
|
}
|
|
}
|
|
|
|
//default helper
|
|
|
|
func ConnectRoomCenters(l *gamemap.Level, room, otherRoom gamemap.Room, toss int) {
|
|
if toss == 0 {
|
|
DigHTunnel(l, room.Center.X, otherRoom.Center.X, room.Center.Y)
|
|
DigVTunnel(l, room.Center.Y, otherRoom.Center.Y, otherRoom.Center.X)
|
|
} else {
|
|
DigVTunnel(l, room.Center.Y, otherRoom.Center.Y, room.Center.Y)
|
|
DigHTunnel(l, room.Center.X, otherRoom.Center.X, otherRoom.Center.Y)
|
|
}
|
|
}
|