Merge branch 'master' into 3d_blocks

This commit is contained in:
nightmareci
2023-12-31 08:50:23 -08:00
42 changed files with 466 additions and 238 deletions

View File

@@ -232,12 +232,15 @@ function Grid:applyBigPiece(piece)
end
end
function Grid:checkForBravo(cleared_row_count)
for i = 0, self.height - 1 - cleared_row_count do
for j = 0, self.width - 1 do
if self:isOccupied(j, i) then return false end
end
-- places where you see this take an argument used the old, buggy method
function Grid:checkForBravo()
for i = 0, self.height - 1 do
if not self:isRowFull(i+1) then
for j = 0, self.width - 1 do
if self:isOccupied(j, i) then return false end
end
end
end
return true
end

View File

@@ -10,41 +10,10 @@ BigA2Game.tagline = "Big blocks in the most celebrated TGM mode!"
function BigA2Game:new()
BigA2Game.super:new()
self.big_mode = true
end
function BigA2Game:updateScore(level, drop_bonus, cleared_lines)
cleared_lines = cleared_lines / 2
if not self.clear then
self:updateGrade(cleared_lines)
if cleared_lines >= 4 then
self.tetris_count = self.tetris_count + 1
end
if self.grid:checkForBravo(cleared_lines) then self.bravo = 4 else self.bravo = 1 end
if cleared_lines > 0 then
self.combo = self.combo + (cleared_lines - 1) * 2
self.score = self.score + (
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
cleared_lines * self.combo * self.bravo
)
else
self.combo = 1
end
self.drop_bonus = 0
else self.lines = self.lines + cleared_lines end
end
function BigA2Game:onLineClear(cleared_row_count)
cleared_row_count = cleared_row_count / 2
self:updateSectionTimes(self.level, self.level + cleared_row_count)
self.level = math.min(self.level + cleared_row_count, 999)
if self.level == 999 and not self.clear then
self.clear = true
self.grid:clear()
if self:qualifiesForMRoll() then self.grade = 32 end
self.roll_frames = -150
local getClearedRowCount = self.grid.getClearedRowCount
self.grid.getClearedRowCount = function(self)
return getClearedRowCount(self) / 2
end
self.lock_drop = self.level >= 900
self.lock_hard_drop = self.level >= 900
end
return BigA2Game

View File

@@ -136,25 +136,27 @@ function GameMode:saveReplay()
replay["lines"] = self.lines
replay["gamesettings"] = config.gamesettings
replay["secret_inputs"] = self.secret_inputs
replay["delayed_auto_shift"] = config.das
replay["auto_repeat_rate"] = config.arr
replay["das_cut_delay"] = config.dcd
replay["timestamp"] = os.time()
replay["pause_count"] = self.pause_count
replay["pause_time"] = self.pause_time
if love.filesystem.getInfo("replays") == nil then
love.filesystem.createDirectory("replays")
end
local replay_files = love.filesystem.getDirectoryItems("replays")
-- Select replay filename that doesn't collide with an existing one
local init_name = string.format("replays/%s.crp", os.date("%Y-%m-%d_%H-%M-%S"))
local replay_name = init_name
local replay_number = 0
local collision = true
while collision do
collision = false
replay_number = replay_number + 1
for key, file in pairs(replay_files) do
if file == replay_number..".crp" then
collision = true
break
end
while true do
if love.filesystem.getInfo(replay_name, "file") then
replay_number = replay_number + 1
replay_name = string.format("%s (%d)", init_name, replay_number)
else
break
end
end
love.filesystem.write("replays/"..replay_number..".crp", binser.serialize(replay))
love.filesystem.write(replay_name, binser.serialize(replay))
end
function GameMode:addReplayInput(inputs)
@@ -178,6 +180,9 @@ function GameMode:update(inputs, ruleset)
if self.game_over or self.completed then
if self.save_replay and self.game_over_frames == 0 then
self:saveReplay()
-- ensure replays are only saved once per game, incase self.game_over_frames == 0 for longer than one frame
self.save_replay = false
end
self.game_over_frames = self.game_over_frames + 1
return
@@ -399,6 +404,7 @@ end
function GameMode:onGameOver()
switchBGM(nil)
pitchBGM(1)
local alpha = 0
local animation_length = 120
if self.game_over_frames < animation_length then
@@ -981,12 +987,10 @@ function GameMode:drawSectionTimesWithSplits(current_section, section_limit)
end
function GameMode:drawBackground()
local id = self:getBackground()
if type(id) == "number" then id = clamp(id, 0, #backgrounds) end
love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(
backgrounds[self:getBackground()],
0, 0, 0,
0.5, 0.5
)
drawBackground(id)
end
function GameMode:drawFrame()

View File

@@ -283,7 +283,7 @@ function Marathon2020Game:sectionPassed(old_level, new_level)
)
else
return (
(new_level < 2001 and math.floor(old_level / 100) < math.floor(new_level / 100)) or
(new_level < 2000 and math.floor(old_level / 100) < math.floor(new_level / 100)) or
(new_level >= 2020)
)
end
@@ -353,15 +353,10 @@ function Marathon2020Game:updateSectionTimes(old_level, new_level)
self.section_start_time = self.frames
if (
self.section_status[section - 1] == "cool" and
self.secondary_section_times[section] <= self.secondary_section_times[section - 1] + 120 and
self.secondary_section_times[section] < cool_cutoffs[self.delay_level]
(self.secondary_section_times[section] < cool_cutoffs[self.delay_level]) and
(section == 1 or self.secondary_section_times[section] <= self.secondary_section_times[section - 1] + 120)
) then
sectionCool(section)
elseif self.section_status[section - 1] == "cool" then
table.insert(self.section_status, "none")
elseif self.secondary_section_times[section] < cool_cutoffs[self.delay_level] then
sectionCool(section)
else
table.insert(self.section_status, "none")
end

View File

@@ -249,10 +249,13 @@ local grade_conversion = {
}
function MarathonA2Game:whilePieceActive()
self.grade_point_decay_counter = self.grade_point_decay_counter + 1
if self.grade_point_decay_counter >= grade_point_decays[self.grade + 1] then
self.grade_point_decay_counter = 0
self.grade_points = math.max(0, self.grade_points - 1)
if self.clear then return
else
self.grade_point_decay_counter = self.grade_point_decay_counter + 1
if self.grade_point_decay_counter >= grade_point_decays[self.grade + 1] then
self.grade_point_decay_counter = 0
self.grade_points = math.max(0, self.grade_points - 1)
end
end
end

View File

@@ -26,7 +26,9 @@ function MarathonA3Game:new()
self.roll_points = 0
self.grade_point_decay_counter = 0
self.section_cool_grade = 0
self.section_status = { [0] = "none" }
--self.section_status = { [0] = "none" }
self.section_cools = { [0] = 0 }
self.section_regrets = { [0] = 0 }
self.section_start_time = 0
self.secondary_section_times = { [0] = 0 }
self.section_times = { [0] = 0 }
@@ -201,15 +203,23 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
self.speed_level = self.section_cool and self.speed_level + 100 or self.speed_level
if section_time > regret_cutoffs[section] then
self.section_cool_grade = self.section_cool_grade - 1
table.insert(self.section_status, "regret")
if self.grade > 0 then
--this happens after the points are added, intentionally
local currentgrade = self:getAggregateGrade()
while self:getAggregateGrade() >= currentgrade do
self.grade = self.grade - 1
end
self.grade_points = 0
end
table.insert(self.section_regrets, 1)
self.coolregret_message = "REGRET!!"
self.coolregret_timer = 300
elseif self.section_cool then
self.section_cool_grade = self.section_cool_grade + 1
table.insert(self.section_status, "cool")
else
table.insert(self.section_status, "none")
table.insert(self.section_regrets, 0)
end
if self.section_cool then
self.section_cool_grade = self.section_cool_grade + 1
end
self.section_cool = false
@@ -223,6 +233,9 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
self.section_cool = true
self.coolregret_message = "COOL!!"
self.coolregret_timer = 300
table.insert(self.section_cools, 1)
else
table.insert(self.section_cools, 0)
end
end
end
@@ -402,9 +415,11 @@ MarathonA3Game.mRollOpacityFunction = function(age)
end
function MarathonA3Game:sectionColourFunction(section)
if self.section_status[section] == "cool" then
if self.section_cools[section] == 1 and self.section_regrets[section] == 1 then
return { 1, 1, 0, 1 }
elseif self.section_cools[section] == 1 then
return { 0, 1, 0, 1 }
elseif self.section_status[section] == "regret" then
elseif self.section_regrets[section] == 1 then
return { 1, 0, 0, 1 }
else
return { 1, 1, 1, 1 }

View File

@@ -28,7 +28,6 @@ function PhantomManiaGame:new()
self.combo = 1
self.tetrises = 0
self.section_tetrises = {[0] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
self.section_req = true
self.randomizer = History6RollsRandomizer()
end
@@ -55,7 +54,7 @@ function PhantomManiaGame:getDasLimit()
end
function PhantomManiaGame:getLineClearDelay()
return self:getLineARE()
return self:getLineARE() - 2
end
function PhantomManiaGame:getLockDelay()
@@ -120,11 +119,6 @@ function PhantomManiaGame:onLineClear(cleared_row_count)
self.level = 999
end
self.clear = true
for i = 0, 9 do
if self.section_tetrises[i] < (i == 9 and 1 or 2) then
self.section_req = false
end
end
else
self.level = new_level
end
@@ -175,6 +169,10 @@ local function getLetterGrade(level, clear)
end
end
function PhantomManiaGame:qualifiesForGM()
return true
end
function PhantomManiaGame:drawScoringInfo()
PhantomManiaGame.super.drawScoringInfo(self)
@@ -195,7 +193,7 @@ function PhantomManiaGame:drawScoringInfo()
if getLetterGrade(self.level, self.clear) ~= "" then
if self.roll_frames > 1982 then love.graphics.setColor(1, 0.5, 0, 1)
elseif self.level == 999 and self.clear then love.graphics.setColor(0, 1, 0, 1) end
if self.level == 999 and self.section_req and self.tetrises >= 31 then
if self.level == 999 and self:qualifiesForGM() then
love.graphics.printf("GM", text_x, 140, 90, "left")
else
love.graphics.printf(getLetterGrade(self.level, self.clear), text_x, 140, 90, "left")

View File

@@ -41,6 +41,7 @@ function PhantomMania2Game:new()
self.coolregret_message = ""
self.coolregret_timer = 0
self.coolregrets = { [0] = 0 }
end
function PhantomMania2Game:getARE()
@@ -202,13 +203,13 @@ end
local cool_cutoffs = {
frameTime(0,36), frameTime(0,36), frameTime(0,36), frameTime(0,36), frameTime(0,36),
frameTime(0,30), frameTime(0,30), frameTime(0,30), frameTime(0,30), frameTime(0,30),
frameTime(0,27), frameTime(0,27), frameTime(0,27),
frameTime(0,30), frameTime(0,30), frameTime(0,30),
}
local regret_cutoffs = {
frameTime(0,50), frameTime(0,50), frameTime(0,50), frameTime(0,50), frameTime(0,50),
frameTime(0,40), frameTime(0,40), frameTime(0,40), frameTime(0,40), frameTime(0,40),
frameTime(0,35), frameTime(0,35), frameTime(0,35),
frameTime(0,42), frameTime(0,42), frameTime(0,42), frameTime(0,42), frameTime(0,42),
frameTime(0,42), frameTime(0,42), frameTime(0,42),
}
function PhantomMania2Game:updateSectionTimes(old_level, new_level)
@@ -219,11 +220,14 @@ function PhantomMania2Game:updateSectionTimes(old_level, new_level)
self.section_start_time = self.frames
if section_time <= cool_cutoffs[section] then
self.grade = self.grade + 2
table.insert(self.coolregrets, 2)
self.coolregret_message = "COOL!!"
self.coolregret_timer = 300
elseif section_time <= regret_cutoffs[section] then
self.grade = self.grade + 1
table.insert(self.coolregrets, 1)
else
table.insert(self.coolregrets, 0)
self.coolregret_message = "REGRET!!"
self.coolregret_timer = 300
end
@@ -292,6 +296,16 @@ function PhantomMania2Game:setHoldOpacity()
end
end
function PhantomMania2Game:sectionColourFunction(section)
if self.coolregrets[section] == 2 then
return { 0, 1, 0, 1 }
elseif self.coolregrets[section] == 0 then
return { 1, 0, 0, 1 }
else
return { 1, 1, 1, 1 }
end
end
function PhantomMania2Game:drawScoringInfo()
PhantomMania2Game.super.drawScoringInfo(self)

View File

@@ -13,4 +13,14 @@ function PhantomManiaNGame:new()
self.enable_hold = true
end
function PhantomManiaNGame:qualifiesForGM()
if self.tetrises < 31 then return false end
for i = 0, 9 do
if self.section_tetrises[i] < (i == 9 and 1 or 2) then
return false
end
end
return true
end
return PhantomManiaNGame

View File

@@ -143,7 +143,7 @@ end
function Survival2020Game:onPieceEnter()
if not self.clear and (
(self.level < 1900 and self.level % 100 ~= 99) or
self.level == 2019
(1900 <= self.level and self.level < 2019)
) then
self.level = self.level + 1
end
@@ -201,7 +201,7 @@ end
Survival2020Game.opacityFunction = function(age)
if age > 300 then return 0
else return 1 - Math.max(age - 240, 0) / 60 end
else return 1 - math.max(age - 240, 0) / 60 end
end
function Survival2020Game:drawGrid()
@@ -249,7 +249,7 @@ function Survival2020Game:drawScoringInfo()
end
function Survival2020Game:getBackground()
return math.floor(self.level / 100)
return math.min(19, math.floor(self.level / 100))
end
function Survival2020Game:getHighscoreData()

View File

@@ -0,0 +1,49 @@
local Piece = require 'tetris.components.piece'
local Ruleset = require 'tetris.rulesets.arika_ace2'
local ARS = Ruleset:extend()
ARS.name = "ARS-X"
ARS.hash = "ArikaEXP"
ARS.MANIPULATIONS_MAX = 24
ARS.ROTATIONS_MAX = 12
function ARS:onPieceCreate(piece, grid)
piece.manipulations = 0
piece.rotations = 0
piece.lowest_y = -math.huge
end
function ARS:checkNewLow(piece)
for _, block in pairs(piece:getBlockOffsets()) do
local y = piece.position.y + block.y
if y > piece.lowest_y then
piece.manipulations = 0
piece.rotations = 0
piece.lowest_y = y
end
end
end
function ARS:onPieceMove(piece, grid)
piece.lock_delay = 0 -- move reset
if piece:isDropBlocked(grid) then
piece.manipulations = piece.manipulations + 1
if piece.manipulations >= ARS.MANIPULATIONS_MAX then
piece.locked = true
end
end
end
function ARS:onPieceRotate(piece, grid, upward)
piece.lock_delay = 0 -- rotate reset
if upward or piece:isDropBlocked(grid) then
piece.rotations = piece.rotations + 1
if piece.rotations >= ARS.ROTATIONS_MAX and piece:isDropBlocked(grid) then
piece.locked = true
end
end
end
return ARS

View File

@@ -1,5 +1,5 @@
local Piece = require 'tetris.components.piece'
local Ruleset = require 'tetris.rulesets.standard_exp'
local Ruleset = require 'tetris.rulesets.standard_ace'
local SRS = Ruleset:extend()
@@ -8,6 +8,8 @@ SRS.hash = "Standard"
SRS.softdrop_lock = false
SRS.harddrop_lock = true
SRS.enable_IRS_wallkicks = true
SRS.MANIPULATIONS_MAX = 15
SRS.wallkicks_line = {
@@ -33,8 +35,8 @@ SRS.wallkicks_line = {
},
};
function SRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
function SRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
local kicks
if piece.shape == "O" then
return
@@ -69,6 +71,12 @@ function SRS:checkNewLow(piece)
end
end
function SRS:onPieceCreate(piece, grid)
piece.manipulations = 0
piece.rotations = 0
piece.lowest_y = -math.huge
end
function SRS:onPieceDrop(piece, grid)
self:checkNewLow(piece)
if piece.manipulations >= self.MANIPULATIONS_MAX and piece:isDropBlocked(grid) then
@@ -85,6 +93,8 @@ function SRS:onPieceMove(piece, grid)
if piece.manipulations >= SRS.MANIPULATIONS_MAX then
piece.locked = true
end
else
piece.locked = false
end
end
@@ -102,4 +112,6 @@ end
function SRS:canPieceRotate() return true end
function SRS:get180RotationValue() return 2 end
return SRS

View File

@@ -1,5 +1,5 @@
local Piece = require 'tetris.components.piece'
local Ruleset = require 'tetris.rulesets.ti_srs'
local Ruleset = require 'tetris.rulesets.standard_ti'
local SRS = Ruleset:extend()

View File

@@ -1,5 +1,5 @@
local Piece = require 'tetris.components.piece'
local Ruleset = require 'tetris.rulesets.arika_srs'
local Ruleset = require 'tetris.rulesets.standard_ti'
local SRS = Ruleset:extend()
@@ -27,8 +27,6 @@ function SRS:checkNewLow(piece)
for _, block in pairs(piece:getBlockOffsets()) do
local y = piece.position.y + block.y
if y > piece.lowest_y then
--piece.manipulations = 0
--piece.rotations = 0
piece.lowest_y = y
end
end