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" ) //fixme move to config var minRoomSize = 3 var maxRoomSize = 22 var maxrooms = 30 //fixme make closure to stack them func DefaultGen(l *gamemap.Level) (*gamemap.Level, []*gamemap.Room) { rng := util.NewRNG() //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) //one wall around whole level guaranteed levelBoundary := types.NewRect(l.X + 1, l.Y + 1, l.W - 2, l.H - 2) for i := 0; i < maxrooms; i++ { newRoom := &gamemap.Room{ Rect: types.NewRect( rng.Range(l.X, l.W), rng.Range(l.Y, l.H), rng.Range(minRoomSize, maxRoomSize), rng.Range(minRoomSize, maxRoomSize), )} newRoom.Center = types.Coords{newRoom.X + newRoom.W / 2, newRoom.Y + newRoom.H / 2} failed := false if !levelBoundary.InBounds(types.Coords{newRoom.X, newRoom.Y}) { failed = true } if !failed && !l.InBounds(types.Coords{newRoom.X + newRoom.W, newRoom.Y + newRoom.H}) { failed = true } if !failed { for _, otherRoom := range rooms { if otherRoom.Intersects(newRoom.Rect) { failed = true break } } } if !failed { rooms = append(rooms, newRoom) } //addStairs(rooms) //itemize(rooms) } 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() }, }, } var fillage types.RectFill for _, room := range rooms { fillage = fges[rng.GetWeightedEntity(map[int]int{1:10, 2:1})] room.Blit(fillage, l) } for idx, room := range rooms { if idx > 0 { connectRooms(l, room, rooms[idx-1], fillage, rng.Range(0,1)) } } return l, rooms } func connectRooms (l *gamemap.Level, room, otherRoom *gamemap.Room, fillage types.RectFill, toss int) { if toss == 0 { digHTunnel(l, room.Center.X,otherRoom.Center.X,room.Center.Y, fillage) digVTunnel(l, room.Center.Y,otherRoom.Center.Y,otherRoom.Center.X, fillage) } else { digVTunnel(l, room.Center.Y, otherRoom.Center.Y, room.Center.Y, fillage) digHTunnel(l, room.Center.X, otherRoom.Center.X, otherRoom.Center.Y, fillage) } } func digHTunnel(l *gamemap.Level, x1,x2,y int, fillage types.RectFill) { 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, fillage.Body.(func() *gamemap.Tile)()) //l.Tiles[i][y] = gamemap.NewFloor() } } } func digVTunnel(l *gamemap.Level, y1,y2,x int, fillage types.RectFill) { 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, fillage.Body.(func() *gamemap.Tile)()) } } }