Binding of Isaac: Rebirth Wiki
No edit summary
Tag: Visual edit
(extra library gen flag appears to never be set, reworded accordingly)
Line 34: Line 34:
 
* [[Dice_Room|Dice]] or [[Sacrifice Room]] (1/7 (~14%) base chance, plus an independent 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)
 
* [[Dice_Room|Dice]] or [[Sacrifice Room]] (1/7 (~14%) base chance, plus an independent 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 an independent 1/5 chance for a total of 27/125 (~22%) if Isaac has 2 or more keys.
 
** If a Sacrifice Room is successfully generated, it has a 1/50 base chance to become a Dice Room instead, plus an independent 1/5 chance for a total of 27/125 (~22%) if Isaac has 2 or more keys.
* [[Library]] (1/20 chance, plus an independent 1/4 chance for a total of 23/80 (~29%) if Isaac touched a [[book]] this run).
+
* [[Library]] (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 Room]] (1/2 chance, plus an independent 1/4 chance for a total of 5/8 (~63%) if Isaac has entered a [[Devil Room]] this run).
 
* [[Curse Room]] (1/2 chance, plus an independent 1/4 chance for a total of 5/8 (~63%) if Isaac has entered a [[Devil Room]] this run).
 
** An additional curse room is generated on each floor if Isaac has {{i|Voodoo Head}}
 
** An additional curse room is generated on each floor if Isaac has {{i|Voodoo Head}}

Revision as of 17:31, 11 January 2022

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 makes the floor much larger.

  • If the floor is not XL or (in Afterbirth † and Repentance)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.

Next, special rooms are generated in dead ends.

Special rooms generate in the following order:

  • Boss Room (always generates).
    • If it is an XL floor, two boss rooms generate back to back.
    • Multiple Boss Rooms are generated in The Void.
  • Super Secret Room (always generates).
    • Two super secret rooms generate if Isaac has (in Repentance)Collectible Luna iconLuna
  • Shop (always generates in the first 3 chapters, and on chapter 4 if Isaac has (in Afterbirth † and Repentance)Silver DollarSilver Dollar, or on chapter 5 if Isaac has (in Repentance)Holy CrownHoly Crown or (in Repentance)Wicked CrownWicked Crown).
  • Treasure Room (always generates in the first 3 chapters, and on chapter 4 if Isaac has (in Afterbirth † and Repentance)Bloody CrownBloody Crown, or on chapter 5 if Isaac has (in Repentance)Holy CrownHoly Crown or (in Repentance)Wicked CrownWicked Crown).
    • If it is an XL floor, two Treasure Rooms generate.
  • Dice or Sacrifice Room (1/7 (~14%) base chance, plus an independent 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 an independent 1/5 chance for a total of 27/125 (~22%) if Isaac has 2 or more keys.
  • Library (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 Room (1/2 chance, plus an independent 1/4 chance for a total of 5/8 (~63%) if Isaac has entered a Devil Room this run).
    • An additional curse room is generated on each floor if Isaac has (in Repentance)Collectible Voodoo Head iconVoodoo Head
  • Miniboss (1/4 chance, plus an independent 1/4 chance for a total of 7/16 (~44%) if it isn’t the first floor).
  • Challenge Room (1/2 chance if Isaac’s total health is equal to or greater than his total heart containers, can't spawn otherwise).
    • Cannot spawn on the first floor.
    • Will always be a Boss Challenge Room on the second floor of a chapter, and a normal Challenge Room otherwise.
  • Vault or Arcade (guaranteed if Isaac has 5 or more coins and it’s the second floor of a chapter, can’t spawn otherwise).
    • If an Arcade is successfully generated, it has a 1/10 chance to be a Vault instead, plus an independent 1/3 chance for a total of 2/5 (40%) if Isaac has 2 or more keys.
  • (in Repentance) Planetarium (base 1% chance to generate in Basement I - Depths II, 0% later, but skipping Treasure Rooms, several items and trinkets will modify this chance).
    • Note that the Planetariums are above only Bedrooms in priority of all the other room types they compete with, and may end up left out if the level layout has no space for them.
  • Bedroom (1/50 chance, plus an independent 1/5 chance for a total of 27/125 (~22%) if Isaac has less than 2 Red/Bone Hearts and no Soul Hearts, or 2 or fewer Soul Hearts and no Red/Bone Hearts)
    • Equal chance to be a clean or dirty Bedroom.
    • Can only spawn in the first 3 chapters.
  • Secret Room (guaranteed).
  • A Grave Room is placed if the floor is Dark Room.

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() & 3 == 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) then
	TryPlacingSecret()
end
-- Grave Room
if StageId == 11 and StageType == 0 then --Dark Room
	PlaceGrave(DequeueDeadend())
end

Notes

This is taken from Blade's GitHub Gist. (Blade is also known as blcd / Will.) He reverse engineered the game using a disassembler in order to create this pseudo-code.