Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #===============================================================================
- # Roguelike Random Dungeon Generator
- #-------------------------------------------------------------------------------
- # Version: 2.0a
- # Author: cozziekuns (rmrk)
- # Last Date Updated: 4/11/2011
- #===============================================================================
- # Description:
- #-------------------------------------------------------------------------------
- # A random dungeon generator akin to that of games like Rogue or Pokemon Mystery
- # Dungeon.
- #===============================================================================
- # Updates
- # ------------------------------------------------------------------------------
- # o 16/07/2011 - Started Script
- # o 17/07/2011 - Updated Script to support black outlines and some autotile
- # features
- # o 15/09/2011 - Bugfix.
- # o 17/09/2011 - Major overhaul of the entire script. Now has fully functional
- # autotile support, and a much faster algorithm that can create a
- # 500 * 500 tile map with 1000 features in less than 10 seconds.
- #===============================================================================
- # To-do List
- #-------------------------------------------------------------------------------
- # o Nothing! Suggest some features.
- #===============================================================================
- # Instructions
- #-------------------------------------------------------------------------------
- # Copy and paste this script above ? Main Process but below ? Materials, and
- # edit the modules to your liking. Some difficult modules have links to the
- # instructions.
- #===============================================================================
- # Maps
- #-------------------------------------------------------------------------------
- # Start editing at:
- # case id
- # when [id] - Replace [id] with your map id.
- # ROOM_MIN_WIDTH : Minimum width for a single "Room"
- # ROOM_MAX_WIDTH : Maximum width for a single "Room"
- # ROOM_MIN_HEIGHT : Minimum height for a single "Room"
- # ROOM_MAX_HEIGHT : Maximum height for a single "Room"
- # FEATURES : How many features you want to fit in the map
- # WALL_TILE : Tile of the wall
- # FLOOR_TILE : Tile of the floor
- # BLACK_OUTLINE : Do you want a black outline surrounding your random
- # dungeon (slow).
- # end
- #===============================================================================
- module COZZIEKUNS
- module RDG
- def self.map_settings(id)
- case id
- when 1
- room_min_width = 3
- room_max_width = 6
- room_min_height = 3
- room_max_height = 6
- features = 200
- wall_tile = 0
- floor_tile = 16
- black_outline = false
- when 2
- room_min_width = 4
- room_max_width = 8
- room_min_height = 4
- room_max_height = 8
- features = 75
- wall_tile = 6
- floor_tile = 52
- black_outline = false
- end
- return [room_min_width, room_max_width, room_min_height, room_max_height,
- features, wall_tile, floor_tile, black_outline].compact
- end
- end
- end
- #==============================================================================
- # ** Game_Map
- #==============================================================================
- class Game_Map
- alias coz_rdg_gm_setup setup
- def setup(*args)
- coz_rdg_gm_setup(*args)
- create_dungeon if not COZZIEKUNS::RDG.map_settings(@map_id).empty?
- end
- def create_dungeon
- set_variables
- fill_wall_tiles
- dig_random_room
- for i in 0...@features
- count = 0
- loop do
- count += 1
- choose_next_wall
- make_new_feature
- break if @can_make or count == 5
- end
- end
- refine_tilemap
- set_player_and_events
- end
- def set_variables
- settings = COZZIEKUNS::RDG.map_settings(@map_id)
- @rmiw = settings[0]
- @rmaw = settings[1]
- @rmih = settings[2]
- @rmah = settings[3]
- @features = settings[4]
- @walls = []
- @floor = []
- @next_wall = []
- @wall_tile = (settings[5] + 80) * 48 + 2048
- @wall2_tile = (settings[5] + 88) * 48 + 2048
- @floor_tile = (settings[6] + 128) + 1408
- @black_outline = settings[7]
- @next_feature = 0
- @can_make = false
- @player_transfered = false
- end
- def set_player_and_events
- for event in $game_map.events.values + [$game_player]
- loop do
- ax = @floor[rand(@floor.size)][0]
- ay = @floor[rand(@floor.size)][1]
- if passable_in_area?(ax - 1, ay - 1, event)
- event.moveto(ax, ay)
- break
- end
- end
- end
- end
- alias coz_rdg_gm_update update
- def update
- coz_rdg_gm_update
- unless @player_transfered or COZZIEKUNS::RDG.map_settings(@map_id).empty?
- @player_transfered = true
- set_player_and_events
- end
- end
- def passable_in_area?(x, y, char, width = 3, height = 3)
- for i in x...x + width; for j in y...y + height
- return false if not char.passable?(i, j)
- end; end
- return true
- end
- def fill_wall_tiles
- for i in 0...width; for j in 0...height
- @map.data[i, j, 0] = @wall_tile
- end; end
- end
- def dig_random_room
- x = [rand(width) + 1, width - @rmaw - 1].min
- y = [rand(height) + 1, height - @rmah - 1].min
- dig_room(x, y)
- end
- def dig_room(x, y, direction = 2)
- width = rand(@rmiw) + @rmaw - @rmiw + 1
- height = rand(@rmih) + @rmah - @rmih + 1
- for i in 0...width
- for j in 0...height
- case direction
- when 0; new_x = x + j; new_y = y + i
- when 1; new_x = x - i; new_y = y + j
- when 2; new_x = x + i; new_y = y + j
- when 3; new_x = x + j; new_y = y - i
- end
- @map.data[new_x, new_y, 0] = @floor_tile
- @floor.push([new_x, new_y])
- @walls.push([new_x - 1, new_y, 1]) if new_x == x
- @walls.push([new_x + 1, new_y, 2]) if new_x == x + width - 1
- @walls.push([new_x, new_y - 1, 3]) if new_y == y
- @walls.push([new_x, new_y + 1, 0]) if new_y == y + height - 1
- end
- end
- @next_feature = 1
- end
- def dig_corridor(x, y, direction)
- j = 0
- width = rand(@rmiw) + @rmaw - @rmiw + 1
- height = 0
- for i in 0...width
- case direction
- when 0; new_x = x + j; new_y = y + i
- when 1; new_x = x - i; new_y = y + j
- when 2; new_x = x + i; new_y = y + j
- when 3; new_x = x + j; new_y = y - i
- end
- @map.data[new_x, new_y, 0] = @floor_tile
- @floor.push([new_x, new_y])
- @walls.push([new_x - 1, new_y, 1]) if new_x == x
- @walls.push([new_x + 1, new_y, 2]) if new_x == x + width - 1
- @walls.push([new_x, new_y - 1, 3]) if new_y == y
- @walls.push([new_x, new_y + 1, 0]) if new_y == y + height - 1
- end
- case direction
- when 0; @next_wall = [x + height, y + width, 0]
- when 1; @next_wall = [x - width, y + height, 1]
- when 2; @next_wall = [x + width, y + height, 2]
- when 3; @next_wall = [x + height, y - width, 3]
- end
- @next_feature = 0
- end
- def choose_next_wall; @next_wall = @walls[rand(@walls.size)]; end
- def make_new_feature
- direction = rand(4)
- @can_make = scan_area(@next_wall[0], @next_wall[1], @next_wall[2])
- return if not @can_make
- @walls.delete(@next_wall)
- dig_corridor(@next_wall[0], @next_wall[1], @next_wall[2])
- @can_make = scan_area(@next_wall[0], @next_wall[1], @next_wall[2])
- dig_room(@next_wall[0], @next_wall[1], @next_wall[2]) if @can_make
- @next_feature = 1
- end
- def scan_area(x, y, direction)
- case @next_feature
- when 0
- for i in 0..@rmaw + 1; for j in 0..@rmah + 1
- case direction
- when 0; return false if passable?(x + j, y + i) or !valid?(x + j, y + i)
- when 1; return false if passable?(x - i, y + j) or !valid?(x - i, y + j)
- when 2; return false if passable?(x + i, y + j) or !valid?(x + i, y + j)
- when 3; return false if passable?(x + j, y - i) or !valid?(x + j, y - i)
- end
- end; end
- when 1
- for i in 0..@rmaw + 1; for j in -2..2
- case direction
- when 0; return false if passable?(x + j, y + i) or !valid?(x + j, y + i)
- when 1; return false if passable?(x - i, y + j) or !valid?(x - i, y + j)
- when 2; return false if passable?(x + i, y + j) or !valid?(x + i, y + j)
- when 3; return false if passable?(x + j, y - i) or !valid?(x + j, y - i)
- end
- end; end
- end
- return true
- end
- def refine_tilemap
- for point in @floor
- next if passable?(point[0], point[1] - 1)
- if passable?(point[0], point[1] - 2)
- @map.data[point[0], point[1] - 1, 0] = @floor_tile
- else
- @map.data[point[0], point[1] - 1, 0] = @wall2_tile
- end
- end
- for i in 0...width; for j in 0...height
- next if @map.data[i, j, 0] == @floor_tile
- type = @map.data[i, j, 0] == @wall2_tile ? 1 : 0
- @map.data[i, j, 0] = rdg_tilemap_id(i, j, type)
- end; end
- return if not @black_outline
- for i in 0...width; for j in 0...height
- next if @floor.include?([i, j])
- if (@map.data[i, j, 0] - 2048) % 48 == 0
- @map.data[i, j, 0] = 0
- end
- end; end
- end
- def rdg_tilemap_id(x, y, type)
- data = @map.data
- base = @map.data[x, y, 0]
- return base if x == 0 or x == width - 1 or y == 0 or y == width - 1
- case type
- when 0
- count = 0
- count += 1 if (data[x - 1, y, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 2 if (data[x, y - 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 4 if (data[x + 1, y, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 8 if (data[x, y + 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- id = case count
- when 0 then check_corners(x, y, base)
- when 1 then 16 + ((check_corners(x, y, base, [2, 4])) / 2)
- when 2 then 20 + ((check_corners(x, y, base, [4, 8])) / 4)
- when 3 then 34 + ((check_corners(x, y, base, [4])) / 4)
- when 4 then 24 + ([0,8,1,9].index(check_corners(x, y, base, [1, 8])))
- when 5 then 32
- when 6 then 36 + ((check_corners(x, y, base, [8])) / 8)
- when 7 then 42
- when 8 then 28 + check_corners(x, y, base, [1, 2])
- when 9 then 40 + ((check_corners(x, y, base, [2])) / 2)
- when 10 then 33
- when 11 then 43
- when 12 then 38 + check_corners(x, y, base, [1])
- else
- 31 + count
- end
- when 1
- count = 0
- count += 1 if passable?(x - 1, y)
- count += 4 if passable?(x + 1, y)
- id = count + 10
- end
- return base + id
- end
- def check_corners(x, y, base, corners = [1, 2, 4, 8])
- count = 0
- data = @map.data
- count += 1 if corners.include?(1) and (data[x - 1, y - 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 2 if corners.include?(2) and (data[x + 1, y - 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 4 if corners.include?(4) and (data[x + 1, y + 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- count += 8 if corners.include?(8) and (data[x - 1, y + 1, 0] - 2048) / 48 != (base - 2048) / 48 rescue false
- return count
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment