diff --git a/tetris/rulesets/minote.lua b/tetris/rulesets/minote.lua new file mode 100644 index 0000000..c2c03b5 --- /dev/null +++ b/tetris/rulesets/minote.lua @@ -0,0 +1,189 @@ +local Ruleset = require 'tetris.rulesets.ruleset' + +local Minote = Ruleset:extend() + +Minote.name = "Minote" +Minote.hash = "Minote" + +Minote.block_offsets = { + J={ + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=-1, y=-2} }, + { {x=0, y=-1}, {x=1, y=-2}, {x=0, y=-2}, {x=0, y=0} }, + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=1, y=0} }, + { {x=0, y=-1}, {x=0, y=-2}, {x=0, y=0}, {x=-1, y=0} }, + }, + L={ + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=1, y=-2} }, + { {x=0, y=-2}, {x=0, y=-1}, {x=1, y=0}, {x=0, y=0} }, + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=-1, y=0} }, + { {x=0, y=-1}, {x=-1, y=-2}, {x=0, y=-2}, {x=0, y=0} }, + }, + O={ + { {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1}, {x=0, y=-1} }, + { {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1}, {x=0, y=-1} }, + { {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1}, {x=0, y=-1} }, + { {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1}, {x=0, y=-1} }, + }, + T={ + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=0, y=-2} }, + { {x=0, y=-1}, {x=0, y=0}, {x=1, y=-1}, {x=0, y=-2} }, + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=-1}, {x=0, y=0} }, + { {x=0, y=-1}, {x=0, y=0}, {x=-1, y=-1}, {x=0, y=-2} }, + }, + I={ + { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, + { {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=0, y=2} }, + { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, + { {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=0, y=2} }, + }, + S={ + { {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} }, + { {x=0, y=-2}, {x=0, y=-1}, {x=1, y=-1}, {x=1, y=0} }, + { {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} }, + { {x=0, y=-2}, {x=0, y=-1}, {x=1, y=-1}, {x=1, y=0} }, + }, + Z={ + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=0}, {x=0, y=0} }, + { {x=0, y=-1}, {x=0, y=0}, {x=1, y=-2}, {x=1, y=-1} }, + { {x=0, y=-1}, {x=-1, y=-1}, {x=1, y=0}, {x=0, y=0} }, + { {x=0, y=-1}, {x=0, y=0}, {x=1, y=-2}, {x=1, y=-1} }, + } +} + +Minote.spawn_positions = { + I = { x=5, y=4 }, + J = { x=4, y=5 }, + L = { x=4, y=5 }, + O = { x=5, y=5 }, + S = { x=4, y=5 }, + T = { x=4, y=5 }, + Z = { x=4, y=5 }, +} + +Minote.big_spawn_positions = { + I = { x=3, y=2 }, + J = { x=2, y=3 }, + L = { x=2, y=3 }, + O = { x=3, y=3 }, + S = { x=2, y=3 }, + T = { x=2, y=3 }, + Z = { x=2, y=3 }, +} + +function Minote:new() + Ruleset:new() + self.last_direction = 1 -- 1 is right, -1 is left +end + +Minote.kicks = {{0,1},{1,0},{-1,0},{1,1},{-1,1}} + +function Minote:attemptRotate(new_inputs, piece, grid, initial) + -- last direction check + if new_inputs["right"] then + self.last_direction = 1 + elseif new_inputs["left"] then + self.last_direction = -1 + end + + local rot_dir = 0 + + if (new_inputs["rotate_left"] or new_inputs["rotate_left2"]) then + rot_dir = 3 + elseif (new_inputs["rotate_right"] or new_inputs["rotate_right2"]) then + rot_dir = 1 + elseif (new_inputs["rotate_180"]) then + rot_dir = self:get180RotationValue() + end + + if rot_dir == 0 then return end + if config.gamesettings.world_reverse == 3 or (self.world and config.gamesettings.world_reverse == 2) then + rot_dir = 4 - rot_dir + end + + local new_piece = piece:withRelativeRotation(rot_dir) + + self:attemptWallkicks(piece, new_piece, rot_dir, grid, initial) +end + +function Minote:attemptWallkicks(piece, new_piece, rot_dir, grid, initial) + -- piece drift calculation + local drift + if (piece.shape == "S" or piece.shape == "Z" or piece.shape == "I") then + if (new_piece.rotation % 2 == 0 and rot_dir == 1) then + drift = 1 + elseif (new_piece.rotation % 2 == 1 and rot_dir == 3) then + drift = -1 + else + drift = 0 + end + else + drift = 0 + end + + -- base rotation + drift + if grid:canPlacePiece(new_piece:withOffset({x=drift, y=0})) then + piece:setRelativeRotation(rot_dir) + piece:setOffset({x=drift, y=0}) + self:onPieceRotate(piece) + return + end + + -- I, IRS don't kick + if (piece.shape == "I") or initial then return end + + -- J, L, T floorkick + if ( + (piece.shape == "J" or piece.shape == "L" or piece.shape == "T") and + piece.rotation == 0 and + grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) + ) then + piece:setRelativeRotation(rot_dir) + piece:setOffset({x=0, y=-1}) + self:onPieceRotate(piece) + return + end + + for idx, kick in pairs(Minote.kicks) do + -- kick calculation + offset = { + x = kick[1] * self.last_direction + drift, + y = kick[2] + } + + kicked_piece = new_piece:withOffset(offset) + if grid:canPlacePiece(kicked_piece) then + piece:setRelativeRotation(rot_dir) + piece:setOffset(offset) + self:onPieceRotate(piece) + return + end + end +end + +function Minote:checkNewLow(piece) + for _, block in pairs(piece:getBlockOffsets()) do + local y = piece.position.y + block.y + if y > piece.lowest_y then + piece.lock_delay = 0 + piece.lowest_y = y + end + end +end + +function Minote:onPieceCreate(piece) + piece.lowest_y = -math.huge +end + +function Minote:onPieceDrop(piece) + self:checkNewLow(piece) +end + +function Minote:onPieceRotate(piece) + self:checkNewLow(piece) +end + +function Minote:get180RotationValue() return 3 end + +function Minote:getDefaultOrientation() return 3 end -- downward facing pieces by default + +return Minote \ No newline at end of file diff --git a/tetris/rulesets/randompieces.lua b/tetris/rulesets/randompieces.lua index c81601e..b0021f2 100644 --- a/tetris/rulesets/randompieces.lua +++ b/tetris/rulesets/randompieces.lua @@ -58,49 +58,7 @@ RandomPieces.block_offsets = { } } -function RandomPieces:initializePiece( - inputs, data, grid, gravity, prev_inputs, - move, lock_delay, drop_speed, - drop_locked, hard_drop_locked, big, irs, - buffer_hard_drop, buffer_soft_drop, - lock_on_hard_drop, lock_on_soft_drop -) - local spawn_positions - if big then - spawn_positions = self.big_spawn_positions - else - spawn_positions = self.spawn_positions - end - local colours = ({self.colourscheme, ColourSchemes.Arika, ColourSchemes.TTC})[config.gamesettings.piece_colour] - - local spawn_x - if (grid.width ~= 10) then - local percent = spawn_positions[data.shape].x / 10 - for i = 0, grid.width - 1 do - if i / grid.width >= percent then - spawn_x = i - break - end - end - end - - local spawn_dy - if (config.gamesettings.spawn_positions == 1) then - spawn_dy = ( - self.spawn_above_field and 2 or 0 - ) - else - spawn_dy = ( - config.gamesettings.spawn_positions == 3 and - 2 or 0 - ) - end - - local piece = Piece(data.shape, data.orientation - 1, { - x = spawn_x and spawn_x or spawn_positions[data.shape].x, - y = spawn_positions[data.shape].y - spawn_dy - }, self.block_offsets, 0, 0, data.skin, colours[data.shape], big) - +function RandomPieces:onPieceCreate(piece) local offsets = self:generateBlockOffsets() piece.getBlockOffsets = function() return offsets @@ -147,23 +105,6 @@ function RandomPieces:initializePiece( end return piece end - - self:onPieceCreate(piece) - if irs then - self:rotatePiece(inputs, piece, grid, {}, true) - if (data.orientation - 1) ~= piece.rotation then - playSE("irs") - end - end - self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked) - if (buffer_hard_drop and config.gamesettings.buffer_lock == 1) then - piece:dropToBottom(grid) - if lock_on_hard_drop then piece.locked = true end - end - if (buffer_soft_drop and lock_on_soft_drop and piece:isDropBlocked(grid) and config.gamesettings.buffer_lock == 1) then - piece.locked = true - end - return piece end function RandomPieces:attemptRotate(new_inputs, piece, grid, initial)