mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-05-13 20:21:25 -05:00
First bundled release.
This commit is contained in:
98
tetris/rulesets/arika.lua
Normal file
98
tetris/rulesets/arika.lua
Normal file
@@ -0,0 +1,98 @@
|
||||
local Piece = require 'tetris.components.piece'
|
||||
local Ruleset = require 'tetris.rulesets.ruleset'
|
||||
|
||||
local ARS = Ruleset:extend()
|
||||
|
||||
ARS.name = "Classic ARS"
|
||||
ARS.hash = "Arika"
|
||||
|
||||
ARS.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 },
|
||||
}
|
||||
|
||||
ARS.block_offsets = {
|
||||
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} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {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=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=-2}, {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0} },
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=-2}, {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {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} },
|
||||
},
|
||||
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} },
|
||||
}
|
||||
}
|
||||
|
||||
function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
-- I and O don't kick
|
||||
if (piece.shape == "I" or piece.shape == "O") then return end
|
||||
|
||||
-- center column rule
|
||||
if (
|
||||
piece.shape == "J" or piece.shape == "T" or piece.shape == "L"
|
||||
) and (
|
||||
piece.rotation == 0 or piece.rotation == 2
|
||||
) and (
|
||||
grid:isOccupied(piece.position.x, piece.position.y) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 1) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 2)
|
||||
) then return end
|
||||
|
||||
-- kick right, kick left
|
||||
if (grid:canPlacePiece(new_piece:withOffset({x=1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
elseif (grid:canPlacePiece(new_piece:withOffset({x=-1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ARS:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function ARS:get180RotationValue() return config["reverse_rotate"] and 1 or 3 end
|
||||
function ARS:getDefaultOrientation() return 3 end -- downward facing pieces by default
|
||||
|
||||
return ARS
|
||||
132
tetris/rulesets/arika_ti.lua
Normal file
132
tetris/rulesets/arika_ti.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
local Piece = require 'tetris.components.piece'
|
||||
local Ruleset = require 'tetris.rulesets.ruleset'
|
||||
|
||||
local ARS = Ruleset:extend()
|
||||
|
||||
ARS.name = "Ti-ARS"
|
||||
ARS.hash = "ArikaTI"
|
||||
|
||||
ARS.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 },
|
||||
}
|
||||
|
||||
ARS.block_offsets = {
|
||||
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} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {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=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=-2}, {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0} },
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=-2}, {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {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} },
|
||||
},
|
||||
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} },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-- Component functions.
|
||||
|
||||
function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
-- O doesn't kick
|
||||
if (piece.shape == "O") then return end
|
||||
|
||||
-- center column rule
|
||||
if (
|
||||
piece.shape == "J" or piece.shape == "T" or piece.shape == "L"
|
||||
) and (
|
||||
piece.rotation == 0 or piece.rotation == 2
|
||||
) and (
|
||||
grid:isOccupied(piece.position.x, piece.position.y) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 1) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 2)
|
||||
) then return end
|
||||
|
||||
if piece.shape == "I" then
|
||||
-- special kick rules for I
|
||||
if new_piece.rotation == 0 or new_piece.rotation == 2 then
|
||||
-- kick right, right2, left
|
||||
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=2, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=2, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
end
|
||||
elseif piece:isDropBlocked(grid) and (new_piece.rotation == 1 or new_piece.rotation == 3) and piece.floorkick == 0 then
|
||||
-- kick up, up2
|
||||
if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece.floorkick = 1
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2})
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece.floorkick = 1
|
||||
end
|
||||
end
|
||||
elseif piece.shape ~= "I" then
|
||||
-- kick right, kick left
|
||||
if (grid:canPlacePiece(new_piece:withOffset({x=1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||
elseif (grid:canPlacePiece(new_piece:withOffset({x=-1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
|
||||
end
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ARS:onPieceCreate(piece, grid)
|
||||
piece.floorkick = 0
|
||||
end
|
||||
|
||||
function ARS:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function ARS:get180RotationValue() return config["reverse_rotate"] and 1 or 3 end
|
||||
function ARS:getDefaultOrientation() return 3 end -- downward facing pieces by default
|
||||
|
||||
return ARS
|
||||
102
tetris/rulesets/bonkers.lua
Normal file
102
tetris/rulesets/bonkers.lua
Normal file
@@ -0,0 +1,102 @@
|
||||
Piece = require("tetris.components.piece")
|
||||
|
||||
local BONKERS = {}
|
||||
|
||||
BONKERS.name = "B.O.N.K.E.R.S."
|
||||
BONKERS.hash = "Bonkers"
|
||||
|
||||
BONKERS.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 },
|
||||
}
|
||||
|
||||
BONKERS.block_offsets = {
|
||||
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=1}, {x=-1, y=1}, {x=-2, y=1}, {x=1, y=1} },
|
||||
{ {x=-1, y=0}, {x=-1, y=-1}, {x=-1, y=1}, {x=-1, y=2} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1} , {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=1} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=-1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=-1} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=-1, y=-1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=0} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=0} },
|
||||
},
|
||||
Z={
|
||||
{ {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
}
|
||||
}
|
||||
|
||||
-- Component functions.
|
||||
|
||||
function BONKERS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
if piece.shape == "O" then
|
||||
break
|
||||
elseif piece.shape == "I" then
|
||||
horizontal_kicks = {0, 1, -1, 2, -2}
|
||||
else
|
||||
horizontal_kicks = {0, 1, -1}
|
||||
end
|
||||
|
||||
for y_offset = 20, new_piece.position.y - 24, -1 do
|
||||
for idx, x_offset in pairs(horizontal_kicks) do
|
||||
local offset = {x=x_offset, y=y_offset}
|
||||
kicked_piece = new_piece:withOffset(offset)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(offset)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function BONKERS:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function BONKERS:onPieceMove(piece, grid)
|
||||
piece.lock_delay = 0 -- move reset
|
||||
end
|
||||
|
||||
function BONKERS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
end
|
||||
|
||||
return BONKERS
|
||||
410
tetris/rulesets/cambridge.lua
Normal file
410
tetris/rulesets/cambridge.lua
Normal file
@@ -0,0 +1,410 @@
|
||||
local Piece = require 'tetris.components.piece'
|
||||
local Ruleset = require 'tetris.rulesets.ruleset'
|
||||
|
||||
local CRS = Ruleset:extend()
|
||||
|
||||
CRS.name = "Cambridge"
|
||||
CRS.hash = "Cambridge"
|
||||
|
||||
CRS.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=4 },
|
||||
T = { x=4, y=5 },
|
||||
Z = { x=4, y=4 },
|
||||
}
|
||||
|
||||
CRS.block_offsets = {
|
||||
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=1}, {x=-1, y=1}, {x=-2, y=1}, {x=1, y=1} },
|
||||
{ {x=-1, y=0}, {x=-1, y=-1}, {x=-1, y=1}, {x=-1, y=2} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1} , {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=1} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=-1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=-1} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
S={
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=0, y=1}, {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=0, y=1}, {x=0, y=0}, {x=-1, y=0}, {x=-1, y=-1} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=0} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=0} },
|
||||
},
|
||||
Z={
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
}
|
||||
}
|
||||
|
||||
CRS.wallkicks = {
|
||||
I={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
[2]={{x=0, y=0}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}, {x=-1, y=0}, {x=2, y=0}, {x=-1, y=1}, {x=2, y=1}},
|
||||
[3]={{x=0, y=0}},
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}, {x=-1, y=0}, {x=2, y=0}, {x=-1, y=1}, {x=2, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[0]={{x=0, y=0}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}, {x=1, y=0}, {x=-2, y=0}, {x=1, y=1}, {x=-2, y=1}},
|
||||
[1]={{x=0, y=0}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}, {x=1, y=0}, {x=-2, y=0}, {x=1, y=1}, {x=-2, y=1}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
[2]={{x=0, y=0}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}, {x=-1, y=0}, {x=2, y=0}, {x=-1, y=1}, {x=2, y=1}},
|
||||
[3]={{x=0, y=0}},
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}, {x=-1, y=0}, {x=2, y=0}, {x=-1, y=1}, {x=2, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[0]={{x=0, y=0}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}, {x=1, y=0}, {x=-2, y=0}, {x=1, y=1}, {x=-2, y=1}},
|
||||
[1]={{x=0, y=0}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}, {x=1, y=0}, {x=-2, y=0}, {x=1, y=1}, {x=-2, y=1}},
|
||||
},
|
||||
},
|
||||
},
|
||||
J={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=-1}, {x=-1, y=-1}, {x=0, y=0}, {x=-1, y=0}}, -- allows for the "J situp"
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=-1}, {x=1, y=-1}, {x=0, y=0}, {x=1, y=0}},
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[0]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=-1, y=1}, {x=1, y=0}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=1, y=1}, {x=-1, y=0}},
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=1, y=0}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=-1, y=0}, {x=1, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=1, y=0}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=1, y=0}},
|
||||
},
|
||||
},
|
||||
},
|
||||
L={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=-1}, {x=-1, y=-1}, {x=0, y=0}, {x=-1, y=0}},
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=-1}, {x=1, y=-1}, {x=0, y=0}, {x=1, y=0}}, -- allows for the "L situp"
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=-1, y=0}, {x=1, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=1, y=0}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=1, y=0}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=-1, y=0}, {x=1, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=1, y=0}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=1, y=0}},
|
||||
},
|
||||
},
|
||||
},
|
||||
S={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=-1, y=0}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[3]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=-1, y=0}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[1]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=-1, y=0}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[3]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
[3]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
},
|
||||
},
|
||||
},
|
||||
T={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=1, y=0}}, -- prioritizes the nub T spin over the regular T spin
|
||||
[2]={{x=0, y=0}, {x=1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=1}, {x=-1, y=1}, {x=0, y=0}, {x=-1, y=0}}, -- prioritizes the nub T spin over the regular T spin
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=0, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=1}, {x=-1, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=0}, {x=1, y=0}, {x=0, y=-1}, {x=1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=0, y=1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=0}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Z={
|
||||
[true] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=1, y=0}},
|
||||
[2]={{x=0, y=0}, {x=1, y=1}},
|
||||
[3]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=1, y=0}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=-1, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=1, y=1}},
|
||||
[1]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=1, y=0}},
|
||||
[3]={{x=0, y=1}, {x=1, y=1}, {x=0, y=0}, {x=1, y=0}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
},
|
||||
},
|
||||
[false] = {
|
||||
[0]={
|
||||
[1]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=1, y=1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[3]={{x=0, y=0}, {x=-1, y=1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=0}, {x=1, y=1}},
|
||||
[1]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
[3]={{x=0, y=0}, {x=1, y=0}, {x=0, y=1}, {x=1, y=1}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
[1]={{x=0, y=0}, {x=-1, y=1}},
|
||||
[2]={{x=0, y=0}, {x=-1, y=0}, {x=0, y=-1}, {x=-1, y=-1}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
function CRS:attemptRotate(new_inputs, piece, grid, initial)
|
||||
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
|
||||
|
||||
local new_piece = piece:withRelativeRotation(rot_dir)
|
||||
self:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
end
|
||||
|
||||
|
||||
function CRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
if piece.shape == "O" then return end
|
||||
|
||||
local kicks = CRS.wallkicks[piece.shape][piece:isDropBlocked(grid)][piece.rotation][new_piece.rotation]
|
||||
|
||||
assert(piece.rotation ~= new_piece.rotation)
|
||||
|
||||
for idx, offset in pairs(kicks) do
|
||||
kicked_piece = new_piece:withOffset(offset)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(offset)
|
||||
self:onPieceRotate(piece, grid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function CRS:onPieceCreate(piece, grid)
|
||||
piece.rotate_counter = 0
|
||||
piece.move_counter = 0
|
||||
end
|
||||
|
||||
function CRS:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function CRS:onPieceMove(piece, grid)
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.move_counter = piece.move_counter + 1
|
||||
if piece.move_counter >= 24 then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CRS:onPieceRotate(piece, grid)
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.rotate_counter = piece.rotate_counter + 1
|
||||
if piece.rotate_counter >= 12 then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CRS:getDefaultOrientation() return 1 end -- downward facing pieces by default
|
||||
|
||||
return CRS
|
||||
135
tetris/rulesets/ruleset.lua
Normal file
135
tetris/rulesets/ruleset.lua
Normal file
@@ -0,0 +1,135 @@
|
||||
local Object = require 'libs.classic'
|
||||
local Piece = require 'tetris.components.piece'
|
||||
|
||||
local Ruleset = Object:extend()
|
||||
|
||||
Ruleset.name = ""
|
||||
Ruleset.hash = ""
|
||||
|
||||
Ruleset.enable_IRS_wallkicks = false
|
||||
|
||||
-- Component functions.
|
||||
|
||||
function Ruleset:rotatePiece(inputs, piece, grid, prev_inputs, initial)
|
||||
local new_inputs = {}
|
||||
|
||||
for input, value in pairs(inputs) do
|
||||
if value and not prev_inputs[input] then
|
||||
new_inputs[input] = true
|
||||
end
|
||||
end
|
||||
|
||||
self:attemptRotate(new_inputs, piece, grid, initial)
|
||||
|
||||
-- prev_inputs becomes the previous inputs
|
||||
for input, value in pairs(inputs) do
|
||||
prev_inputs[input] = inputs[input]
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:attemptRotate(new_inputs, piece, grid, initial)
|
||||
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
|
||||
|
||||
local new_piece = piece:withRelativeRotation(rot_dir)
|
||||
|
||||
if (grid:canPlacePiece(new_piece)) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
self:onPieceRotate(piece, grid)
|
||||
else
|
||||
if not(initial and self.enable_IRS_wallkicks == false) then
|
||||
self:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
-- do nothing in default ruleset
|
||||
end
|
||||
|
||||
function Ruleset:movePiece(piece, grid, move)
|
||||
local x = piece.position.x
|
||||
if move == "left" then
|
||||
piece:moveInGrid({x=-1, y=0}, 1, grid)
|
||||
elseif move == "speedleft" then
|
||||
piece:moveInGrid({x=-1, y=0}, 10, grid)
|
||||
elseif move == "right" then
|
||||
piece:moveInGrid({x=1, y=0}, 1, grid)
|
||||
elseif move == "speedright" then
|
||||
piece:moveInGrid({x=1, y=0}, 10, grid)
|
||||
end
|
||||
if piece.position.x ~= x then
|
||||
self:onPieceMove(piece, grid)
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked, hard_drop_enabled)
|
||||
local y = piece.position.y
|
||||
if inputs["down"] == true and drop_locked == false then
|
||||
piece:addGravity(gravity + drop_speed, grid)
|
||||
elseif inputs["up"] == true and hard_drop_enabled == true then
|
||||
if hard_drop_locked == true or piece:isDropBlocked(grid) then
|
||||
piece:addGravity(gravity, grid)
|
||||
else
|
||||
piece:dropToBottom(grid)
|
||||
end
|
||||
else
|
||||
piece:addGravity(gravity, grid)
|
||||
end
|
||||
if piece.position.y ~= y then
|
||||
self:onPieceDrop(piece, grid)
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:lockPiece(piece, grid, lock_delay)
|
||||
if piece:isDropBlocked(grid) and piece.gravity >= 1 and piece.lock_delay >= lock_delay then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||
function Ruleset:get180RotationValue() return 2 end
|
||||
function Ruleset:getDefaultOrientation() return 1 end
|
||||
|
||||
function Ruleset:initializePiece(
|
||||
inputs, data, grid, gravity, prev_inputs,
|
||||
move, lock_delay, drop_speed,
|
||||
drop_locked, hard_drop_locked
|
||||
)
|
||||
local piece = Piece(data.shape, data.orientation - 1, {
|
||||
x = self.spawn_positions[data.shape].x,
|
||||
y = self.spawn_positions[data.shape].y
|
||||
}, self.block_offsets, 0, 0, data.skin)
|
||||
self:onPieceCreate(piece)
|
||||
self:rotatePiece(inputs, piece, grid, {}, true)
|
||||
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked)
|
||||
return piece
|
||||
end
|
||||
|
||||
-- stuff like move count, rotate count, floorkick count go here
|
||||
function Ruleset:onPieceCreate(piece) end
|
||||
|
||||
function Ruleset:processPiece(
|
||||
inputs, piece, grid, gravity, prev_inputs,
|
||||
move, lock_delay, drop_speed,
|
||||
drop_locked, hard_drop_locked, hard_drop_enabled
|
||||
)
|
||||
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
||||
self:movePiece(piece, grid, move)
|
||||
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked, hard_drop_enabled)
|
||||
self:lockPiece(piece, grid, lock_delay)
|
||||
end
|
||||
|
||||
function Ruleset:onPieceMove(piece) end
|
||||
function Ruleset:onPieceRotate(piece) end
|
||||
function Ruleset:onPieceDrop(piece) end
|
||||
|
||||
return Ruleset
|
||||
168
tetris/rulesets/standard_exp.lua
Normal file
168
tetris/rulesets/standard_exp.lua
Normal file
@@ -0,0 +1,168 @@
|
||||
local Piece = require 'tetris.components.piece'
|
||||
local Ruleset = require 'tetris.rulesets.ruleset'
|
||||
|
||||
local SRS = Ruleset:extend()
|
||||
|
||||
SRS.name = "SRS"
|
||||
SRS.hash = "Standard"
|
||||
|
||||
SRS.enable_IRS_wallkicks = true
|
||||
|
||||
SRS.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 },
|
||||
}
|
||||
|
||||
SRS.block_offsets = {
|
||||
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=1}, {x=-1, y=1}, {x=-2, y=1}, {x=1, y=1} },
|
||||
{ {x=-1, y=0}, {x=-1, y=-1}, {x=-1, y=1}, {x=-1, y=2} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1} , {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=1} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=-1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=-1} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=-1, y=-1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=0} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=0} },
|
||||
},
|
||||
Z={
|
||||
{ {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
}
|
||||
}
|
||||
|
||||
SRS.wallkicks_3x3 = {
|
||||
[0]={
|
||||
[1]={{x=-1, y=0}, {x=-1, y=-1}, {x=0, y=2}, {x=-1, y=2}},
|
||||
[2]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[3]={{x=1, y=0}, {x=1, y=-1}, {x=0, y=2}, {x=1, y=2}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=1, y=0}, {x=1, y=1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[2]={{x=1, y=0}, {x=1, y=1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[3]={{x=0, y=1}, {x=0, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[1]={{x=-1, y=0}, {x=-1, y=-1}, {x=0, y=2}, {x=-1, y=2}},
|
||||
[3]={{x=1, y=0}, {x=1, y=-1}, {x=0, y=2}, {x=1, y=2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=-1, y=0}, {x=-1, y=1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
[1]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=-1, y=0}, {x=-1, y=1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
},
|
||||
};
|
||||
|
||||
SRS.wallkicks_line = {
|
||||
[0]={
|
||||
[1]={{x=-2, y=0}, {x=1, y=0}, {x=-2, y=1}, {x=1, y=-2}},
|
||||
[2]={},
|
||||
[3]={{x=-1, y=0}, {x=2, y=0}, {x=-1, y=-2}, {x=2, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=2, y=0}, {x=-1, y=0}, {x=2, y=-1}, {x=-1, y=2}},
|
||||
[2]={{x=-1, y=0}, {x=2, y=0}, {x=-1, y=-2}, {x=2, y=1}},
|
||||
[3]={{x=0, y=1}, {x=0, y=-1}, {x=0, y=2}, {x=0, y=-2}},
|
||||
},
|
||||
[2]={
|
||||
[0]={},
|
||||
[1]={{x=1, y=0}, {x=-2, y=0}, {x=1, y=2}, {x=-2, y=-1}},
|
||||
[3]={{x=2, y=0}, {x=-1, y=0}, {x=2, y=-1}, {x=-1, y=2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=1, y=0}, {x=-2, y=0}, {x=1, y=2}, {x=-2, y=-1}},
|
||||
[1]={{x=0, y=1}, {x=0, y=-1}, {x=0, y=2}, {x=0, y=-2}},
|
||||
[2]={{x=-2, y=0}, {x=1, y=0}, {x=-2, y=1}, {x=1, y=-2}},
|
||||
},
|
||||
};
|
||||
|
||||
-- Component functions.
|
||||
|
||||
function SRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
local kicks
|
||||
if piece.shape == "O" then
|
||||
return
|
||||
elseif piece.shape == "I" then
|
||||
kicks = SRS.wallkicks_line[piece.rotation][new_piece.rotation]
|
||||
else
|
||||
kicks = SRS.wallkicks_3x3[piece.rotation][new_piece.rotation]
|
||||
end
|
||||
|
||||
assert(piece.rotation ~= new_piece.rotation)
|
||||
|
||||
for idx, offset in pairs(kicks) do
|
||||
kicked_piece = new_piece:withOffset(offset)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(offset)
|
||||
self:onPieceRotate(piece, grid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SRS:onPieceCreate(piece, grid)
|
||||
piece.rotate_counter = 0
|
||||
piece.move_counter = 0
|
||||
end
|
||||
|
||||
function SRS:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function SRS:onPieceMove(piece, grid)
|
||||
piece.lock_delay = 0 -- move reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.move_counter = piece.move_counter + 1
|
||||
if piece.move_counter >= 24 then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.rotate_counter = piece.rotate_counter + 1
|
||||
if piece.rotate_counter >= 12 then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return SRS
|
||||
133
tetris/rulesets/tengen.lua
Normal file
133
tetris/rulesets/tengen.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
local Piece = require 'tetris.components.piece'
|
||||
local Ruleset = require 'tetris.rulesets.ruleset'
|
||||
|
||||
local Tengen = Ruleset:extend()
|
||||
|
||||
Tengen.name = "Tengen"
|
||||
Tengen.hash = "Tengen"
|
||||
|
||||
Tengen.spawn_positions = {
|
||||
I = { x=3, y=4 },
|
||||
J = { x=4, y=4 },
|
||||
L = { x=4, y=4 },
|
||||
O = { x=5, y=4 },
|
||||
S = { x=4, y=4 },
|
||||
T = { x=4, y=4 },
|
||||
Z = { x=4, y=4 },
|
||||
}
|
||||
|
||||
Tengen.block_offsets = {
|
||||
I={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=2, y=1} },
|
||||
{ {x=1, y=0}, {x=1, y=1}, {x=1, y=2}, {x=0, y=2} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=1, y=1}, {x=2, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=1, y=0} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=1, y=2} },
|
||||
{ {x=2, y=0}, {x=0, y=1}, {x=1, y=1}, {x=2, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=1, y=1}, {x=1, y=2} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
-- up to here
|
||||
S={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
},
|
||||
Z={
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=2}, {x=0, y=3} },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-- Component functions.
|
||||
|
||||
function Tengen:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
-- O doesn't kick
|
||||
if (piece.shape == "O") then return end
|
||||
|
||||
-- center column rule
|
||||
if (
|
||||
piece.shape == "J" or piece.shape == "T" or piece.shape == "L"
|
||||
) and (
|
||||
piece.rotation == 0 or piece.rotation == 2
|
||||
) and (
|
||||
grid:isOccupied(piece.position.x, piece.position.y) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 1) or
|
||||
grid:isOccupied(piece.position.x, piece.position.y - 2)
|
||||
) then return end
|
||||
|
||||
if piece.shape == "I" then
|
||||
-- special kick rules for I
|
||||
if new_piece.rotation == 0 or new_piece.rotation == 2 then
|
||||
-- kick right, right2, left
|
||||
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=2, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=2, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
|
||||
self:onPieceRotate(piece, grid)
|
||||
end
|
||||
elseif piece:isDropBlocked(grid) and (new_piece.rotation == 1 or new_piece.rotation == 3) and piece.floorkick == 0 then
|
||||
-- kick up, up2
|
||||
if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece.floorkick = 1
|
||||
elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2})
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece.floorkick = 1
|
||||
end
|
||||
end
|
||||
elseif piece.shape ~= "I" then
|
||||
-- kick right, kick left
|
||||
if (grid:canPlacePiece(new_piece:withOffset({x=1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
|
||||
elseif (grid:canPlacePiece(new_piece:withOffset({x=-1, y=0}))) then
|
||||
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
|
||||
end
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Tengen:onPieceCreate(piece, grid)
|
||||
piece.floorkick = 0
|
||||
end
|
||||
|
||||
function Tengen:onPieceDrop(piece, grid)
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
|
||||
function Tengen:get180RotationValue() return config["reverse_rotate"] and 1 or 3 end
|
||||
function Tengen:getDefaultOrientation() return 3 end -- downward facing pieces by default
|
||||
|
||||
return Tengen
|
||||
235
tetris/rulesets/unrefactored_rulesets/shirase.lua
Normal file
235
tetris/rulesets/unrefactored_rulesets/shirase.lua
Normal file
@@ -0,0 +1,235 @@
|
||||
Piece = require("tetris.components.piece")
|
||||
require("funcs")
|
||||
|
||||
local SRS = {}
|
||||
|
||||
SRS.name = "SHIRASE"
|
||||
SRS.hash = "Shirase"
|
||||
|
||||
SRS.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 },
|
||||
}
|
||||
|
||||
SRS.block_offsets = {
|
||||
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=1}, {x=-1, y=1}, {x=-2, y=1}, {x=1, y=1} },
|
||||
{ {x=-1, y=0}, {x=-1, y=-1}, {x=-1, y=1}, {x=-1, y=2} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1} , {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=1} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=-1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=-1} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=-1, y=-1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=0} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=0} },
|
||||
},
|
||||
Z={
|
||||
{ {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
}
|
||||
}
|
||||
|
||||
SRS.wallkicks_3x3 = {
|
||||
[0]={
|
||||
[1]={{x=-1, y=0}, {x=-1, y=-1}, {x=0, y=2}, {x=-1, y=2}},
|
||||
[2]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[3]={{x=1, y=0}, {x=1, y=-1}, {x=0, y=2}, {x=1, y=2}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=1, y=0}, {x=1, y=1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[2]={{x=1, y=0}, {x=1, y=1}, {x=0, y=-2}, {x=1, y=-2}},
|
||||
[3]={{x=0, y=1}, {x=0, y=-1}},
|
||||
},
|
||||
[2]={
|
||||
[0]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[1]={{x=-1, y=0}, {x=-1, y=-1}, {x=0, y=2}, {x=-1, y=2}},
|
||||
[3]={{x=1, y=0}, {x=1, y=-1}, {x=0, y=2}, {x=1, y=2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=-1, y=0}, {x=-1, y=1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
[1]={{x=0, y=1}, {x=0, y=-1}},
|
||||
[2]={{x=-1, y=0}, {x=-1, y=1}, {x=0, y=-2}, {x=-1, y=-2}},
|
||||
},
|
||||
};
|
||||
|
||||
SRS.wallkicks_line = {
|
||||
[0]={
|
||||
[1]={{x=-2, y=0}, {x=1, y=0}, {x=-2, y=1}, {x=1, y=-2}},
|
||||
[2]={},
|
||||
[3]={{x=-1, y=0}, {x=2, y=0}, {x=-1, y=-2}, {x=2, y=1}},
|
||||
},
|
||||
[1]={
|
||||
[0]={{x=2, y=0}, {x=-1, y=0}, {x=2, y=-1}, {x=-1, y=2}},
|
||||
[2]={{x=-1, y=0}, {x=2, y=0}, {x=-1, y=-2}, {x=2, y=1}},
|
||||
[3]={{x=0, y=1}, {x=0, y=-1}, {x=0, y=2}, {x=0, y=-2}},
|
||||
},
|
||||
[2]={
|
||||
[0]={},
|
||||
[1]={{x=1, y=0}, {x=-2, y=0}, {x=1, y=2}, {x=-2, y=-1}},
|
||||
[3]={{x=2, y=0}, {x=-1, y=0}, {x=2, y=-1}, {x=-1, y=2}},
|
||||
},
|
||||
[3]={
|
||||
[0]={{x=1, y=0}, {x=-2, y=0}, {x=1, y=2}, {x=-2, y=-1}},
|
||||
[1]={{x=0, y=1}, {x=0, y=-1}, {x=0, y=2}, {x=0, y=-2}},
|
||||
[2]={{x=-2, y=0}, {x=1, y=0}, {x=-2, y=1}, {x=1, y=-2}},
|
||||
},
|
||||
};
|
||||
|
||||
local basicOffsets = {
|
||||
[0] = { x = 1, y = 0 },
|
||||
[1] = { x = 0, y = 1 },
|
||||
[2] = { x = -1, y = 0 },
|
||||
[3] = { x = 0, y = -1 }
|
||||
}
|
||||
|
||||
-- Component functions.
|
||||
|
||||
local function rotatePiece(inputs, piece, grid, prev_inputs)
|
||||
local new_inputs = {}
|
||||
|
||||
for input, value in pairs(inputs) do
|
||||
if value and not prev_inputs[input] then
|
||||
new_inputs[input] = true
|
||||
end
|
||||
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 = 2
|
||||
end
|
||||
|
||||
while rot_dir ~= 0 do
|
||||
rotated_piece = piece:withRelativeRotation(rot_dir)
|
||||
rotation_offset = vAdd(
|
||||
basicOffsets[piece.rotation],
|
||||
vNeg(basicOffsets[rotated_piece.rotation])
|
||||
)
|
||||
new_piece = rotated_piece:withOffset(rotation_offset)
|
||||
|
||||
if (grid:canPlacePiece(new_piece)) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(rotation_offset)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
break
|
||||
end
|
||||
|
||||
if piece.shape == "I" then
|
||||
kicks = SRS.wallkicks_line[piece.rotation][new_piece.rotation]
|
||||
else
|
||||
kicks = SRS.wallkicks_3x3[piece.rotation][new_piece.rotation]
|
||||
end
|
||||
|
||||
for idx, offset in pairs(kicks) do
|
||||
kicked_piece = new_piece:withOffset(offset)
|
||||
if grid:canPlacePiece(kicked_piece) then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece:setOffset(vAdd(offset, rotation_offset))
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
rot_dir = 0
|
||||
end
|
||||
if rot_dir == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
rot_dir = 0
|
||||
end
|
||||
|
||||
-- prev_inputs becomes the previous inputs
|
||||
for input, value in pairs(inputs) do
|
||||
prev_inputs[input] = inputs[input]
|
||||
end
|
||||
end
|
||||
|
||||
local function movePiece(piece, grid, move)
|
||||
if move == "left" then
|
||||
if not piece:isMoveBlocked(grid, {x=-1, y=0}) then
|
||||
piece.lock_delay = 0 -- move reset
|
||||
end
|
||||
piece:moveInGrid({x=-1, y=0}, 1, grid)
|
||||
elseif move == "right" then
|
||||
if not piece:isMoveBlocked(grid, {x=1, y=0}) then
|
||||
piece.lock_delay = 0 -- move reset
|
||||
end
|
||||
piece:moveInGrid({x=1, y=0}, 1, grid)
|
||||
end
|
||||
end
|
||||
|
||||
local function dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
local y = piece.position.y
|
||||
if inputs["down"] == true and drop_locked == false then
|
||||
piece:addGravity(gravity + 1, grid):lockIfBottomed(grid)
|
||||
elseif inputs["up"] == true then
|
||||
if piece:isDropBlocked(grid) then
|
||||
return
|
||||
end
|
||||
piece:dropToBottom(grid)
|
||||
else
|
||||
piece:addGravity(gravity, grid)
|
||||
end
|
||||
if piece.position.y ~= y then -- step reset
|
||||
piece.lock_delay = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function lockPiece(piece, grid, lock_delay)
|
||||
if piece:isDropBlocked(grid) and piece.lock_delay >= lock_delay then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||
function SRS.initializePiece(inputs, data, grid, gravity, prev_inputs, move, lock_delay, drop_speed, drop_locked)
|
||||
local piece = Piece(shape, 0, {
|
||||
x = SRS.spawn_positions[shape].x,
|
||||
y = SRS.spawn_positions[shape].y
|
||||
}, SRS.block_offsets, 0, 0)
|
||||
-- have to copy that object otherwise it gets referenced
|
||||
rotatePiece(inputs, piece, grid, {})
|
||||
dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
return piece
|
||||
end
|
||||
|
||||
function SRS.processPiece(inputs, piece, grid, gravity, prev_inputs, move, lock_delay, drop_speed, drop_locked)
|
||||
rotatePiece(inputs, piece, grid, prev_inputs)
|
||||
movePiece(piece, grid, move)
|
||||
dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
lockPiece(piece, grid, lock_delay)
|
||||
end
|
||||
|
||||
return SRS
|
||||
174
tetris/rulesets/unrefactored_rulesets/super302.lua
Normal file
174
tetris/rulesets/unrefactored_rulesets/super302.lua
Normal file
@@ -0,0 +1,174 @@
|
||||
Piece = require("tetris.components.piece")
|
||||
|
||||
local BONKERS = {}
|
||||
|
||||
BONKERS.name = "SUPER302"
|
||||
BONKERS.hash = "Super302"
|
||||
|
||||
BONKERS.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 },
|
||||
}
|
||||
|
||||
BONKERS.block_offsets = {
|
||||
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=1}, {x=-1, y=1}, {x=-2, y=1}, {x=1, y=1} },
|
||||
{ {x=-1, y=0}, {x=-1, y=-1}, {x=-1, y=1}, {x=-1, y=2} },
|
||||
},
|
||||
J={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=-1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1} , {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=1} },
|
||||
},
|
||||
L={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=1, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=1} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=-1, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=-1} },
|
||||
},
|
||||
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} },
|
||||
},
|
||||
S={
|
||||
{ {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=1, y=1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
{ {x=-1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=-1, y=-1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
},
|
||||
T={
|
||||
{ {x=0, y=0}, {x=-1, y=0}, {x=1, y=0}, {x=0, y=-1} },
|
||||
{ {x=0, y=0}, {x=0, y=-1}, {x=0, y=1}, {x=1, y=0} },
|
||||
{ {x=0, y=0}, {x=1, y=0}, {x=-1, y=0}, {x=0, y=1} },
|
||||
{ {x=0, y=0}, {x=0, y=1}, {x=0, y=-1}, {x=-1, y=0} },
|
||||
},
|
||||
Z={
|
||||
{ {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=0}, {x=1, y=0} },
|
||||
{ {x=1, y=-1}, {x=1, y=0}, {x=0, y=0}, {x=0, y=1} },
|
||||
{ {x=1, y=1}, {x=0, y=1}, {x=0, y=0}, {x=-1, y=0} },
|
||||
{ {x=-1, y=1}, {x=-1, y=0}, {x=0, y=0}, {x=0, y=-1} },
|
||||
}
|
||||
}
|
||||
|
||||
-- Component functions.
|
||||
|
||||
local function rotatePiece(inputs, piece, grid, prev_inputs)
|
||||
local new_inputs = {}
|
||||
|
||||
for input, value in pairs(inputs) do
|
||||
if value and not prev_inputs[input] then
|
||||
new_inputs[input] = true
|
||||
end
|
||||
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 = 2
|
||||
end
|
||||
|
||||
while rot_dir ~= 0 do
|
||||
if piece.filled then break end
|
||||
|
||||
new_piece = piece:withRelativeRotation(rot_dir)
|
||||
|
||||
if (grid:canPlacePiece(new_piece)) and piece.shape ~= "O" then
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
else
|
||||
-- set the piece to occupy the whole grid
|
||||
piece.filled = true
|
||||
unfilled_block_offsets = {}
|
||||
for y = 4, 23 do
|
||||
for x = 0, 9 do
|
||||
if not grid:isOccupied(x, y) then
|
||||
table.insert(unfilled_block_offsets, {x=x, y=y})
|
||||
end
|
||||
end
|
||||
end
|
||||
piece.position = {x=0, y=0}
|
||||
piece.getBlockOffsets = function(piece)
|
||||
return unfilled_block_offsets
|
||||
end
|
||||
piece.isDropBlocked = function(piece)
|
||||
return true
|
||||
end
|
||||
end
|
||||
rot_dir = 0
|
||||
end
|
||||
|
||||
-- prev_inputs becomes the previous inputs
|
||||
for input, value in pairs(inputs) do
|
||||
prev_inputs[input] = inputs[input]
|
||||
end
|
||||
end
|
||||
|
||||
local function movePiece(piece, grid, move)
|
||||
if move == "left" then
|
||||
if not piece:isMoveBlocked(grid, {x=-1, y=0}) then
|
||||
piece.lock_delay = 0 -- move reset
|
||||
end
|
||||
piece:moveInGrid({x=-1, y=0}, 1, grid)
|
||||
elseif move == "right" then
|
||||
if not piece:isMoveBlocked(grid, {x=1, y=0}) then
|
||||
piece.lock_delay = 0 -- move reset
|
||||
end
|
||||
piece:moveInGrid({x=1, y=0}, 1, grid)
|
||||
end
|
||||
end
|
||||
|
||||
local function dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
local y = piece.position.y
|
||||
if inputs["down"] == true and drop_locked == false then
|
||||
piece:addGravity(gravity + 1, grid):lockIfBottomed(grid)
|
||||
elseif inputs["up"] == true then
|
||||
if piece:isDropBlocked(grid) then
|
||||
return
|
||||
end
|
||||
piece:dropToBottom(grid)
|
||||
else
|
||||
piece:addGravity(gravity, grid)
|
||||
end
|
||||
if piece.position.y ~= y then -- step reset
|
||||
piece.lock_delay = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function lockPiece(piece, grid, lock_delay)
|
||||
if piece:isDropBlocked(grid) and piece.lock_delay >= lock_delay then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||
function BONKERS.initializePiece(inputs, data, grid, gravity, prev_inputs, move, lock_delay, drop_speed, drop_locked)
|
||||
local piece = Piece(shape, 0, {
|
||||
x = BONKERS.spawn_positions[shape].x,
|
||||
y = BONKERS.spawn_positions[shape].y
|
||||
}, BONKERS.block_offsets, 0, 0)
|
||||
-- have to copy that object otherwise it gets referenced
|
||||
rotatePiece(inputs, piece, grid, {})
|
||||
dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
return piece
|
||||
end
|
||||
|
||||
function BONKERS.processPiece(inputs, piece, grid, gravity, prev_inputs, move, lock_delay, drop_speed, drop_locked)
|
||||
rotatePiece(inputs, piece, grid, prev_inputs)
|
||||
movePiece(piece, grid, move)
|
||||
dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked)
|
||||
lockPiece(piece, grid, lock_delay)
|
||||
end
|
||||
|
||||
return BONKERS
|
||||
Reference in New Issue
Block a user