-- 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
