2019-11-13 02:56:09 +03:00

162 lines
4.1 KiB
Go

package mapgens
import (
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util"
)
//fixme move to config
var minRoomSize = 3
var maxRoomSize = 15
var maxrooms = 50
var fges = map[int]types.RectFill{
1: types.RectFill{
Top: func() *gamemap.Tile { return gamemap.NewWall() },
Bottom: func() *gamemap.Tile { return gamemap.NewWall() },
Left: func() *gamemap.Tile { return gamemap.NewWall() },
Right: func() *gamemap.Tile { return gamemap.NewWall() },
BottomLeft: func() *gamemap.Tile { return gamemap.NewWall() },
BottomRight: func() *gamemap.Tile { return gamemap.NewWall() },
TopLeft: func() *gamemap.Tile { return gamemap.NewWall() },
TopRight: func() *gamemap.Tile { return gamemap.NewWall() },
Body: func() *gamemap.Tile { return gamemap.NewFloor() },
},
2: types.RectFill{
Top: func() *gamemap.Tile { return gamemap.NewWaterTile() },
Bottom: func() *gamemap.Tile { return gamemap.NewWaterTile() },
Left: func() *gamemap.Tile { return gamemap.NewWaterTile() },
Right: func() *gamemap.Tile { return gamemap.NewWaterTile() },
BottomLeft: func() *gamemap.Tile { return gamemap.NewWaterTile() },
BottomRight: func() *gamemap.Tile { return gamemap.NewWaterTile() },
TopLeft: func() *gamemap.Tile { return gamemap.NewWaterTile() },
TopRight: func() *gamemap.Tile { return gamemap.NewWaterTile() },
Body: func() *gamemap.Tile { return gamemap.NewDeepWaterTile() },
},
}
func DefaultGen(ctx util.ClientCtx,l *gamemap.Level) (*gamemap.Level, []gamemap.Room) {
rng := util.NewRNG()
//load prefabs
pfLoader := gamemap.NewPrefabLoader(ctx)
pfRooms := pfLoader.PrefabRoomsList()
//fill with walls
for i := 0; i < l.W; i ++ {
for j := 0; j < l.H; j++ {
l.SetTileByXY(i, j, gamemap.NewWall())
}
}
rooms := make([]gamemap.Room, 0)
prefabUsed := false
for i := 0; i < maxrooms; i++ {
failed := false
var fillage types.RectFill
fillage = fges[rng.GetWeightedEntity(map[int]int{1: 10, 2: 1})]
var newRoom gamemap.Room
if !prefabUsed || rng.Range(0,5) > 3 {
//prefab
prefabUsed = true
r := pfRooms[rng.Range(0, len(pfRooms))] //copy to local scope
newRoom = r
} else {
newRoom = gamemap.NewRandomRectRoom(
rng,
rng.Range(minRoomSize, maxRoomSize),
rng.Range(minRoomSize, maxRoomSize),
fillage,
)
}
where := types.Coords{
rng.Range(1, l.W -2 - newRoom.W),
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 {
rooms = append(rooms, newRoom)
}
//addStairs(rooms)
//itemize(rooms)
}
//build delannay graph from room center
//refine it to minimum spanning tree
//connect accordingly
for _, room := range rooms {
err := room.BlitToLevel(l)
if err != nil {
fmt.Printf("err: %v", err)
}
}
for idx, room := range rooms {
if idx > 0 {
connectRooms(l, room, rooms[idx-1], rng.Range(0, 1))
}
}
return l, rooms
}
func connectRooms(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)
}
}
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{i, y}) {
l.SetTileByXY(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, i}) {
l.SetTileByXY(x, i, gamemap.NewFloor())
}
}
}