cambridge-modpack/tetris/rulesets/krs.lua
2023-04-04 13:53:02 +07:00

182 lines
4.6 KiB
Lua

local SRS = require 'tetris.rulesets.standard_ti'
local KRS = SRS:extend()
KRS.name = "K.R.S."
KRS.hash = "KRS"
KRS.colourscheme = {
I = "M",
L = "R",
J = "C",
S = "O",
Z = "B",
O = "Y",
T = "G",
}
KRS.wallkicks_3x3 = {
[0]={
[1]={{-1,0},{-1,-1}},
[2]={{0,-1},{0,-2}},
[3]={{1,0},{1,-1}},
},
[1]={
[0]={{1,0},{1,1}},
[2]={{1,0},{1,-1}},
[3]={{1,0},{2,0}},
},
[2]={
[0]={{0,1},{0,2}},
[1]={{-1,0},{-1,1}},
[3]={{1,0},{1,1}},
},
[3]={
[0]={{-1,0},{-1,1}},
[1]={{-1,0},{-2,0}},
[2]={{-1,0},{-1,-1}},
},
}
KRS.wallkicks_line = {
[0]={
[1]={{-1,0},{-1,-1},{1,0},{1,1}},
[2]={{0,-1},{0,-2}},
[3]={{1,0},{1,-1},{-1,0},{-1,1}},
},
[1]={
[0]={{1,0},{1,1},{-1,0},{-1,-1}},
[2]={{1,0},{1,-1},{-1,0},{-1,1}},
[3]={{2,0}},
},
[2]={
[0]={{0,1},{0,2}},
[1]={{-1,0},{-1,1},{1,0},{1,-1}},
[3]={{1,0},{1,1},{-1,0},{-1,-1}},
},
[3]={
[0]={{-1,0},{-1,1},{1,0},{1,-1}},
[1]={{-2,0}},
[2]={{-1,0},{-1,-1},{1,0},{1,1}},
},
}
function KRS:onPieceCreate(piece)
piece.das_kicked = false
piece.recovery_frames = self.game:getLockDelay() * 15
end
function KRS:onPieceDrop() end
function KRS:onPieceMove(piece)
while piece.lock_delay > 0 and piece.recovery_frames > 0 do
piece.recovery_frames = piece.recovery_frames - 1
piece.lock_delay = piece.lock_delay - 1
end
end
function KRS:onPieceRotate(piece)
while piece.lock_delay > 0 and piece.recovery_frames > 0 do
piece.recovery_frames = piece.recovery_frames - 1
piece.lock_delay = piece.lock_delay - 1
end
end
function KRS:canPieceMove(piece) return not piece.das_kicked end
function KRS:canPieceRotate(piece) return true end
function KRS:attemptRotate(new_inputs, piece, grid, initial)
piece.das_kicked = false
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)
if initial then
if grid:canPlacePiece(new_piece) then
piece:setRelativeRotation(rot_dir)
self:onPieceRotate(piece)
end
else
self:attemptWallkicks(piece, new_piece, rot_dir, grid, new_inputs)
end
end
function KRS:attemptWallkicks(piece, new_piece, rot_dir, grid, new_inputs)
local kicks = (
piece.shape == "I" and
KRS.wallkicks_line[piece.rotation][new_piece.rotation] or
KRS.wallkicks_3x3[piece.rotation][new_piece.rotation]
)
local priority = 0
local das_charged = (
self.game.das.frames >= self.game:getDasLimit() - self.game:getARR()
)
if (
new_inputs.left or
(self.game.das.direction == "left" and
(das_charged or piece:isMoveBlocked(grid, {x=-1, y=0})))
) then
priority = -1
elseif (
new_inputs.right or
(self.game.das.direction == "right" and
(das_charged or piece:isMoveBlocked(grid, {x=1, y=0})))
) then
priority = 1
end
-- base rotation with offset
if grid:canPlacePiece(new_piece:withOffset({x=priority, y=0})) then
piece:setRelativeRotation(rot_dir)
piece:setOffset({x=priority, y=0})
self:onPieceRotate(piece)
piece.das_kicked = priority ~= 0
return
end
-- das kicks
for idx, offset in pairs(kicks) do
kicked_piece = new_piece:withOffset({x=offset[1]+priority, y=offset[2]})
if grid:canPlacePiece(kicked_piece) then
piece:setRelativeRotation(rot_dir)
piece:setOffset({x=offset[1]+priority, y=offset[2]})
self:onPieceRotate(piece)
piece.das_kicked = priority ~= 0
return
end
end
-- base rotation
if grid:canPlacePiece(new_piece) then
piece:setRelativeRotation(rot_dir)
self:onPieceRotate(piece)
return
end
-- regular kicks
for idx, offset in pairs(kicks) do
kicked_piece = new_piece:withOffset({x=offset[1], y=offset[2]})
if grid:canPlacePiece(kicked_piece) then
piece:setRelativeRotation(rot_dir)
piece:setOffset({x=offset[1], y=offset[2]})
self:onPieceRotate(piece)
return
end
end
end
function KRS:get180RotationValue() return 2 end
return KRS