Level Generation

From The Binding of Isaac: Rebirth Wiki
Jump to navigation Jump to search

Level generation is the process the game uses to create each floor. Each floor has its own requirements of size, special rooms, and dead ends that must be met.

Process

First, the game determines how many rooms will generate on the floor. Later floors have more rooms, and Curse of the Labyrinth.pngCurse of the Labyrinth makes the floor much larger.

  • If the floor is not XL or (except in Rebirth and Afterbirth)The VoidThe Void:
    • NumberOfRooms = 3.33 × FloorDepth + 5-6 (maximum of 20)
  • If the floor is an XL floor:
    • NumberOfRooms = 1.8 × (3.33 × FloorDepth + 5-6) (maximum of 45)
  • If the floor is The Void:
    • NumberOfRooms = 50-59
  • 2-3 more rooms are added if playing on Hard Mode
  • 4 more rooms are added if the floor has Curse of the Lost.

Then the minimum number of dead ends the floor must generate is set.

  • All floors have at least 5 dead ends:
    • 1 dead end is added to all floors except the first floor.
    • 1 dead end is added to XL floors.
    • 2 dead ends are added to The Void.
    • (in Repentance and Repentance+) 1 dead end is added if Isaac has Collectible Voodoo Head icon.pngVoodoo Head.

Next, special rooms are generated in dead ends.

Special rooms generate in the following order:

  • Boss RoomBoss Room (guaranteed).
    • If it is an XL floor, two boss rooms will be generated back to back.
    • (except in Rebirth and Afterbirth) Multiple Boss Rooms are generated in The VoidThe Void.
  • Super Secret RoomSuper Secret Room (guaranteed).
    • (in Repentance and Repentance+) Two Super Secret Rooms will be generated if Isaac has Collectible Luna icon.pngLuna.
  • ShopShop (guaranteed for the first 3 Chapters).
  • Treasure RoomTreasure Room (guaranteed for the first 3 Chapters).
  • (in Repentance and Repentance+) PlanetariumPlanetarium (base 1% chance to be generated in Chapter 1 through Chapter 3, but will not be generated in later chapters; skipping Treasure Rooms, and obtaining one of a number of items and trinkets will modify this chance).
  • Dice RoomDice Room or Sacrifice RoomSacrifice Room (1/7 (~14%) base chance, plus a second 1/4 chance for a total of 5/14 (~36%) if Isaac’s total health is equal to or greater than his total Heart Containers).
    • If a Sacrifice Room is successfully generated, it has a 1/50 base chance to become a Dice Room instead, plus a second 1/5 chance for a total of 27/125 (~22%) if Isaac has 2 or more Keys.
  • LibraryLibrary (1/20 chance).
    • The code specifically checks for a flag that is supposed to increase Library generation rate if a book was touched, but the flag is never set.
  • Curse RoomCurse Room (1/2 chance, plus a second 1/4 chance for a total of 5/8 (~63%) if Isaac has entered a Devil RoomDevil Room this run).
    • (in Repentance and Repentance+) An additional Curse Room is generated on each floor if Isaac has Collectible Voodoo Head icon.pngVoodoo Head; an extra dead end is also generated to accommodate it.
  • Mini-Boss RoomMini-Boss Room (1/4 chance, plus a second 1/3 chance for a total of 1/2 (50%) if it is the first floor).
  • Challenge RoomChallenge Room (guaranteed if Isaac’s total health is equal to or greater than his total heart containers; will not be generated otherwise).
    • Will not be generated on the first floor, and has a 50% chance on the second floor.
    • Will always be a Boss Challenge RoomBoss Challenge Room on the second floor of a chapter, and a normal Challenge Room otherwise.
  • VaultVault or ArcadeArcade (guaranteed if Isaac has 5 or more Coins and it’s the second floor of a Chapter; will not be generated otherwise).
    • If an Arcade is successfully generated, it has a 1/10 chance to be a Vault instead, plus a second 1/3 chance for a total of 2/5 (40%) if Isaac has 2 or more Keys.
    • (in Repentance and Repentance+) If Isaac has 2 or more Keys but less than 5 Coins, a Vault can still be generated. If Isaac has 5 or more Coins but less than 2 Keys, and if the 1/10 chance to become a Vault passes, then neither an Arcade or a Vault will be generated.
  • Clean BedroomClean Bedroom or Dirty BedroomDirty Bedroom (1/50 chance, plus a second 1/5 chance for a total of 27/125 (~22%) if Isaac has 1/2 or fewer Red Heart.pngRed Hearts and no Soul Heart.pngSoul Hearts, or 1 or fewer Soul Hearts and no Red/(except in Rebirth and Afterbirth) Bone Heart.pngBone Hearts).
    • Equal chance to be a Clean or Dirty Bedroom.
    • Will only be generated in the first 3 Chapters.
  • Secret RoomSecret Room (guaranteed).
    • Each location candidate is given a starting weight of 10-14, reduced by 3 if it has only 2 neighboring rooms, and reduced by 6 if it has only 1 neighboring room. The highest weight candidate is picked.
      • In practice, this means a Secret Room will be extremely likely to have at least 2 rooms adjacent to it, unless it's the very first floor, where occasionally one will be placed at a dead end for lack of anywhere else to put it.
    • Will not be placed next to a Boss Room, Super Secret Room, another Secret Room, or the starting room if it's The Chest or Dark Room.
    • (except in Rebirth and Afterbirth) An additional Secret Room will be generated if Isaac has Fragmented CardFragmented Card.
    • (in Repentance and Repentance+) An additional Secret Room will be generated if Isaac has Collectible Luna icon.pngLuna, three if he also has Fragmented Card.
  • (in Repentance and Repentance+) Ultra Secret RoomUltra Secret Room (guaranteed).
  • (except in Rebirth and Afterbirth) A Grave Room is placed if the floor is Dark Room.
  • Normal Room layouts are chosen.
    • Each room has a set difficulty number, which is chosen based on the current floor of the chapter and if it's Hard Mode or not.
      • Normal Mode floor 1: 1-5
      • Normal Mode floor 2: 5-10
      • Hard Mode floor 1: (except in Repentance and Repentance+) 5 only / (in Repentance and Repentance+) 1-10 (1 and 10 are less common)
      • Hard Mode floor 2: (in Rebirth and Afterbirth) 10 / (in Afterbirth †) 10-15 / (in Repentance and Repentance+) 5-15 (5 is less common)
      • XL Floors count as (except in Repentance and Repentance+) floor 1 / (in Repentance and Repentance+) both floors
      • Chapters 5 and 6 count as (except in Repentance and Repentance+) floor 1 / (in Repentance and Repentance+) floor 2
      • The Void on Normal Mode: 5-10 ((in Repentance and Repentance+) and 20)
      • The Void on Hard Mode: 5-15 / (in Repentance and Repentance+) 5-20

Pseudo-Code

Some parts of the level generation are based on the following pseudo-code:

--Pseudo lua code for getting the number of rooms for a floor.

NumberOfRooms = Min(20, Rand(0, 1) + 5 + Floor(StageId * 10 / 3))
if CurseOfTheLabyrinth then
 NumberOfRooms = Min(45, Floor(NumberOfRooms * 1.8))
elseif CurseOfTheLost then
 NumberOfRooms += 4
end
if StageId == 12 then --The Void
 NumberOfRooms = 50 + (Rand() % 10)
end
if IsHardDifficulty then
 NumberOfRooms += 2 + Rand(0, 1)
end

--Pseudo lua code for getting the number of deadends a floor must have.

MinDeadEnds = 5
if StageId ~= 1 then
 MinDeadEnds += 1
end
if CurseOfTheLabyrinth then
 MinDeadEnds += 1
end
if StageId == 12 then
	MinDeadEnds += 2
end


--Deadends are sorted by distance from the starting room descending.
--e.g. Boss room is placed in the farthest deadend, super secret is placed in the next farthest deadend

--DequeueDeadend also resizes the deadend. This is important to note because that means most deadends get changed to a 1x1 by the end of this.

PlaceRoom(ROOM_BOSS, DequeueDeadend())
--Super Secret
PlaceRoom(ROOM_SUPERSECRET, DequeueDeadend())
--Shop
if StageId < 7 or (StageId < 9 and HasTrinket(SilverDollar)) and VictoryLap < 3 then
	PlaceRoom(ROOM_SHOP, DequeueDeadend())
end
--Treasure
if StageId < 7 or (StageId < 9 and HasTrinket(BloodyCrown)) then
	PlaceRoom(ROOM_TREASURE, DequeueDeadend())
end
--Dice and Sacrifice
if StageId < 12 then
	local deadend = DequeueDeadend() --resizes the room :(
	if deadend ~= nil then
		local roomType = nil
		if Rng() % 50 == 0 or (Rng() % 5 == 0 and GetNumKeys() > 1) then 
			roomType = ROOM_DICE
		else
			roomType = ROOM_SACRIFICE
		end
		if Rng() % 7 == 0 or (Rng() & 3 == 0 and GetHearts() + GetSoulHearts() >= GetMaxHearts()) then
			PlaceRoom(roomType)
		else
			QueueDeadend(deadend)
		end
	end
end
--Library
local deadend = DequeueDeadend()
if deadend ~= nil then
	if Rng() % 20 == 0 or (Rng() & 3 == 0 and GetStateFlag(STATE_BOOK_PICKED_UP)) then
		PlaceRoom(ROOM_LIBRARY, deadend)
	else
		QueueDeadend(deadend)
	end
end
--Curse
local deadend = DequeueDeadend()
if deadend ~= nil then
	if Rng() & 1 == 0 or (Rng() & 3 == 0 and GetStateFlag(STATE_DEVILROOM_VISITED)) then
		PlaceRoom(ROOM_CURSE, deadend)
	else
		QueueDeadend(deadend)
	end
end
--MiniBoss
local boss = GetMiniBossRoom() --mini boss is picked based on floor, STATE_ULTRAPRIDE_SPAWNED and rng
local deadend = DequeueDeadend()
if deadend ~= nil then
	if Rng() & 3 == 0 or (Rng() & 2 == 0 and StageId == 1) then
		PlaceRoom(boss, deadend)
	else
		QueueDeadend(deadend)
	end
end
--Challenge
local deadend = DequeueDeadend()
if deadend ~= nil then
	if (Rng() & 1 == 0 or StageId > 2) and GetHearts() + GetSoulHearts() >= GetMaxHearts() and StageId > 1 then
		PlaceRoom(boss, deadend)
	else
		QueueDeadend(deadend)
	end
end
--Chest and Arcade
local deadend = DequeueDeadend()
if deadend ~= nil then
	local roomType = nil
	if Rng() % 10 == 0 or (Rng() % 3 == 0 and GetNumKeys() > 1) then 
		roomType = ROOM_CHEST
	else
		roomType = ROOM_ARCADE
	end
	if GetNumCoins() >= 5 and (StageId == 2 or StageId == 4 or StageId == 6 or StageId == 8) then
		PlaceRoom(roomType)
	else
		QueueDeadend(deadend)
	end
end
--Bedroom
if StageId < 7 then
	local deadend = DequeueDeadend()
	if deadend ~= nil then
		local roomType = nil
		if Rng() & 1 == 0 then
			roomType = ROOM_ISAACS
		else
			roomType = ROOM_BARREN
		end
		
		local maxHearts = nil
		if GetPlayerType() == PLAYER_THELOST or GetPlayerType() == PLAYER_XXX or GetPlayerType() == PLAYER_THESOUL then
			maxHearts = GetMaxHearts()
		else
			maxHearts = GetMaxHearts() + GetBoneHearts() * 2
		end
		
		local second = false
		if (GetHearts() < 2 and GetSoulHearts() <= 0) or (maxHearts <= 0 and GetSoulHearts() <= 2) then
			second = true
		end

		if Rng() % 50 == 0 or (Rng() % 5 == 0 and second) then
			PlaceRoom(roomType)
		else
			QueueDeadend(deadend)
		end
	end
end
--Secret
TryPlacingSecret()
if HasTrinket(TRINKET_FRAGMENTED_CARD) or HasItem(ITEM_LUNA) then
	TryPlacingSecret()
end
-- Grave Room
if StageId == 11 and StageType == 0 then --Dark Room
	PlaceGrave(DequeueDeadend())
end

Notes

  • The algorithm is from Blade's GitHub Gist, also known as blcd / Will. He reverse engineered the game using a disassembler in order to create the pseudo-code.
  • The second chances for certain types of rooms are separate, independent rolls: the probabilities are not added together directly.