fixed issue with 100% and Best Ending producing the same results with the same seed.

also made it more efficient.
This commit is contained in:
HapaxL 2021-03-02 01:54:05 +01:00
parent 0a12d846c5
commit 67bf6706fc

View file

@ -67,7 +67,7 @@ function C:randomize()
self:_logSettings() self:_logSettings()
local seed = self:_seedRngesus() local seed = self:_seedRngesus(self.obj) -- append obj string in order to shuffle differently depending on the objective
self:_updateSharecode(seed) self:_updateSharecode(seed)
local tscFiles = self:_createTscFiles(dirStage) local tscFiles = self:_createTscFiles(dirStage)
@ -117,9 +117,9 @@ function C:_mountDirectory(path)
return true, dirStage return true, dirStage
end end
function C:_seedRngesus() function C:_seedRngesus(suffix)
local seedstring = self.customseed or tostring(os.time()) local seedstring = self.customseed or tostring(os.time())
local seed = ld.encode('string', 'hex', ld.hash('sha256', seedstring)) local seed = ld.encode('string', 'hex', ld.hash('sha256', seedstring .. suffix))
local s1 = tonumber(seed:sub(-8, -1), 16) -- first 32 bits (from right) local s1 = tonumber(seed:sub(-8, -1), 16) -- first 32 bits (from right)
local s2 = tonumber(seed:sub(-16, -9), 16) -- next 32 bits local s2 = tonumber(seed:sub(-16, -9), 16) -- next 32 bits
@ -157,14 +157,6 @@ function C:getObjective()
end end
function C:_shuffleItems(tscFiles) function C:_shuffleItems(tscFiles)
-- ensure unique randomization between settings with the same seed
local function shuffle(t)
if self.obj == "objBadEnd" then return _.shuffle(_.shuffle(t)) end
if self.obj == "objNormalEnd" then return _.shuffle(_.shuffle(_.shuffle(t))) end
if self.obj == "objAllBosses" then return _.shuffle(_.shuffle(_.shuffle(_.shuffle(t)))) end
return _.shuffle(t)
end
local obj = self:getObjective()[1] local obj = self:getObjective()[1]
obj.name = obj.name .. (", %s"):format(self.worldGraph.spawn) obj.name = obj.name .. (", %s"):format(self.worldGraph.spawn)
obj.script = obj.script .. self.worldGraph:getSpawnScript() obj.script = obj.script .. self.worldGraph:getSpawnScript()
@ -175,10 +167,10 @@ function C:_shuffleItems(tscFiles)
if self.worldGraph:StartPoint() then if self.worldGraph:StartPoint() then
-- first, fill one of the first cave spots with a weapon that can break blocks -- first, fill one of the first cave spots with a weapon that can break blocks
_.shuffle(self.worldGraph:getFirstCaveSpots())[1]:setItem(shuffle(self.itemDeck:getItemsByAttribute("weaponSN"))[1]) _.shuffle(self.worldGraph:getFirstCaveSpots())[1]:setItem(_.shuffle(self.itemDeck:getItemsByAttribute("weaponSN"))[1])
elseif self.worldGraph:Camp() then elseif self.worldGraph:Camp() then
-- give Dr. Gero a strong weapon... you'll need it -- give Dr. Gero a strong weapon... you'll need it
self.worldGraph:getCamp()[1]:setItem(shuffle(self.itemDeck:getItemsByAttribute("weaponStrong"))[1]) self.worldGraph:getCamp()[1]:setItem(_.shuffle(self.itemDeck:getItemsByAttribute("weaponStrong"))[1])
-- and some HP once you fight your way past the first few enemies -- and some HP once you fight your way past the first few enemies
self.worldGraph:getCamp()[2]:setItem(self.itemDeck:getByKey("capsule5G")) self.worldGraph:getCamp()[2]:setItem(self.itemDeck:getByKey("capsule5G"))
end end
@ -188,27 +180,27 @@ function C:_shuffleItems(tscFiles)
self.worldGraph:getMALCO()[1]:setItem(self.itemDeck:getByKey("bomb")) self.worldGraph:getMALCO()[1]:setItem(self.itemDeck:getByKey("bomb"))
end end
local mandatory = _.compact(shuffle(self.itemDeck:getMandatoryItems(true))) local mandatory = _.compact(_.shuffle(self.itemDeck:getMandatoryItems(true)))
local optional = _.compact(shuffle(self.itemDeck:getOptionalItems(true))) local optional = _.compact(_.shuffle(self.itemDeck:getOptionalItems(true)))
local puppies = _.compact(shuffle(self.itemDeck:getItemsByAttribute("puppy"))) local puppies = _.compact(_.shuffle(self.itemDeck:getItemsByAttribute("puppy")))
if not self.puppy then if not self.puppy then
-- then fill puppies, for normal gameplay -- then fill puppies, for normal gameplay
self:_fastFillItems(puppies, shuffle(self.worldGraph:getPuppySpots())) self:_fastFillItems(puppies, _.shuffle(self.worldGraph:getPuppySpots()))
else else
-- for puppysanity, shuffle puppies in with the mandatory items -- for puppysanity, shuffle puppies in with the mandatory items
mandatory = shuffle(_.append(mandatory, puppies)) mandatory = _.shuffle(_.append(mandatory, puppies))
puppies = {} puppies = {}
end end
-- next fill hell chests, which cannot have mandatory items -- next fill hell chests, which cannot have mandatory items
self:_fastFillItems(optional, shuffle(self.worldGraph:getHellSpots())) self:_fastFillItems(optional, _.shuffle(self.worldGraph:getHellSpots()))
-- add map system AFTER filling hell chests so that it gets placed somewhere accessible in every objective -- add map system AFTER filling hell chests so that it gets placed somewhere accessible in every objective
optional = _.append(optional, self.itemDeck:getByKey("mapSystem")) optional = _.append(optional, self.itemDeck:getByKey("mapSystem"))
-- place mandatory items with assume fill -- place mandatory items with assume fill
self:_fillItems(mandatory, shuffle(_.reverse(self.worldGraph:getEmptyLocations()))) self:_fillItems(mandatory, _.shuffle(_.reverse(self.worldGraph:getEmptyLocations())))
-- place optional items with a simple random fill -- place optional items with a simple random fill
local opt = #optional local opt = #optional
@ -216,7 +208,7 @@ function C:_shuffleItems(tscFiles)
if opt > loc then if opt > loc then
logWarning(("Trying to fill more optional items than there are locations! Items: %d Locations: %d"):format(opt, loc)) logWarning(("Trying to fill more optional items than there are locations! Items: %d Locations: %d"):format(opt, loc))
end end
self:_fastFillItems(optional, shuffle(self.worldGraph:getEmptyLocations())) self:_fastFillItems(optional, _.shuffle(self.worldGraph:getEmptyLocations()))
self:_generateHints() self:_generateHints()
if tscFiles ~= nil then if tscFiles ~= nil then