Merge pull request #3 from nathyong/feature/nathyong/tetrax-randomizer
Add the Tetra Legends Tetra-X randomizerpull/4/head
commit
4ca4a4a52e
|
@ -0,0 +1,72 @@
|
|||
-- A randomizer based on Tetra Legends' "Tetra-X" game mode
|
||||
-- There are two main rules:
|
||||
-- * if piece hasn't been generated for 13+ pieces, force it
|
||||
-- * if piece has been generated in the last two pieces, don't give it out
|
||||
--
|
||||
-- The official implementation also has self-balancing functionality (bias
|
||||
-- towards pieces that have appeared less often).
|
||||
|
||||
local Randomizer = require 'tetris.randomizers.randomizer'
|
||||
|
||||
local TetraXRandomizer = Randomizer:extend()
|
||||
|
||||
function TetraXRandomizer:initialize()
|
||||
local pieces = {"I", "J", "L", "O", "S", "T", "Z"}
|
||||
|
||||
self.count = {}
|
||||
self.lastseen = {}
|
||||
self.totalcount = 0
|
||||
self.pieceselection = pieces
|
||||
|
||||
for _, piece in ipairs(pieces) do
|
||||
self.count[piece] = 0
|
||||
self.lastseen[piece] = -1 -- use -1 as magic value for "not seen"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function TetraXRandomizer:generatePiece()
|
||||
local generated = nil
|
||||
while true do
|
||||
generated = self.pieceselection[math.random(#self.pieceselection)]
|
||||
if not (self.lastseen[generated] == 0 or self.lastseen[generated] == 1) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- piece has not been generated in the last 13+
|
||||
for piece, val in pairs(self.lastseen) do
|
||||
if val >= 13 then
|
||||
generated = piece
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
for piece, val in pairs(self.lastseen) do
|
||||
if piece == generated then
|
||||
self.lastseen[piece] = 0
|
||||
else
|
||||
if val ~= -1 then
|
||||
self.lastseen[piece] = val + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.count[generated] = self.count[generated] + 1
|
||||
self.totalcount = self.totalcount + 1
|
||||
|
||||
-- shuffle the piece selection for the next time
|
||||
self.pieceselection = {}
|
||||
for piece, count in pairs(self.count) do
|
||||
-- in this case 6 = #piece types - 1, so all probabilities sum to 1
|
||||
local probability = (self.totalcount - count) / (self.totalcount * 6)
|
||||
local chances = math.floor(probability * 1000 + 0.5) -- simulated "round"
|
||||
for _ = 1, chances do
|
||||
table.insert(self.pieceselection, piece)
|
||||
end
|
||||
end
|
||||
|
||||
return generated
|
||||
end
|
||||
|
||||
return TetraXRandomizer
|
Loading…
Reference in New Issue