From 76dd287a11501fa9ce6bec560de7201456b6f9a3 Mon Sep 17 00:00:00 2001 From: Ishaan Bhardwaj Date: Tue, 22 Dec 2020 22:09:17 -0500 Subject: [PATCH] h (v0.2.6) --- tetris/modes/demon_mode.lua | 2 +- tetris/modes/joker.lua | 2 +- tetris/modes/marathon_gf.lua | 10 +- tetris/modes/marathon_wcb.lua | 7 ++ tetris/modes/non.lua | 31 ++++- tetris/modes/pacer_test.lua | 177 ++++++++++++++++++++++++++ tetris/modes/race_40.lua | 2 +- tetris/modes/scoreattack_o.lua | 223 +++++++++++++++++++++++++++++++++ tetris/modes/speed.lua | 5 +- tetris/modes/survival_a2n.lua | 15 +++ tetris/randomizers/mirror.lua | 56 +++++++++ tetris/rulesets/cultris.lua | 2 +- tetris/rulesets/h.lua | 37 ++++++ tetris/rulesets/mizu_rs.lua | 150 ++++++++++++++++++++++ tetris/rulesets/super302.lua | 24 ++++ tetris/rulesets/thenext.lua | 2 +- 16 files changed, 729 insertions(+), 16 deletions(-) create mode 100644 tetris/modes/pacer_test.lua create mode 100644 tetris/modes/scoreattack_o.lua create mode 100644 tetris/modes/survival_a2n.lua create mode 100644 tetris/randomizers/mirror.lua create mode 100644 tetris/rulesets/h.lua create mode 100644 tetris/rulesets/mizu_rs.lua create mode 100644 tetris/rulesets/super302.lua diff --git a/tetris/modes/demon_mode.lua b/tetris/modes/demon_mode.lua index 4e6a918..893d203 100644 --- a/tetris/modes/demon_mode.lua +++ b/tetris/modes/demon_mode.lua @@ -26,7 +26,7 @@ function DemonModeGame:new() self.enable_hold = true self.lock_drop = true self.lock_hard_drop = true - self.next_queue_length = 3 + self.next_queue_length = 6 if math.random() < 1/6.66 then self.rpc_details = "Suffering" end diff --git a/tetris/modes/joker.lua b/tetris/modes/joker.lua index 1ced15b..9f03531 100644 --- a/tetris/modes/joker.lua +++ b/tetris/modes/joker.lua @@ -23,7 +23,7 @@ function JokerGame:new() self.lock_drop = true self.lock_hard_drop = true self.enable_hold = false - self.next_queue_length = 5 + self.next_queue_length = 6 end function JokerGame:getARE() return 16 end diff --git a/tetris/modes/marathon_gf.lua b/tetris/modes/marathon_gf.lua index 941225d..3bd10e8 100644 --- a/tetris/modes/marathon_gf.lua +++ b/tetris/modes/marathon_gf.lua @@ -25,7 +25,7 @@ function MarathonGFGame:new() self.instant_hard_drop = true self.instant_soft_drop = false self.enable_hold = true - self.next_queue_length = 5 + self.next_queue_length = 6 end function MarathonGFGame:getARE() return 6 end @@ -91,7 +91,7 @@ end function MarathonGFGame:updateScore(level, drop_bonus, cleared_lines) local normal_table = {[0] = 0, 1, 3, 5, 8} local spin_score = 4 * (cleared_lines + 1) - local all_clear_table = {8, 12, 18, 20} + local all_clear_table = {[0] = 0, 8, 12, 18, 20} if self.grid:checkForBravo(cleared_lines) then self.score = self.score + ( @@ -139,11 +139,15 @@ function MarathonGFGame:onAttemptPieceMove(piece) end function MarathonGFGame:onAttemptPieceRotate(piece) - if self.piece ~= nil and piece:isDropBlocked(self.grid) and + if self.piece ~= nil then + if piece:isDropBlocked(self.grid) and piece:isMoveBlocked(self.grid, { x=-1, y=0 }) and piece:isMoveBlocked(self.grid, { x=1, y=0 }) and piece:isMoveBlocked(self.grid, { x=0, y=-1 }) then piece.spin = true + else + piece.spin = false + end end end diff --git a/tetris/modes/marathon_wcb.lua b/tetris/modes/marathon_wcb.lua index 535ef23..500112f 100644 --- a/tetris/modes/marathon_wcb.lua +++ b/tetris/modes/marathon_wcb.lua @@ -28,6 +28,13 @@ function MarathonWCBGame:new() self.piece_is_active = false end +function MarathonWCBGame:initialize(ruleset) + self.super.initialize(self, ruleset) + ruleset.onPieceDrop = function() end + ruleset.onPieceMove = function() end + ruleset.onPieceRotate = function() end +end + function MarathonWCBGame:getDropSpeed() return 20 end diff --git a/tetris/modes/non.lua b/tetris/modes/non.lua index 4cb4e38..78ed7f8 100644 --- a/tetris/modes/non.lua +++ b/tetris/modes/non.lua @@ -1,5 +1,10 @@ require 'funcs' +bgm.non = { + start = love.audio.newSource("res/bgm/non-start.ogg", "stream"), + loop = love.audio.newSource("res/bgm/non-loop.ogg", "stream"), +} + local GameMode = require 'tetris.modes.gamemode' local Bag7NoSZOStartRandomizer = require 'tetris.randomizers.bag7noSZOstart' @@ -14,6 +19,7 @@ function NightOfNights:new() self.super:new() self.active_time = 0 + self.pieces = 0 self.randomizer = Bag7NoSZOStartRandomizer() @@ -22,7 +28,7 @@ function NightOfNights:new() self.instant_soft_drop = false self.instant_hard_drop = false self.enable_hold = true - self.next_queue_length = 3 + self.next_queue_length = 6 end function NightOfNights:getARE() return 0 end @@ -32,6 +38,19 @@ function NightOfNights:getDasLimit() return config.das end function NightOfNights:getARR() return config.arr end function NightOfNights:getGravity() return 20 end +function NightOfNights:advanceOneFrame() + if self.ready_frames == 0 then + if self.frames == 0 then + switchBGM("non", "start") + elseif self.frames == 1280 then + switchBGMLoop("non", "loop") + end + self.frames = self.frames + 1 + else + switchBGM(nil) + end +end + function NightOfNights:whilePieceActive() self.active_time = self.active_time + 1 if self.active_time >= 20 then self.piece.locked = true end @@ -40,6 +59,7 @@ end function NightOfNights:onPieceLock(piece, cleared_row_count) self.super:onPieceLock() self.active_time = 0 + self.pieces = self.pieces + 1 self.lines = self.lines + cleared_row_count end @@ -57,10 +77,12 @@ function NightOfNights:drawScoringInfo() strTrueValues(self.prev_inputs) ) love.graphics.printf("NEXT", 64, 40, 40, "left") - love.graphics.printf("LINES", 240, 200, 40, "left") + love.graphics.printf("LINES", 240, 160, 80, "left") + love.graphics.printf("PIECES", 240, 240, 80, "left") love.graphics.setFont(font_3x5_4) - love.graphics.printf(self.lines, 240, 220, 90, "left") + love.graphics.printf(self.lines, 240, 180, 90, "left") + love.graphics.printf(self.pieces, 240, 260, 90, "left") love.graphics.setFont(font_8x11) love.graphics.printf(formatTime(self.frames), 64, 420, 160, "center") @@ -72,7 +94,8 @@ end function NightOfNights:getHighscoreData() return { - level = self.level, + lines = self.lines, + pieces = self.pieces, frames = self.frames, } end diff --git a/tetris/modes/pacer_test.lua b/tetris/modes/pacer_test.lua new file mode 100644 index 0000000..533993e --- /dev/null +++ b/tetris/modes/pacer_test.lua @@ -0,0 +1,177 @@ +require 'funcs' + +local GameMode = require 'tetris.modes.gamemode' +local Piece = require 'tetris.components.piece' + +local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls' + +local PacerTest = GameMode:extend() + +PacerTest.name = "TetrisGramâ„¢ Pacer Test" +PacerTest.hash = "PacerTest" +PacerTest.tagline = "The FitnessGram Pacer Test is a multi-stage aerobic capacity test" + + + + +local function getLevelFrames(level) + if level == 1 then return 72 * 60 / 8.0 + else return 72 * 60 / (8.0 + level * 0.5) + end +end + +local level_end_sections = { + 7, 15, 23, 32, 41, 51, 61, 72, 83, 94, + 106, 118, 131, 144, 157, 171, 185, 200, + 215, 231, 247 +} + +function PacerTest:new() + PacerTest.super:new() + + self.ready_frames = 2430 + self.clear_frames = 0 + self.randomizer = History6RollsRandomizer() + + self.level = 1 + self.section = 0 + self.level_frames = 0 + + self.section_lines = 0 + self.section_clear = false + self.strikes = 0 + + self.lock_drop = true + self.lock_hard_drop = true + self.enable_hold = true + self.instant_hard_drop = true + self.instant_soft_drop = false + self.next_queue_length = 3 +end + +function PacerTest:initialize(ruleset) + self.super.initialize(self, ruleset) + self.level_frames = getLevelFrames(1) + switchBGM("pacer_test") +end + +function PacerTest:getARE() + return 0 +end + +function PacerTest:getARR() + return config.arr +end + +function PacerTest:getLineARE() + return 0 +end + +function PacerTest:getDasLimit() + return config.das +end + +function PacerTest:getLineClearDelay() + return 6 +end + +function PacerTest:getLockDelay() + return 30 +end + +function PacerTest:getGravity() + return 1/64 +end + +function PacerTest:getSection() + return math.floor(level / 100) + 1 +end + +function PacerTest:onPieceEnter() + self.irs = false + self.ihs = false +end + +function PacerTest:advanceOneFrame() + if self.clear then + self.clear_frames = self.clear_frames + 1 + if self.clear_frames > 600 then + self.completed = true + end + return false + elseif self.ready_frames == 0 then + self.frames = self.frames + 1 + self.level_frames = self.level_frames - 1 + if self.level_frames <= 0 then + self:checkSectionStatus() + self.section = self.section + 1 + if self.section >= level_end_sections[self.level] then + self.level = self.level + 1 + end + self.level_frames = self.level_frames + getLevelFrames(self.level) + end + end + return true +end + +function PacerTest:checkSectionStatus() + if self.section_clear then + self.strikes = 0 + self.section_clear = false + else + self.strikes = self.strikes + 1 + if self.strikes >= 2 then + self.game_over = true + fadeoutBGM(2.5) + end + end + self.section_lines = 0 +end + +function PacerTest:onLineClear(cleared_row_count) + self.section_lines = self.section_lines + cleared_row_count + if self.section_lines >= 3 then + self.section_clear = true + end +end + +function PacerTest:drawGrid(ruleset) + self.grid:draw() + if self.piece ~= nil then + self:drawGhostPiece(ruleset) + end +end + +function PacerTest:getHighscoreData() + return { + level = self.level, + frames = self.frames, + } +end + +function PacerTest:drawScoringInfo() + PacerTest.super.drawScoringInfo(self) + love.graphics.setColor(1, 1, 1, 1) + + local text_x = config["side_next"] and 320 or 240 + + love.graphics.setFont(font_3x5_2) + love.graphics.printf("NEXT", 64, 40, 40, "left") + love.graphics.printf("LINES", text_x, 224, 70, "left") + love.graphics.printf("LEVEL", text_x, 320, 40, "left") + + for i = 1, math.min(self.strikes, 3) do + love.graphics.draw(misc_graphics["strike"], text_x + (i - 1) * 30, 280) + end + + love.graphics.setFont(font_3x5_3) + love.graphics.printf(self.section_lines .. "/3", text_x, 244, 80, "left") + love.graphics.printf(self.level, text_x, 340, 40, "right") + love.graphics.printf(self.section, text_x, 370, 40, "right") +end + +function PacerTest:getBackground() + return math.min(self.level - 1, 19) +end + +return PacerTest diff --git a/tetris/modes/race_40.lua b/tetris/modes/race_40.lua index b5431ea..082829e 100644 --- a/tetris/modes/race_40.lua +++ b/tetris/modes/race_40.lua @@ -35,7 +35,7 @@ function Race40Game:new() self.instant_hard_drop = true self.instant_soft_drop = false self.enable_hold = true - self.next_queue_length = 3 + self.next_queue_length = 6 end function Race40Game:getDropSpeed() diff --git a/tetris/modes/scoreattack_o.lua b/tetris/modes/scoreattack_o.lua new file mode 100644 index 0000000..106e6ae --- /dev/null +++ b/tetris/modes/scoreattack_o.lua @@ -0,0 +1,223 @@ +require 'funcs' + +local GameMode = require 'tetris.modes.gamemode' +local Piece = require 'tetris.components.piece' + +local History4RollsRandomizer = require 'tetris.randomizers.bag7noSZOstart' + +local ArcadeScoreAttack = GameMode:extend() + +ArcadeScoreAttack.name = "Arcade Score Attack" +ArcadeScoreAttack.hash = "Oshisaure-ArcadeScoreAttack" +ArcadeScoreAttack.tagline = "Huge scores! How big can you make yours?" + + + +function ArcadeScoreAttack:new() + ArcadeScoreAttack.super:new() + + self.timeleft = 9000 + self.chain = 0 + self.quads = 0 + self.level = 1 + self.multiplier = 1 + self.b2b = false + + self.randomizer = History4RollsRandomizer() + + self.lock_drop = false + self.enable_hard_drop = true + self.enable_hold = true + self.next_queue_length = 5 +end + +function ArcadeScoreAttack:updateMultiplier() +end + +function ArcadeScoreAttack:getARE() + return 24 +end + +function ArcadeScoreAttack:getLineARE() + return 8 +end + +function ArcadeScoreAttack:getLineClearDelay() + return 16 +end + +function ArcadeScoreAttack:getLockDelay() + return 30 +end + +function ArcadeScoreAttack:getDasLimit() + return 12 +end + +function ArcadeScoreAttack:getARR() + return 1 +end + +local levelchanges = { + 5, --lv 1: 5 lines + 10, + 15, + 20, + 25, + 35, --lv 6: 10 lines + 45, + 55, + 65, + 75, + 90, --lv11: 15 lines + 115, + 130, + 145, + 160, --lv15: 20 lines + 180, + 200, + 220, + 250, + math.huge --lv20: infinite +} + +local gravitycurve = { + 1/60, --lv1 + 1/30, + 1/20, + 1/15, + 1/12, --lv5 + 1/10, + 1/ 6, + 1/ 4, + 1/ 3, + 1/ 2, --lv10 + 2/ 2, + 3/ 2, + 4/ 2, + 5/ 2, + 3/ 1, --lv15 + 4/ 1, + 5/ 1, + 7/ 1, + 10/ 1, + 20/ 1, --lv20 +} +function ArcadeScoreAttack:getGravity() + return gravitycurve[self.level] +end + +function ArcadeScoreAttack:advanceOneFrame() + if self.ready_frames == 0 then + self.score = self.score + self.multiplier + self.timeleft = self.timeleft-1 + if self.timeleft <= 0 then + self.game_over = true + end + self.frames = self.frames + 1 + end +end + +function ArcadeScoreAttack:onPieceEnter() +end + +function ArcadeScoreAttack:onLineClear(cleared_row_count) + self.lines = self.lines + cleared_row_count + if self.lines >= levelchanges[self.level] then + self.level = self.level + 1 + self.timeleft = self.timeleft + 1800 + end +end + +function ArcadeScoreAttack:updateScore(level, drop_bonus, cleared_lines) + local pts = 0 + if cleared_lines == 0 then + if not self.b2b then self.chain = 0 end + else + self.chain = self.chain + 1 + self.b2b = false + if cleared_lines >= 4 then + self.b2b = true + self.quads = self.quads + 1 + end + pts = 1000 + for i = 2, cleared_lines do pts = pts * i end + end + self.multiplier = self.level * (self.chain+1) * (self.quads+1) + if pts > 0 then + self.score = self.score + pts * self.multiplier + end +end + +function ArcadeScoreAttack:drawGrid() + self.grid:draw() + self:drawGhostPiece(ruleset) +end + +local function comma(score) + if score == 0 then return "0" end + local scorestr = "" + local p = 1 + for d = 0, math.log10(score) do + if d % 3 == 0 and d ~= 0 then scorestr = ","..scorestr end + local digit = math.floor(score/p)%10 + scorestr = digit..scorestr + p = p*10 + end + return scorestr +end + +function ArcadeScoreAttack:drawScoringInfo() + ArcadeScoreAttack.super.drawScoringInfo(self) + love.graphics.setColor(1, 1, 1, 1) + + love.graphics.setFont(font_3x5_2) + love.graphics.print( + self.das.direction .. " " .. + self.das.frames .. " " .. + strTrueValues(self.prev_inputs) + ) + love.graphics.printf("NEXT", 64, 40, 40, "left") + love.graphics.printf("SCORE", 240, 100, 40, "left") + love.graphics.printf("LINES", 240, 165, 40, "left") + love.graphics.printf("MULTIPLIER" , 240, 220, 153, "right") + love.graphics.printf("LEVEL" , 240, 240, 153, "left") + love.graphics.printf("QUADS x (1 + ", 240, 260, 160, "left") + love.graphics.printf("CHAIN x (1 + ", 240, 280, 160, "left") + love.graphics.printf("TOTAL =" , 240, 310, 153, "left") + love.graphics.printf("TIME REMAINING", 240, 350, 120, "left") + + love.graphics.printf(self.level .." ", 240, 240, 153, "right") + love.graphics.printf(self.quads ..")", 240, 260, 160, "right") + love.graphics.printf(self.chain ..")", 240, 280, 160, "right") + love.graphics.printf(self.multiplier.." ", 240, 310, 153, "right") + + love.graphics.setFont(font_3x5_3) + local li = levelchanges[self.level] + if li == math.huge then + love.graphics.printf(self.lines, 240, 190, 40, "left") + else + love.graphics.printf(self.lines.."/"..li, 240, 185, 100, "left") + end + love.graphics.printf(formatTime(self.timeleft), 240, 370, 150, "left") + + love.graphics.setFont(font_3x5_4) + love.graphics.printf(comma(self.score), 240, 120, 300, "left") + + love.graphics.setFont(font_8x11) + love.graphics.printf(formatTime(self.frames), 64, 420, 160, "center") +end + +function ArcadeScoreAttack:getBackground() + return self.level - 1 +end + +function ArcadeScoreAttack:getHighscoreData() + return { + score = self.score, + level = self.level, + frames = self.frames, + } +end + +return ArcadeScoreAttack diff --git a/tetris/modes/speed.lua b/tetris/modes/speed.lua index 8f254f4..2ee1dc9 100644 --- a/tetris/modes/speed.lua +++ b/tetris/modes/speed.lua @@ -25,10 +25,7 @@ function LudicrousSpeed:new() self.instant_soft_drop = false self.instant_hard_drop = true self.enable_hold = true - self.next_queue_length = 3 - - self.irs = false - self.ihs = false + self.next_queue_length = 6 end function LudicrousSpeed:getGravity() diff --git a/tetris/modes/survival_a2n.lua b/tetris/modes/survival_a2n.lua new file mode 100644 index 0000000..3c883a7 --- /dev/null +++ b/tetris/modes/survival_a2n.lua @@ -0,0 +1,15 @@ +local SurvivalA2Game = require 'tetris.modes.survival_a2' + +local SurvivalA2NGame = SurvivalA2Game:extend() + +SurvivalA2NGame.name = "Survival A2N" +SurvivalA2NGame.hash = "SurvivalA2N" +SurvivalA2NGame.tagline = "A variation of Survival A2 for Carnival of Derp." + +function SurvivalA2NGame:new() + self.super:new() + self.next_queue_length = 3 + self.enable_hold = true +end + +return SurvivalA2NGame \ No newline at end of file diff --git a/tetris/randomizers/mirror.lua b/tetris/randomizers/mirror.lua new file mode 100644 index 0000000..dfa88da --- /dev/null +++ b/tetris/randomizers/mirror.lua @@ -0,0 +1,56 @@ +local Randomizer = require 'tetris.randomizers.randomizer' + +local MirrorRandomizer = Randomizer:extend() + +function MirrorRandomizer:initialize() + self.mirror_state = false + self.total_pieces = 0 + self.piece_stack = {} + self.history = {"S", "Z"} + self.shapes = {"I", "J", "L", "O", "S", "T", "Z"} + self.mirrors = { + ["I"] = "O", + ["J"] = "L", + ["L"] = "J", + ["O"] = "I", + ["S"] = "Z", + ["T"] = "T", + ["Z"] = "S" + } +end + +function inHistory(piece, history) + for idx, entry in pairs(history) do + if entry == piece then + return true + end + end + return false +end + +function MirrorRandomizer:generatePiece() + local generated + + if self.mirror_state then + generated = table.remove(self.piece_stack) + else + repeat + generated = self.shapes[math.random(7)] + until not inHistory(generated, self.history) + table.remove(self.history, 1) + table.insert(self.history, generated) + table.insert(self.piece_stack, self.mirrors[generated]) + end + + self.total_pieces = self.total_pieces + 1 + + if self.total_pieces % 14 == 0 then + self.mirror_state = false + elseif self.total_pieces % 14 == 7 then + self.mirror_state = true + end + + return generated +end + +return MirrorRandomizer \ No newline at end of file diff --git a/tetris/rulesets/cultris.lua b/tetris/rulesets/cultris.lua index 0330c6d..2420a79 100644 --- a/tetris/rulesets/cultris.lua +++ b/tetris/rulesets/cultris.lua @@ -10,7 +10,7 @@ Cultris.colourscheme = { L = "M", J = "B", S = "C", - Z = "F", + Z = "X", O = "Y", T = "R", } diff --git a/tetris/rulesets/h.lua b/tetris/rulesets/h.lua new file mode 100644 index 0000000..fa971aa --- /dev/null +++ b/tetris/rulesets/h.lua @@ -0,0 +1,37 @@ +local SRS = require 'tetris.rulesets.standard_exp' + +local H = SRS:extend() + +H.name = "h" +H.hash = "h" +H.world = false + +function H: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 + 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 not(initial and self.enable_IRS_wallkicks == false) then + self:onPieceRotate(piece, grid) + piece:setRelativeRotation(rot_dir) + end +end + +function H:getDefaultOrientation() + return math.random(4) +end + +return H \ No newline at end of file diff --git a/tetris/rulesets/mizu_rs.lua b/tetris/rulesets/mizu_rs.lua new file mode 100644 index 0000000..8476622 --- /dev/null +++ b/tetris/rulesets/mizu_rs.lua @@ -0,0 +1,150 @@ +local Piece = require 'tetris.components.piece' +local Ruleset = require 'tetris.rulesets.ruleset' + +local MizuRS = Ruleset:extend() + +MizuRS.name = "Mizu Rotation" +MizuRS.hash = "MizuRS" + +MizuRS.softdrop_lock = false +MizuRS.harddrop_lock = true + +MizuRS.colourscheme = { + I = "R", + L = "O", + J = "C", + S = "G", + Z = "M", + O = "Y", + T = "B", +} + +MizuRS.spawn_positions = { + I = { x=5, y=2 }, + J = { x=4, y=3 }, + L = { x=4, y=3 }, + O = { x=5, y=3 }, + S = { x=4, y=3 }, + T = { x=4, y=3 }, + Z = { x=4, y=3 }, +} + +MizuRS.big_spawn_positions = { + I = { x=3, y=0 }, + J = { x=2, y=1 }, + L = { x=2, y=1 }, + O = { x=3, y=1 }, + S = { x=2, y=1 }, + T = { x=2, y=1 }, + Z = { x=2, y=1 }, +} + +MizuRS.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=0}, {x=0, y=0}, {x=0, y=-1}, {x=1, y=-1} }, + { {x=1, y=0}, {x=1, y=-1}, {x=0, y=-1}, {x=0, y=-2} }, + }, + 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=1, y=0}, {x=0, y=0}, {x=0, y=-1}, {x=-1, y=-1} }, + { {x=-1, y=0}, {x=-1, y=-1}, {x=0, y=-1}, {x=0, y=-2} }, + { {x=1, y=0}, {x=0, y=0}, {x=0, y=-1}, {x=-1, y=-1} }, + { {x=1, y=-2}, {x=1, y=-1}, {x=0, y=-1}, {x=0, y=0} }, + } +} + +MizuRS.wallkicks_cw = {{x=0, y=-1}, {x=0, y=-2}, {x=1, y=0}, {x=2, y=0}, {x=0, y=1}, {x=0, y=2}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=-1}, {x=2, y=-2}, {x=1, y=1}, {x=2, y=2}, {x=-1, y=1}, {x=-2, y=2}, {x=-1, y=-1}, {x=-2, y=-2}} +MizuRS.wallkicks_ccw = {{x=0, y=-1}, {x=0, y=-2}, {x=-1, y=0}, {x=-2, y=0}, {x=0, y=1}, {x=0, y=2}, {x=1, y=0}, {x=2, y=0}, {x=-1, y=-1}, {x=-2, y=-2}, {x=-1, y=1}, {x=-2, y=2}, {x=1, y=1}, {x=2, y=2}, {x=1, y=1}, {x=2, y=2}} + +function MizuRS:attemptWallkicks(piece, new_piece, rot_dir, grid) + local kicks + if piece.shape == "O" then + return + elseif rot_dir == 1 then + kicks = MizuRS.wallkicks_cw + else + kicks = MizuRS.wallkicks_ccw + 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 MizuRS:checkNewLow(piece) + for _, block in pairs(piece:getBlockOffsets()) do + local y = piece.position.y + block.y + if y > piece.lowest_y then + piece.ldincrease = 20 + piece.lock_delay = 0 + piece.lowest_y = y + end + end +end + +function MizuRS:onPieceCreate(piece, grid) + piece.ldincrease = 20 + piece.lowest_y = -math.huge +end + +function MizuRS:onPieceDrop(piece, grid) + self:checkNewLow(piece) +end + +function MizuRS:onPieceMove(piece, grid) + if piece:isDropBlocked(grid) then + piece.lock_delay = math.max((piece.lock_delay - piece.ldincrease), 0) + piece.ldincrease = piece.ldincrease - 1 + end +end + +function MizuRS:onPieceRotate(piece, grid) + if piece:isDropBlocked(grid) then + piece.lock_delay = math.max((piece.lock_delay - piece.ldincrease), 0) + piece.ldincrease = piece.ldincrease - 1 + end +end + +function MizuRS:getDefaultOrientation() return 3 end + +return MizuRS diff --git a/tetris/rulesets/super302.lua b/tetris/rulesets/super302.lua new file mode 100644 index 0000000..183fc6f --- /dev/null +++ b/tetris/rulesets/super302.lua @@ -0,0 +1,24 @@ +local ARS = require 'tetris.rulesets.arika' + +local BONKERS = ARS:extend() + +BONKERS.name = "SUPER302" +BONKERS.hash = "Super302" + +function BONKERS:attemptWallkicks(piece, new_piece, rot_dir, grid) + 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-100, y=y-100}) + end + end + end + -- don't ask + piece.position = {x=100, y=100} + piece.getBlockOffsets = function(piece) + return unfilled_block_offsets + end +end + +return BONKERS \ No newline at end of file diff --git a/tetris/rulesets/thenext.lua b/tetris/rulesets/thenext.lua index 4d462f3..867e93b 100644 --- a/tetris/rulesets/thenext.lua +++ b/tetris/rulesets/thenext.lua @@ -13,7 +13,7 @@ TheNext.colourscheme = { I = "C", J = "B", L = "M", - O = "A", + O = "X", S = "G", Z = "R", T = "Y"