From c8665d06f03859e6916129e0ece21fb5d1940e0d Mon Sep 17 00:00:00 2001 From: SweetSea <106439598+SweetSea-ButImNotSweet@users.noreply.github.com> Date: Sat, 26 Oct 2024 23:29:10 +0700 Subject: [PATCH] First commit --- game/gamemode.lua | 4 +- game/rotation_big.lua | 474 ++++++++++++++++++++++++++++++++++++++++++ scene/game.lua | 4 +- 3 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 game/rotation_big.lua diff --git a/game/gamemode.lua b/game/gamemode.lua index 0319304..62f8db1 100644 --- a/game/gamemode.lua +++ b/game/gamemode.lua @@ -13,7 +13,7 @@ local GameMode = Object:extend() function GameMode:new(player_name, input_file, replay_grade) VCTRL.toggle(MOBILE and not input_file and not SETTINGS.tvMode) VCTRL.reset() - + if player_name == nil then self.training = true else self.training = false end if input_file ~= nil then input_file = love.filesystem.read(REPLAY_DIR..input_file) @@ -59,7 +59,7 @@ function GameMode:new(player_name, input_file, replay_grade) self.did_grades = false self.active_frames = 0 self.total_lines = 0 - self.lineClearPoints = {[0]=0, 0, 1667, 3750, 6668, 8335} + self.lineClearPoints = {[0]=0, 0, 1667, 3750, 6668, 8335, 10418, 13336, 15003, 17086} self.gradeNames = { "19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k", "10k", "9k", "8k", "7k", "6k", "5k", "4k", "3k", "2k", "1k", diff --git a/game/rotation_big.lua b/game/rotation_big.lua new file mode 100644 index 0000000..a7323a6 --- /dev/null +++ b/game/rotation_big.lua @@ -0,0 +1,474 @@ +local Object = require 'libs.classic' +local Piece = require 'game.piece' + +local Rotation = Object:extend() + +Rotation.spawn_positions = { + I = { x=2, y= 0 }, + J = { x=2, y= 0 }, + L = { x=2, y= 0 }, + O = { x=2, y= 0 }, + S = { x=2, y= 0 }, + T = { x=2, y= 0 }, + Z = { x=2, y= 0 }, +} + +Rotation.colourscheme = { + I = "R", + L = "O", + J = "B", + S = "M", + Z = "G", + O = "Y", + T = "C", +} + +local a = { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, {x=6, y=0}, {x=7, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, {x=6, y=1}, {x=7, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3}, + {x=0, y=4}, {x=1, y=4}, {x=2, y=4}, {x=3, y=4}, {x=4, y=4}, {x=5, y=4}, {x=6, y=4}, {x=7, y=4}, + {x=0, y=5}, {x=1, y=5}, {x=2, y=5}, {x=3, y=5}, {x=4, y=5}, {x=5, y=5}, {x=6, y=5}, {x=7, y=5}, + {x=0, y=6}, {x=1, y=6}, {x=2, y=6}, {x=3, y=6}, {x=4, y=6}, {x=5, y=6}, {x=6, y=6}, {x=7, y=6}, + {x=0, y=7}, {x=1, y=7}, {x=2, y=7}, {x=3, y=7}, {x=4, y=7}, {x=5, y=7}, {x=6, y=7}, {x=7, y=7}, +} + +Rotation.block_offsets = { + I={ + { + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3}, + }, + { + {x=4, y=0}, {x=5, y=0}, + {x=4, y=1}, {x=5, y=1}, + {x=4, y=2}, {x=5, y=2}, + {x=4, y=3}, {x=5, y=3}, + {x=4, y=4}, {x=5, y=4}, + {x=4, y=5}, {x=5, y=5}, + {x=4, y=6}, {x=5, y=6}, + {x=4, y=7}, {x=5, y=7}, + }, + { + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3}, + }, + { + {x=4, y=0}, {x=5, y=0}, + {x=4, y=1}, {x=5, y=1}, + {x=4, y=2}, {x=5, y=2}, + {x=4, y=3}, {x=5, y=3}, + {x=4, y=4}, {x=5, y=4}, + {x=4, y=5}, {x=5, y=5}, + {x=4, y=6}, {x=5, y=6}, + {x=4, y=7}, {x=5, y=7}, + }, + }, + J={ + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=4, y=2}, {x=5, y=2}, + {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, + {x=2, y=3}, {x=3, y=3}, + {x=0, y=4}, {x=1, y=4}, {x=2, y=4}, {x=3, y=4}, + {x=0, y=5}, {x=1, y=5}, {x=2, y=5}, {x=3, y=5}, + }, + { + {x=0, y=0}, {x=1, y=0}, + {x=0, y=1}, {x=1, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, + {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + }, + L={ + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=0, y=2}, {x=1, y=2}, + {x=0, y=3}, {x=1, y=3}, + }, + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, + {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + { + {x=4, y=0}, {x=5, y=0}, + {x=4, y=1}, {x=5, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, + {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, {x=4, y=4}, {x=5, y=4}, + {x=2, y=5}, {x=3, y=5}, {x=4, y=5}, {x=5, y=5}, + }, + }, + O={ + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + }, + S={ + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=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}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + { + {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=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}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + }, + T={ + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, + {x=2, y=2}, {x=3, y=2}, + {x=2, y=3}, {x=3, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + {x=2, y=4}, {x=3, y=4}, + {x=2, y=5}, {x=3, y=5}, + }, + }, + Z={ + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, + {x=0, y=4}, {x=1, y=4}, + {x=0, y=5}, {x=1, y=5}, + }, + { + {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, + {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, + {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, + {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, + }, + { + {x=2, y=0}, {x=3, y=0}, + {x=2, y=1}, {x=3, y=1}, + {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, + {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, + {x=0, y=4}, {x=1, y=4}, + {x=0, y=5}, {x=1, y=5}, + }, + } +} + +Rotation.pieces = 7 + +-- Component functions. + +function Rotation:new(game_mode) + self.game = require 'game.gamemode' +end + +function Rotation:rotatePiece(inputs, piece, grid, prev_inputs, initial, lastdir) + 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 was_drop_blocked = piece:isDropBlocked(grid) + + if self:canPieceRotate(piece, grid) then +-- if not self.held_rotate then +-- self:attemptRotate(inputs, piece, grid, initial) +-- self.held_rotate = true +-- else + self:attemptRotate(new_inputs, piece, grid, initial, lastdir) +-- end + end + + if not initial and not was_drop_blocked and piece:isDropBlocked(grid) then + PlaySE("bottom") + end + + -- prev_inputs becomes the previous inputs + for input, value in pairs(inputs) do + prev_inputs[input] = inputs[input] + end +end + +function Rotation:attemptRotate(new_inputs, piece, grid, initial, lastdir) + local rot_dir = 0 + + if (new_inputs["rotate_left"] or new_inputs["rotate_left2"]) then + rot_dir = 3 + if lastdir == 0 then lastdir = -1 end + elseif (new_inputs["rotate_right"] or new_inputs["rotate_right2"]) then + rot_dir = 1 + if lastdir == 0 then lastdir = 1 end + end + if rot_dir == 0 then return end + + local new_piece = piece:withRelativeRotation(rot_dir) + self:attemptWallkicks(piece, new_piece, rot_dir, grid, lastdir) +end + +function Rotation:attemptWallkicks(piece, new_piece, rot_dir, grid, lastdir) + -- wallkick routine designed to maximize flexibility while minimizing teleports + + -- O doesn't kick + if (piece.shape == "O") then return end + + -- assess precisely what rows/columns would be blocked given the desired rotation + local sides = {top=false,uright=false,lright=false,uleft=false,lleft=false,center=false,bottom=false} + local left_exists = false + local right_exists = false + local kick = {x=0,y=0} + for _,offset in pairs(new_piece:getBlockOffsets()) do + local x = piece.position.x + offset.x + local y = piece.position.y + offset.y + if offset.x == 0 then left_exists = true end + if offset.x == 2 or offset.x == 3 then right_exists = true end + + if grid:isOccupied(x,y) then + if offset.y == 0 then sides.top = true end + if offset.y == 3 then sides.bottom = true end + if offset.y == 1 and offset.x == 0 then sides.uleft = true end + if offset.y == 2 and offset.x == 0 then sides.lleft = true end + if offset.y == 1 and (offset.x == 2 or offset.x == 3) then sides.uright = true end + if offset.y == 2 and (offset.x == 2 or offset.x == 3) then sides.lright = true end + if offset.x == 1 then sides.center = true end + end + end + + if sides.top then kick = {x=0,y=1} + elseif (sides.uleft and sides.lright) or (sides.uright and sides.lleft) or (sides.uright and sides.uleft) then kick = {x=0,y=1} + elseif (sides.lleft and sides.lright) then kick = {x=0,y=-1} + elseif (sides.lleft or sides.uleft) then kick = {x=1,y=0} + elseif (sides.lright or sides.uright) then kick = {x=-1,y=0} + elseif sides.center and left_exists then kick = {x=1,y=0} + elseif sides.center and right_exists then kick = {x=-1,y=0} + elseif sides.bottom then kick = {x=0,y=-1} + end + + + if grid:canPlacePiece(new_piece:withOffset({x=0,y=0})) then + self:onPieceRotate(piece, grid) + piece:setRelativeRotation(rot_dir):setOffset({x=0,y=0}) + elseif grid:canPlacePiece(new_piece:withOffset(kick)) then + self:onPieceRotate(piece, grid) + piece:setRelativeRotation(rot_dir):setOffset(kick) + end +end + +function Rotation:movePiece(piece, grid, move, instant) + local was_drop_blocked = piece:isDropBlocked(grid) + local offset = ({x=0, y=0}) + local moves = 0 + local y = piece.position.y + if move == "left" then + offset.x = -1 + moves = 1 + elseif move == "right" then + offset.x = 1 + moves = 1 + elseif move == "speedleft" then + offset.x = -1 + moves = grid.width + elseif move == "speedright" then + offset.x = 1 + moves = grid.width + end + if not self:canPieceMove(piece, grid) then return end + for i = 1, moves do + local x = piece.position.x + if moves ~= 1 then + piece:moveInGrid(offset, 1, grid, instant) + else + piece:moveInGrid(offset, 1, grid, false) + end + if piece.position.x ~= x then + self:onPieceMove(piece, grid) + if piece.locked then break end + end + end + if not was_drop_blocked and piece:isDropBlocked(grid) then + PlaySE("bottom") + end +end + +function Rotation:dropPiece( + inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked, + hard_drop_enabled, additive_gravity, classic_lock +) + local y = piece.position.y + if inputs["down"] == true and drop_locked == false then + piece:addGravity(math.max(gravity, drop_speed), grid, classic_lock) + else + piece:addGravity(gravity, grid, classic_lock) + end + if piece.position.y ~= y then + self:onPieceDrop(piece, grid) + end +end + +function Rotation:lockPiece(piece, grid, lock_delay, classic_lock) + if piece:isDropBlocked(grid) and piece.lock_delay >= lock_delay then + piece.locked = true + end +end + +function Rotation:get180RotationValue() return 3 end +function Rotation:getDefaultOrientation() return 1 end +function Rotation:getDrawOffset(shape, orientation) return { x=0, y=0 } end +function Rotation:getAboveFieldOffset(shape, orientation) + if shape == "I" then + return 1 + else + return 2 + end +end + +function Rotation:initializePiece( + inputs, data, grid, gravity, prev_inputs, + move, lock_delay, drop_speed, + drop_locked, hard_drop_locked, big, irs, lastdir +) + local spawn_positions + spawn_positions = self.spawn_positions + + local colours + colours = self.colourscheme + self.last_dir = 0 + self.held_rotate = false + if inputs['left'] then self.last_dir = -1 + elseif inputs['right'] then self.last_dir = 1 end + local spawn_x = math.floor(spawn_positions[data.shape].x / 10 * grid.width) + + local spawn_dy + spawn_dy = 0 + + local piece = Piece(data.shape, data.orientation - 1, { + x = 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) + + self:onPieceCreate(piece) + if irs then + self:rotatePiece(inputs, piece, grid, {}, true, lastdir) + end + return piece +end + +function Rotation:onPieceCreate(piece) end + +function Rotation:processPiece( + inputs, piece, grid, gravity, prev_inputs, + move, lock_delay, drop_speed, + drop_locked, hard_drop_locked, + hard_drop_enabled, additive_gravity, classic_lock, lastdir +) + self:rotatePiece(inputs, piece, grid, prev_inputs, false, lastdir) + self:movePiece(piece, grid, move, gravity >= grid.height) + self:dropPiece( + inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked, + hard_drop_enabled, additive_gravity, classic_lock + ) + self:lockPiece(piece, grid, lock_delay, classic_lock) +end + +function Rotation:canPieceMove(piece, grid) return true end +function Rotation:canPieceRotate(piece, grid) return true end +function Rotation:onPieceMove(piece) end +function Rotation:onPieceRotate(piece) end +function Rotation:onPieceDrop(piece) + if piece.position.y > piece.lowest_point then + piece.lock_delay = 0 + piece.lowest_point = piece.position.y + end +end + +return Rotation diff --git a/scene/game.lua b/scene/game.lua index dcec993..abca843 100644 --- a/scene/game.lua +++ b/scene/game.lua @@ -58,11 +58,11 @@ function GameScene:new(player_name, replay_file, replay_grade) game_mode = require 'game.gamemode' if PENTO_MODE then - ruleset = require 'game.rotation_pent' + ruleset = require 'game.rotation_big' else ruleset = require 'game.rotation' end - + self.retry_mode = game_mode self.retry_ruleset = ruleset -- self.secret_inputs = inputs