Added all the Marathon AX modes and Ace-ARS.

This commit is contained in:
Joe Z 2019-06-19 22:56:33 -04:00
parent 1254de15d5
commit 7deaa5ab92
10 changed files with 311 additions and 65 deletions

View File

@ -28,7 +28,9 @@ From other games:
* **MARATHON A1**: Tetris the Grand Master 1. * **MARATHON A1**: Tetris the Grand Master 1.
* **MARATHON A2**: Tetris the Grand Master 2 (TAP Master). * **MARATHON A2**: Tetris the Grand Master 2 (TAP Master).
* **MARATHON A3**: Tetris the Grand Master 3 (no exams). * **MARATHON A3**: Tetris the Grand Master 3 (no exams).
* **MARATHON AX4**: Another mode from TGM Ace. * **MARATHON AX**: Normal mode from TGM Ace.
* **MARATHON AX2**: Hi-Speed1 mode from TGM Ace.
* **MARATHON AX3**: Hi-Speed2 mode from TGM Ace.
* **MARATHON C89**: Nintendo NES Tetris. Can you transition and make it to the killscreen? * **MARATHON C89**: Nintendo NES Tetris. Can you transition and make it to the killscreen?
@ -43,6 +45,8 @@ From other games:
* **SURVIVAL A1**: 20G mode from Tetris the Grand Master. * **SURVIVAL A1**: 20G mode from Tetris the Grand Master.
* **SURVIVAL A2**: T.A. Death. * **SURVIVAL A2**: T.A. Death.
* **SURVIVAL A3**: Ti Shirase. * **SURVIVAL A3**: Ti Shirase.
* **SURVIVAL AX**: Another mode from TGM Ace.
* **SURVIVAL AX2**: Another2 mode from TGM Ace.
RACE RACE
@ -63,7 +67,6 @@ Modes where pieces turn invisible as soon as you lock them. One of Cambridge's s
* **Phantom Mania 2**: Phantom Mania but way faster! Can you face a mode where even the garbage and the next preview turn invisible? * **Phantom Mania 2**: Phantom Mania but way faster! Can you face a mode where even the garbage and the next preview turn invisible?
OTHER MODES OTHER MODES
----------- -----------

View File

@ -19,17 +19,22 @@ game_modes = {
require 'tetris.modes.marathon_a1', require 'tetris.modes.marathon_a1',
require 'tetris.modes.marathon_a2', require 'tetris.modes.marathon_a2',
require 'tetris.modes.marathon_a3', require 'tetris.modes.marathon_a3',
require 'tetris.modes.marathon_ax4', require 'tetris.modes.marathon_ax',
require 'tetris.modes.marathon_ax2',
require 'tetris.modes.marathon_ax3',
require 'tetris.modes.marathon_c89', require 'tetris.modes.marathon_c89',
require 'tetris.modes.survival_a1', require 'tetris.modes.survival_a1',
require 'tetris.modes.survival_a2', require 'tetris.modes.survival_a2',
require 'tetris.modes.survival_a3', require 'tetris.modes.survival_a3',
require 'tetris.modes.survival_ax',
require 'tetris.modes.survival_ax2',
} }
rulesets = { rulesets = {
require 'tetris.rulesets.cambridge', require 'tetris.rulesets.cambridge',
require 'tetris.rulesets.arika', require 'tetris.rulesets.arika',
require 'tetris.rulesets.arika_ti', require 'tetris.rulesets.arika_ti',
require 'tetris.rulesets.arika_ace',
require 'tetris.rulesets.standard_exp', require 'tetris.rulesets.standard_exp',
--require 'tetris.rulesets.bonkers', --require 'tetris.rulesets.bonkers',
--require 'tetris.rulesets.shirase', --require 'tetris.rulesets.shirase',

View File

@ -5,20 +5,19 @@ local Piece = require 'tetris.components.piece'
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls' local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
local MarathonAX4Game = GameMode:extend() local MarathonAXGame = GameMode:extend()
MarathonAX4Game.name = "Marathon AX4" MarathonAXGame.name = "Marathon AX"
MarathonAX4Game.hash = "MarathonAX4" MarathonAXGame.hash = "MarathonAX"
MarathonAX4Game.tagline = "Can you clear the time hurdles when the game goes this fast?" MarathonAXGame.tagline = "Can you clear the time hurdles when the game goes this fast?"
function MarathonAX4Game:new() function MarathonAXGame:new()
MarathonAX4Game.super:new() MarathonAXGame.super:new()
self.roll_frames = 0 self.roll_frames = 0
self.randomizer = History6RollsRandomizer() self.randomizer = History6RollsRandomizer()
self.section_time_limit = 3600
self.section_start_time = 0 self.section_start_time = 0
self.section_times = { [0] = 0 } self.section_times = { [0] = 0 }
self.section_clear = false self.section_clear = false
@ -28,52 +27,48 @@ function MarathonAX4Game:new()
self.next_queue_length = 3 self.next_queue_length = 3
end end
function MarathonAX4Game:getARE() function MarathonAXGame:getSectionTimeLimit()
if self.lines < 10 then return 18 if self.lines < 20 then return 7200
elseif self.lines < 40 then return 14 else return 5400 end
elseif self.lines < 60 then return 12
elseif self.lines < 70 then return 10
elseif self.lines < 80 then return 8
elseif self.lines < 90 then return 7
else return 6 end
end end
function MarathonAX4Game:getLineARE() function MarathonAXGame:getARE()
return 27
end
function MarathonAXGame:getLineARE()
return self:getARE() return self:getARE()
end end
function MarathonAX4Game:getDasLimit() function MarathonAXGame:getDasLimit()
if self.lines < 20 then return 10 return 15
elseif self.lines < 50 then return 9
elseif self.lines < 70 then return 8
else return 7 end
end end
function MarathonAX4Game:getLineClearDelay() function MarathonAXGame:getLineClearDelay()
if self.lines < 10 then return 14 return 40
elseif self.lines < 30 then return 9
else return 5 end
end end
function MarathonAX4Game:getLockDelay() function MarathonAXGame:getLockDelay()
if self.lines < 10 then return 28 return 30
elseif self.lines < 20 then return 24
elseif self.lines < 30 then return 22
elseif self.lines < 40 then return 20
elseif self.lines < 50 then return 18
elseif self.lines < 70 then return 14
else return 13 end
end end
function MarathonAX4Game:getGravity() function MarathonAXGame:getGravity()
return 20 if self.lines < 10 then return 4/256
elseif self.lines < 20 then return 12/256
elseif self.lines < 30 then return 48/256
elseif self.lines < 40 then return 72/256
elseif self.lines < 50 then return 96/256
elseif self.lines < 60 then return 1/2
elseif self.lines < 70 then return 1
elseif self.lines < 80 then return 3/2
elseif self.lines < 90 then return 2
elseif self.lines < 100 then return 3
elseif self.lines < 110 then return 4
elseif self.lines < 120 then return 5
else return 20 end
end end
function MarathonAX4Game:getSection() function MarathonAXGame:advanceOneFrame()
return math.floor(level / 100) + 1
end
function MarathonAX4Game:advanceOneFrame()
if self.clear then if self.clear then
self.roll_frames = self.roll_frames + 1 self.roll_frames = self.roll_frames + 1
if self.roll_frames < 0 then if self.roll_frames < 0 then
@ -85,14 +80,14 @@ function MarathonAX4Game:advanceOneFrame()
if not self.section_clear then if not self.section_clear then
self.frames = self.frames + 1 self.frames = self.frames + 1
end end
if self:getSectionTime() >= self.section_time_limit then if self:getSectionTime() >= self:getSectionTimeLimit() then
self.game_over = true self.game_over = true
end end
end end
return true return true
end end
function MarathonAX4Game:onLineClear(cleared_row_count) function MarathonAXGame:onLineClear(cleared_row_count)
if not self.clear then if not self.clear then
local new_lines = self.lines + cleared_row_count local new_lines = self.lines + cleared_row_count
self:updateSectionTimes(self.lines, new_lines) self:updateSectionTimes(self.lines, new_lines)
@ -104,11 +99,11 @@ function MarathonAX4Game:onLineClear(cleared_row_count)
end end
end end
function MarathonAX4Game:getSectionTime() function MarathonAXGame:getSectionTime()
return self.frames - self.section_start_time return self.frames - self.section_start_time
end end
function MarathonAX4Game:updateSectionTimes(old_lines, new_lines) function MarathonAXGame:updateSectionTimes(old_lines, new_lines)
if math.floor(old_lines / 10) < math.floor(new_lines / 10) then if math.floor(old_lines / 10) < math.floor(new_lines / 10) then
-- record new section -- record new section
table.insert(self.section_times, self:getSectionTime()) table.insert(self.section_times, self:getSectionTime())
@ -117,23 +112,23 @@ function MarathonAX4Game:updateSectionTimes(old_lines, new_lines)
end end
end end
function MarathonAX4Game:onPieceEnter() function MarathonAXGame:onPieceEnter()
self.section_clear = false self.section_clear = false
end end
function MarathonAX4Game:drawGrid(ruleset) function MarathonAXGame:drawGrid(ruleset)
self.grid:draw() self.grid:draw()
end end
function MarathonAX4Game:getHighscoreData() function MarathonAXGame:getHighscoreData()
return { return {
lines = self.lines, lines = self.lines,
frames = self.frames, frames = self.frames,
} }
end end
function MarathonAX4Game:drawScoringInfo() function MarathonAXGame:drawScoringInfo()
MarathonAX4Game.super.drawScoringInfo(self) MarathonAXGame.super.drawScoringInfo(self)
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
@ -155,7 +150,7 @@ function MarathonAX4Game:drawScoringInfo()
love.graphics.printf(self.clear and self.lines or self:getSectionEndLines(), 240, 370, 40, "right") love.graphics.printf(self.clear and self.lines or self:getSectionEndLines(), 240, 370, 40, "right")
-- draw time left, flash red if necessary -- draw time left, flash red if necessary
local time_left = self.section_time_limit - math.max(self:getSectionTime(), 0) local time_left = self:getSectionTimeLimit() - math.max(self:getSectionTime(), 0)
if not self.game_over and not self.clear and time_left < sp(0,10) and time_left % 4 < 2 then if not self.game_over and not self.clear and time_left < sp(0,10) and time_left % 4 < 2 then
love.graphics.setColor(1, 0.3, 0.3, 1) love.graphics.setColor(1, 0.3, 0.3, 1)
end end
@ -163,12 +158,12 @@ function MarathonAX4Game:drawScoringInfo()
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
end end
function MarathonAX4Game:getSectionEndLines() function MarathonAXGame:getSectionEndLines()
return math.floor(self.lines / 10 + 1) * 10 return math.floor(self.lines / 10 + 1) * 10
end end
function MarathonAX4Game:getBackground() function MarathonAXGame:getBackground()
return math.floor(self.lines / 10) return math.floor(self.lines / 10)
end end
return MarathonAX4Game return MarathonAXGame

View File

@ -0,0 +1,42 @@
require 'funcs'
local MarathonAX = require 'tetris.modes.marathon_ax'
local Piece = require 'tetris.components.piece'
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
local MarathonAX2Game = MarathonAX:extend()
MarathonAX2Game.name = "Marathon AX2"
MarathonAX2Game.hash = "MarathonAX2"
MarathonAX2Game.tagline = "Can you clear the time hurdles when the game goes this fast?"
function MarathonAX2Game:new()
MarathonAX2Game.super:new()
self.roll_frames = 0
self.randomizer = History6RollsRandomizer()
self.section_time_limit = 3600
self.section_start_time = 0
self.section_times = { [0] = 0 }
self.section_clear = false
self.lock_drop = true
self.enable_hold = true
self.next_queue_length = 3
end
function MarathonAX2Game:getGravity()
if self.lines < 10 then return 84/256
elseif self.lines < 20 then return 1/2
elseif self.lines < 30 then return 1
elseif self.lines < 40 then return 2
elseif self.lines < 50 then return 3
elseif self.lines < 60 then return 4
elseif self.lines < 70 then return 5
else return 20 end
end
return MarathonAX2Game

View File

@ -0,0 +1,35 @@
require 'funcs'
local MarathonAX = require 'tetris.modes.marathon_ax'
local Piece = require 'tetris.components.piece'
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
local MarathonAX3Game = MarathonAX:extend()
MarathonAX3Game.name = "Marathon AX3"
MarathonAX3Game.hash = "MarathonAX3"
MarathonAX3Game.tagline = "Can you clear the time hurdles when the game goes this fast?"
function MarathonAX3Game:new()
MarathonAX3Game.super:new()
self.roll_frames = 0
self.randomizer = History6RollsRandomizer()
self.section_time_limit = 3600
self.section_start_time = 0
self.section_times = { [0] = 0 }
self.section_clear = false
self.lock_drop = true
self.enable_hold = true
self.next_queue_length = 3
end
function MarathonAX3Game:getGravity()
return 20
end
return MarathonAX3Game

View File

@ -0,0 +1,76 @@
require 'funcs'
local MarathonAX = require 'tetris.modes.marathon_ax'
local Piece = require 'tetris.components.piece'
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
local SurvivalAXGame = MarathonAX:extend()
SurvivalAXGame.name = "Survival AX"
SurvivalAXGame.hash = "SurvivalAX"
SurvivalAXGame.tagline = "Can you clear the time hurdles when the game goes this fast?"
function SurvivalAXGame:new()
SurvivalAXGame.super:new()
self.roll_frames = 0
self.randomizer = History6RollsRandomizer()
self.section_time_limit = 3600
self.section_start_time = 0
self.section_times = { [0] = 0 }
self.section_clear = false
self.lock_drop = true
self.enable_hold = true
self.next_queue_length = 3
end
function SurvivalAXGame:getSectionTimeLimit()
return 3600
end
function SurvivalAXGame:getARE()
if self.lines < 10 then return 18
elseif self.lines < 40 then return 14
elseif self.lines < 60 then return 12
elseif self.lines < 70 then return 10
elseif self.lines < 80 then return 8
elseif self.lines < 90 then return 7
else return 6 end
end
function SurvivalAXGame:getLineARE()
return self:getARE()
end
function SurvivalAXGame:getDasLimit()
if self.lines < 20 then return 10
elseif self.lines < 50 then return 9
elseif self.lines < 70 then return 8
else return 7 end
end
function SurvivalAXGame:getLineClearDelay()
if self.lines < 10 then return 14
elseif self.lines < 30 then return 8
else return 5 end
end
function SurvivalAXGame:getLockDelay()
if self.lines < 10 then return 30
elseif self.lines < 20 then return 26
elseif self.lines < 30 then return 24
elseif self.lines < 40 then return 22
elseif self.lines < 50 then return 20
elseif self.lines < 70 then return 16
else return 15 end
end
function SurvivalAXGame:getGravity()
return 20
end
return SurvivalAXGame

View File

@ -0,0 +1,59 @@
require 'funcs'
local MarathonAX2 = require 'tetris.modes.marathon_AX2'
local Piece = require 'tetris.components.piece'
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
local SurvivalAX2Game = MarathonAX2:extend()
SurvivalAX2Game.name = "Survival AX2"
SurvivalAX2Game.hash = "SurvivalAX2"
SurvivalAX2Game.tagline = "Can you clear the time hurdles when the game goes this fast?"
function SurvivalAX2Game:new()
SurvivalAX2Game.super:new()
self.roll_frames = 0
self.randomizer = History6RollsRandomizer()
self.section_time_limit = 3600
self.section_start_time = 0
self.section_times = { [0] = 0 }
self.section_clear = false
self.lock_drop = true
self.enable_hold = true
self.next_queue_length = 3
end
function SurvivalAX2Game:getSectionTimeLimit()
return 3600
end
function SurvivalAX2Game:getARE()
return 6
end
function SurvivalAX2Game:getLineARE()
return self:getARE()
end
function SurvivalAX2Game:getDasLimit()
return 7
end
function SurvivalAX2Game:getLineClearDelay()
return 5
end
function SurvivalAX2Game:getLockDelay()
return 15
end
function SurvivalAX2Game:getGravity()
return 20
end
return SurvivalAX2Game

View File

@ -0,0 +1,32 @@
local ArikaTI = require 'tetris.rulesets.arika_ti'
local ARS = ArikaTI:extend()
ARS.name = "Ace-ARS"
ARS.hash = "ArikaAce"
function ARS:onPieceCreate(piece, grid)
piece.floorkick = 0
piece.rotate_counter = 0
piece.move_counter = 0
end
function ARS:onPieceDrop(piece, grid)
piece.lock_delay = 0 -- step reset
end
function ARS: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 >= 128 then
piece.locked = true
end
end
end
function ARS:onPieceRotate(piece, grid)
self:onPieceMove(piece, grid)
end
return ARS

View File

@ -117,13 +117,12 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
end end
end end
elseif piece.shape ~= "I" then elseif piece.shape ~= "I" then
-- kick right, kick left -- kick right, kick left
if (grid:canPlacePiece(new_piece:withOffset({x=1, y=0}))) then if (grid:canPlacePiece(new_piece:withOffset({x=1, y=0}))) then
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
elseif (grid:canPlacePiece(new_piece:withOffset({x=-1, y=0}))) then elseif (grid:canPlacePiece(new_piece:withOffset({x=-1, y=0}))) then
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
end end
else
end end
end end

View File

@ -398,6 +398,7 @@ function CRS:onPieceDrop(piece, grid)
end end
function CRS:onPieceMove(piece, grid) function CRS:onPieceMove(piece, grid)
piece.lock_delay = 0 -- move reset
if piece:isDropBlocked(grid) then if piece:isDropBlocked(grid) then
piece.move_counter = piece.move_counter + 1 piece.move_counter = piece.move_counter + 1
if piece.move_counter >= 24 then if piece.move_counter >= 24 then
@ -407,6 +408,7 @@ function CRS:onPieceMove(piece, grid)
end end
function CRS:onPieceRotate(piece, grid) function CRS:onPieceRotate(piece, grid)
piece.lock_delay = 0 -- move reset
if piece:isDropBlocked(grid) then if piece:isDropBlocked(grid) then
piece.rotate_counter = piece.rotate_counter + 1 piece.rotate_counter = piece.rotate_counter + 1
if piece.rotate_counter >= 12 then if piece.rotate_counter >= 12 then
@ -415,6 +417,4 @@ function CRS:onPieceRotate(piece, grid)
end end
end end
function CRS:getDefaultOrientation() return 1 end -- downward facing pieces by default
return CRS return CRS