Compare commits

..

37 Commits

Author SHA1 Message Date
--global
bfbba75f17 made the experience feel closer to arcade stackers 2022-03-31 23:27:22 -04:00
--global
27e699841e Fixed a graphical issue in Survival A2 when getting torikanned 2022-03-31 23:00:39 -04:00
--global
fac8c6584e Added batch scripts to start the game on Windows 2022-03-10 22:36:21 -05:00
Oshisaure
9e447d51a7 Merge pull request #57 from jjdelvalle/master
Include complete path when printing screenshot info
2022-03-03 19:29:48 +00:00
JDV
4dfa234bc3 Include complete path when printing screenshot info 2022-03-03 20:27:41 +01:00
Ishaan Bhardwaj
92d67968f5 Tiny UI feature added to the title screen.
If you load a custom block skin, the title screen will use your skin to draw the logo.
2022-02-07 20:39:26 -05:00
Ishaan Bhardwaj
d68bd13d2a LOVE 11.3 notice
Reminder that Windows is unaffected by this, because Windows releases come bundled with the correct version, and the bleeding edge source includes the correct version of LOVE for Windows
2022-01-28 22:22:05 -05:00
Ishaan Bhardwaj
a84335646d Fix two bugs with Marathon A3 grading
S4 now correctly has 3 internal grades instead of 4
You can get a green-line GM
2022-01-28 20:51:25 -05:00
Ishaan Bhardwaj
d46973f12d Fixed color scheme setting not applying to active piece 2021-12-18 21:30:19 -05:00
Ishaan Bhardwaj
d4360b3662 Fixed the replay system's interaction with secret inputs 2021-12-09 23:00:20 -05:00
Ishaan Bhardwaj
06225bd35a Fixed an issue where replays played in the menu could save a duplicate copy 2021-12-09 22:21:48 -05:00
Ishaan Bhardwaj
e68238cbce Fixed disabling saving replays 2021-12-09 22:00:13 -05:00
Ishaan Bhardwaj
83e197b5d6 Slight RPC change to the selection menus 2021-12-09 21:51:41 -05:00
Ishaan Bhardwaj
1c0b73987d Rearrange sliders on the game settings menu 2021-12-09 21:48:39 -05:00
Ishaan Bhardwaj
afe6a43dab Rearrange game settings, add toggle for replay saving 2021-12-09 21:44:18 -05:00
Ishaan Bhardwaj
47a5a53e23 Fixed sorting replays in the replay select
In addition, minor change to the default text that shows up when the game is paused
2021-12-09 18:18:23 -05:00
Ishaan Bhardwaj
b9ae08051a Fixed BGM not resetting after a replay 2021-12-08 21:56:31 -05:00
Ishaan Bhardwaj
d7f4aa2007 Reverted a mode select change 2021-12-08 21:56:17 -05:00
Ishaan Bhardwaj
ca85107063 Replace replay select title graphic with text 2021-12-08 21:37:34 -05:00
Ishaan Bhardwaj
fdcec19d56 Bump version to v0.3.1 + re-add snow easter egg 2021-12-08 21:30:09 -05:00
Ishaan Bhardwaj
89c7205347 Replay system v3 + love.math.random migration 2021-12-08 21:23:00 -05:00
Ishaan Bhardwaj
9b41e56135 Replay system v2 2021-12-08 20:19:46 -05:00
710f658540 Merge pull request #48 from BoatsandJoes/replays
Added replays
2021-12-07 22:39:08 -05:00
BoatsandJoes
332e3869de Replay menu no longer crashes if level or timer is nil. 2021-12-06 22:38:07 -06:00
BoatsandJoes
febd1de0ef Replays are now fully functional. 2021-12-05 22:17:44 -06:00
BoatsandJoes
81ab7cd4de Replays now replay inputs properly, and replay list has fast scroll. 2021-12-05 21:16:13 -06:00
BoatsandJoes
a5750e4959 Replays list is now sorted, and replays are smaller. 2021-12-05 15:41:51 -06:00
BoatsandJoes
59c7834c9a Fixed replay deserialization. 2021-12-05 00:18:19 -06:00
BoatsandJoes
71ada76a00 Started work on replay select menu. 2021-12-04 23:37:51 -06:00
BoatsandJoes
6c4551ebef Added replay saving. 2021-12-04 20:35:15 -06:00
9fc7e4b1eb Merge pull request #47 from BoatsandJoes/game-over-animation
Game over fadeout easing function now accelerates
2021-12-02 19:27:32 -05:00
BoatsandJoes
9e59c158b2 Line clear easing is now quadratic for all line clear delays. 2021-12-02 16:22:29 -06:00
BoatsandJoes
e464307625 Game over animation is longer, and reveals stack once it's over. 2021-12-02 15:49:27 -06:00
BoatsandJoes
888312c578 Game over fadeout easing function now accelerates. 2021-12-02 13:42:51 -06:00
a838294435 Merge pull request #46 from BoatsandJoes/line-clear-animation
Added new default line clear animations using easing functions.
2021-12-02 13:57:19 -05:00
BoatsandJoes
049806d9e2 Added a new default line clear animation using easing functions. 2021-12-02 10:59:45 -06:00
Ishaan Bhardwaj
c1693524d7 Credits change 2021-11-30 20:08:52 -05:00
33 changed files with 612 additions and 72 deletions

View File

@@ -26,13 +26,13 @@ All assets needed are bundled with the executable.
#### Bleeding edge #### Bleeding edge
If you want the bleeding edge version, download [this](https://github.com/MillaBasset/cambridge/archive/master.zip). If you want the bleeding edge version, download [this](https://github.com/MillaBasset/cambridge/archive/master.zip). Extract the ZIP to a folder of your choosing.
Extract the ZIP, open a Command Prompt at the folder you extracted Cambridge to, then run this command: Assuming you're on a 64-bit system, you can double-click `start_win64.bat` to run the game. If that doesn't work, open a Command Prompt where you extracted Cambridge and run:
dist\windows\love.exe . dist\windows\love.exe .
Alternatively, if you're on a 32-bit system, run this instead: If you're on a 32-bit system, you'll want to double-click `start_win32.bat`. If that doesn't work, run this instead:
dist\win32\love.exe . dist\win32\love.exe .
@@ -42,7 +42,7 @@ Then, check the mod pack section at the bottom of this page.
### macOS, Linux ### macOS, Linux
If you haven't already, install `love` with your favourite package manager (Homebrew on macOS, your system's default on Linux). **Make sure you're using LÖVE 11, because it won't work with earlier versions!** If you haven't already, install `love` with your favourite package manager (Homebrew on macOS, your system's default on Linux). **Make sure you're using LÖVE 11.3, because it won't work with earlier or later versions!**
#### Downloading a release #### Downloading a release
@@ -102,7 +102,6 @@ Other Notable Games
- [Tetra Online](https://github.com/Juan-Cartes/Tetra-Offline) by Mine - [Tetra Online](https://github.com/Juan-Cartes/Tetra-Offline) by Mine
- [Techmino](https://discord.gg/6Yuww44tq8) by MrZ - [Techmino](https://discord.gg/6Yuww44tq8) by MrZ
- [Example Block Game](https://github.com/oshisaure/example-block-game) by Oshisaure - [Example Block Game](https://github.com/oshisaure/example-block-game) by Oshisaure
- [TETR.IO](https://tetr.io) by osk
- [Master of Blocks](https://discord.gg/72FZ49mjWh) by Phoenix Flare - [Master of Blocks](https://discord.gg/72FZ49mjWh) by Phoenix Flare
- [Spirit Drop](https://rayblastgames.com/spiritdrop.php) by RayRay26 - [Spirit Drop](https://rayblastgames.com/spiritdrop.php) by RayRay26
- [Puzzle Trial](https://kagamine-rin.itch.io/puzzle-trial) by Rin - [Puzzle Trial](https://kagamine-rin.itch.io/puzzle-trial) by Rin

View File

@@ -20,6 +20,7 @@ backgrounds = {
love.graphics.newImage("res/backgrounds/1800.png"), love.graphics.newImage("res/backgrounds/1800.png"),
love.graphics.newImage("res/backgrounds/1900.png"), love.graphics.newImage("res/backgrounds/1900.png"),
title = love.graphics.newImage("res/backgrounds/title.png"), title = love.graphics.newImage("res/backgrounds/title.png"),
title_no_icon = love.graphics.newImage("res/backgrounds/title-no-icon.jpg"),
title_night = love.graphics.newImage("res/backgrounds/title-night.jpg"), title_night = love.graphics.newImage("res/backgrounds/title-night.jpg"),
snow = love.graphics.newImage("res/backgrounds/snow.png"), snow = love.graphics.newImage("res/backgrounds/snow.png"),
input_config = love.graphics.newImage("res/backgrounds/options-input.png"), input_config = love.graphics.newImage("res/backgrounds/options-input.png"),

View File

@@ -39,7 +39,7 @@ function initConfig()
else else
if config.current_mode then current_mode = config.current_mode end if config.current_mode then current_mode = config.current_mode end
if config.current_ruleset then current_ruleset = config.current_ruleset end if config.current_ruleset then current_ruleset = config.current_ruleset end
scene = TitleScene() scene = ArcadeScene()
end end
end end

View File

@@ -1 +1 @@
version = "v0.3" version = "v0.3.1"

View File

@@ -35,6 +35,8 @@ function love.load()
end end
function initModules() function initModules()
-- replays are not loaded here, but they are cleared
replays = {}
game_modes = {} game_modes = {}
mode_list = love.filesystem.getDirectoryItems("tetris/modes") mode_list = love.filesystem.getDirectoryItems("tetris/modes")
for i=1,#mode_list do for i=1,#mode_list do
@@ -101,6 +103,9 @@ function love.keypressed(key, scancode)
scene = InputConfigScene() scene = InputConfigScene()
switchBGM(nil) switchBGM(nil)
loadSave() loadSave()
elseif scancode == "f8" and scene.title == "Arcade" then
scene = TitleScene()
playSE("mode_decide")
-- secret sound playing :eyes: -- secret sound playing :eyes:
elseif scancode == "f8" and scene.title == "Title" then elseif scancode == "f8" and scene.title == "Title" then
config.secret = not config.secret config.secret = not config.secret
@@ -116,7 +121,7 @@ function love.keypressed(key, scancode)
love.filesystem.remove("ss") love.filesystem.remove("ss")
love.filesystem.createDirectory("ss") love.filesystem.createDirectory("ss")
end end
print("Saving screenshot as "..ss_name) print("Saving screenshot as "..love.filesystem.getSaveDirectory().."/"..ss_name)
GLOBAL_CANVAS:newImageData():encode("png", ss_name) GLOBAL_CANVAS:newImageData():encode("png", ss_name)
-- function keys are reserved -- function keys are reserved
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

View File

@@ -8,9 +8,12 @@ function Scene:render() end
function Scene:onInputPress() end function Scene:onInputPress() end
function Scene:onInputRelease() end function Scene:onInputRelease() end
ArcadeScene = require "scene.arcade"
ExitScene = require "scene.exit" ExitScene = require "scene.exit"
GameScene = require "scene.game" GameScene = require "scene.game"
ReplayScene = require "scene.replay"
ModeSelectScene = require "scene.mode_select" ModeSelectScene = require "scene.mode_select"
ReplaySelectScene = require "scene.replay_select"
KeyConfigScene = require "scene.key_config" KeyConfigScene = require "scene.key_config"
StickConfigScene = require "scene.stick_config" StickConfigScene = require "scene.stick_config"
InputConfigScene = require "scene.input_config" InputConfigScene = require "scene.input_config"

52
scene/arcade.lua Normal file
View File

@@ -0,0 +1,52 @@
local ArcadeScene = Scene:extend()
ArcadeScene.title = "Arcade"
function ArcadeScene:new()
self.frames = 0
DiscordRPC:update({
details = "In menus",
state = "Waiting for a credit",
largeImageKey = "icon2",
largeImageText = version
})
end
local block_offsets = {
{color = "M", x = 0, y = 0},
{color = "G", x = 32, y = 0},
{color = "Y", x = 64, y = 0},
{color = "B", x = 0, y = 32},
{color = "O", x = 0, y = 64},
{color = "C", x = 32, y = 64},
{color = "R", x = 64, y = 64}
}
function ArcadeScene:update()
self.frames = self.frames + 1
end
function ArcadeScene:render()
love.graphics.setFont(font_3x5_3)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(
backgrounds["title_no_icon"],
0, 0, 0,
0.5, 0.5
)
for _, b in ipairs(block_offsets) do
love.graphics.draw(
blocks["2tie"][b.color],
272 + b.x, 144 + b.y, 0,
2, 2
)
end
love.graphics.printf("CAMBRIDGE: THE OPEN SOURCE ARCADE STACKER", 0, 256, 640, "center")
love.graphics.setFont(font_3x5_2)
love.graphics.setColor(1, 1, 1, 1 - (math.floor(self.frames / 60) % 2))
love.graphics.printf("Insert 1 credit(s)", 0, 416, 640, "center")
end
return ArcadeScene

View File

@@ -5,7 +5,7 @@ CreditsScene.title = "Credits"
function CreditsScene:new() function CreditsScene:new()
self.frames = 0 self.frames = 0
-- higher = slower -- higher = slower
self.scroll_speed = 1.85 self.scroll_speed = 1.8
switchBGM("credit_roll", "gm3") switchBGM("credit_roll", "gm3")
DiscordRPC:update({ DiscordRPC:update({
@@ -46,7 +46,7 @@ function CreditsScene:render()
love.graphics.print("Game Developers", 320, 550 - offset) love.graphics.print("Game Developers", 320, 550 - offset)
love.graphics.print("Project Heads", 320, 640 - offset) love.graphics.print("Project Heads", 320, 640 - offset)
love.graphics.print("Notable Game Developers", 320, 750 - offset) love.graphics.print("Notable Game Developers", 320, 750 - offset)
love.graphics.print("Special Thanks", 320, 1020 - offset) love.graphics.print("Special Thanks", 320, 1000 - offset)
love.graphics.print("- Milla", 320, math.max(2130 - offset, 320)) love.graphics.print("- Milla", 320, math.max(2130 - offset, 320))
love.graphics.setFont(font_3x5_2) love.graphics.setFont(font_3x5_2)
@@ -55,7 +55,7 @@ function CreditsScene:render()
love.graphics.print( love.graphics.print(
"2Tie - TGMsim\nAxel Fox - Multimino\nDr Ocelot - Tetra Legends\n" .. "2Tie - TGMsim\nAxel Fox - Multimino\nDr Ocelot - Tetra Legends\n" ..
"Electra - ZTrix\nFelicity/nightmareci/kdex - Shiromino\n" .. "Electra - ZTrix\nFelicity/nightmareci/kdex - Shiromino\n" ..
"Mine - Tetra Online\nMrZ - Techmino\nosk - TETR.IO\n" .. "Mine - Tetra Online\nMrZ - Techmino\n" ..
"Phoenix Flare - Master of Blocks\nRayRay26 - Spirit Drop\n" .. "Phoenix Flare - Master of Blocks\nRayRay26 - Spirit Drop\n" ..
"Rin - Puzzle Trial\nsinefuse - stackfuse", "Rin - Puzzle Trial\nsinefuse - stackfuse",
320, 790 - offset 320, 790 - offset
@@ -66,7 +66,7 @@ function CreditsScene:render()
"CylinderKnot\neightsixfivezero\nEricICX\nGesomaru\n" .. "CylinderKnot\neightsixfivezero\nEricICX\nGesomaru\n" ..
"gizmo4487\nJBroms\nKirby703\nKitaru\n" .. "gizmo4487\nJBroms\nKirby703\nKitaru\n" ..
"M1ssing0\nMattMayuga\nMyPasswordIsWeak\n" .. "M1ssing0\nMattMayuga\nMyPasswordIsWeak\n" ..
"Nikki Karissa\noffwo\nOliver\nPineapple\npokemonfan1937\n" .. "Nikki Karissa\nnim\noffwo\nOliver\nPineapple\npokemonfan1937\n" ..
"Pyra Neoxi\nRDST64\nRocketLanterns\nRustyFoxxo\n" .. "Pyra Neoxi\nRDST64\nRocketLanterns\nRustyFoxxo\n" ..
"saphie\nShelleloch\nSimon\nstratus\nSuper302\n" .. "saphie\nShelleloch\nSimon\nstratus\nSuper302\n" ..
"switchpalacecorner\nterpyderp\nTetrian22\nTetro48\nThatCookie\n" .. "switchpalacecorner\nterpyderp\nTetrian22\nTetro48\nThatCookie\n" ..
@@ -75,7 +75,7 @@ function CreditsScene:render()
"Tetra Legends Discord\nTetra Online Discord\nMultimino Discord\n" .. "Tetra Legends Discord\nTetra Online Discord\nMultimino Discord\n" ..
"Hard Drop Discord\nRusty's Systemspace\nCambridge Discord\n" .. "Hard Drop Discord\nRusty's Systemspace\nCambridge Discord\n" ..
"And to you, the player!", "And to you, the player!",
320, 1060 - offset 320, 1040 - offset
) )
end end

View File

@@ -9,6 +9,7 @@ function GameScene:new(game_mode, ruleset, inputs)
self.retry_ruleset = ruleset self.retry_ruleset = ruleset
self.secret_inputs = inputs self.secret_inputs = inputs
self.game = game_mode(self.secret_inputs) self.game = game_mode(self.secret_inputs)
self.game.secret_inputs = inputs
self.ruleset = ruleset(self.game) self.ruleset = ruleset(self.game)
self.game:initialize(self.ruleset) self.game:initialize(self.ruleset)
self.inputs = { self.inputs = {
@@ -40,6 +41,8 @@ function GameScene:update()
self.game:update(inputs, self.ruleset) self.game:update(inputs, self.ruleset)
self.game.grid:update() self.game.grid:update()
DiscordRPC:update({ DiscordRPC:update({
details = self.game.rpc_details,
state = self.game.name,
largeImageKey = "ingame-"..self.game:getBackground().."00" largeImageKey = "ingame-"..self.game:getBackground().."00"
}) })
end end
@@ -61,18 +64,19 @@ function GameScene:onInputPress(e)
highscore_hash = self.game.hash .. "-" .. self.ruleset.hash highscore_hash = self.game.hash .. "-" .. self.ruleset.hash
submitHighscore(highscore_hash, highscore_entry) submitHighscore(highscore_hash, highscore_entry)
self.game:onExit() self.game:onExit()
scene = e.input == "retry" and GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs) or ModeSelectScene() scene = ArcadeScene()
-- e.input == "retry" and GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs) or ModeSelectScene()
elseif e.input == "retry" then elseif e.input == "retry" then
switchBGM(nil) switchBGM(nil)
self.game:onExit() self.game:onExit()
scene = GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs) scene = ArcadeScene() --GameScene(self.retry_mode, self.retry_ruleset, self.secret_inputs)
elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then
self.paused = not self.paused self.paused = not self.paused
if self.paused then pauseBGM() if self.paused then pauseBGM()
else resumeBGM() end else resumeBGM() end
elseif e.input == "menu_back" then elseif e.input == "menu_back" then
self.game:onExit() self.game:onExit()
scene = ModeSelectScene() scene = ArcadeScene() -- ModeSelectScene()
elseif e.input and string.sub(e.input, 1, 5) ~= "menu_" then elseif e.input and string.sub(e.input, 1, 5) ~= "menu_" then
self.inputs[e.input] = true self.inputs[e.input] = true
end end

View File

@@ -13,11 +13,12 @@ ConfigScene.options = {
{"world_reverse", "A Button Rotation", false, {"Left", "Auto", "Right"}}, {"world_reverse", "A Button Rotation", false, {"Left", "Auto", "Right"}},
{"spawn_positions", "Spawn Positions", false, {"Per ruleset", "In field", "Out of field"}}, {"spawn_positions", "Spawn Positions", false, {"Per ruleset", "In field", "Out of field"}},
{"display_gamemode", "Debug Info", false, {"On", "Off"}}, {"display_gamemode", "Debug Info", false, {"On", "Off"}},
{"das_last_key", "DAS Last Key", false, {"Off", "On"}}, {"save_replay", "Save Replays", false, {"On", "Off"}},
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}}, {"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}}, {"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
{"das_last_key", "DAS Last Key", false, {"Off", "On"}},
{"buffer_lock", "Buffer Drop Type", false, {"Off", "Hold", "Tap"}}, {"buffer_lock", "Buffer Drop Type", false, {"Off", "Hold", "Tap"}},
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
{"sfx_volume", "SFX", true, "sfxSlider"}, {"sfx_volume", "SFX", true, "sfxSlider"},
{"bgm_volume", "BGM", true, "bgmSlider"}, {"bgm_volume", "BGM", true, "bgmSlider"},
} }
@@ -33,8 +34,8 @@ function ConfigScene:new()
state = "Changing game settings", state = "Changing game settings",
}) })
self.sfxSlider = newSlider(165, 400, 225, config.sfx_volume * 100, 0, 100, function(v) config.sfx_volume = v / 100 end, {width=20, knob="circle", track="roundrect"}) self.sfxSlider = newSlider(165, 420, 225, config.sfx_volume * 100, 0, 100, function(v) config.sfx_volume = v / 100 end, {width=20, knob="circle", track="roundrect"})
self.bgmSlider = newSlider(465, 400, 225, config.bgm_volume * 100, 0, 100, function(v) config.bgm_volume = v / 100 end, {width=20, knob="circle", track="roundrect"}) self.bgmSlider = newSlider(465, 420, 225, config.bgm_volume * 100, 0, 100, function(v) config.bgm_volume = v / 100 end, {width=20, knob="circle", track="roundrect"})
end end
function ConfigScene:update() function ConfigScene:update()
@@ -58,7 +59,7 @@ function ConfigScene:render()
if not ConfigScene.options[self.highlight][3] then if not ConfigScene.options[self.highlight][3] then
love.graphics.rectangle("fill", 25, 98 + self.highlight * 20, 170, 22) love.graphics.rectangle("fill", 25, 98 + self.highlight * 20, 170, 22)
else else
love.graphics.rectangle("fill", 65 + (1+self.highlight-#self.options) * 300, 342, 215, 33) love.graphics.rectangle("fill", 65 + (1+self.highlight-#self.options) * 300, 362, 215, 33)
end end
love.graphics.setFont(font_3x5_2) love.graphics.setFont(font_3x5_2)
@@ -75,8 +76,8 @@ function ConfigScene:render()
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.setFont(font_3x5_3) love.graphics.setFont(font_3x5_3)
love.graphics.print("SFX Volume: " .. math.floor(self.sfxSlider:getValue()) .. "%", 75, 345) love.graphics.print("SFX Volume: " .. math.floor(self.sfxSlider:getValue()) .. "%", 75, 365)
love.graphics.print("BGM Volume: " .. math.floor(self.bgmSlider:getValue()) .. "%", 375, 345) love.graphics.print("BGM Volume: " .. math.floor(self.bgmSlider:getValue()) .. "%", 375, 365)
love.graphics.setColor(1, 1, 1, 0.75) love.graphics.setColor(1, 1, 1, 0.75)
self.sfxSlider:draw() self.sfxSlider:draw()

View File

@@ -78,7 +78,7 @@ function KeyConfigScene:onInputPress(e)
if not config.input then config.input = {} end if not config.input then config.input = {} end
config.input.keys = self.new_input config.input.keys = self.new_input
saveConfig() saveConfig()
scene = had_config and InputConfigScene() or TitleScene() scene = had_config and InputConfigScene() or ArcadeScene()
elseif e.scancode == "delete" or e.scancode == "backspace" then elseif e.scancode == "delete" or e.scancode == "backspace" then
-- retry -- retry
self.input_state = 1 self.input_state = 1

92
scene/replay.lua Normal file
View File

@@ -0,0 +1,92 @@
local Sequence = require 'tetris.randomizers.fixed_sequence'
local ReplayScene = Scene:extend()
ReplayScene.title = "Replay"
function ReplayScene:new(replay, game_mode, ruleset)
config.gamesettings = replay["gamesettings"]
love.math.setRandomSeed(replay["random_low"], replay["random_high"])
love.math.setRandomState(replay["random_state"])
self.retry_replay = replay
self.retry_mode = game_mode
self.retry_ruleset = ruleset
self.secret_inputs = replay["secret_inputs"]
self.game = game_mode(self.secret_inputs)
self.game.save_replay = false
self.ruleset = ruleset(self.game)
self.game:initialize(self.ruleset)
self.inputs = {
left=false,
right=false,
up=false,
down=false,
rotate_left=false,
rotate_left2=false,
rotate_right=false,
rotate_right2=false,
rotate_180=false,
hold=false,
}
self.paused = false
self.replay = deepcopy(replay)
self.replay_index = 1
DiscordRPC:update({
details = "Viewing a replay",
state = self.game.name,
largeImageKey = "ingame-"..self.game:getBackground().."00"
})
end
function ReplayScene:update()
if love.window.hasFocus() and not self.paused then
self.inputs = self.replay["inputs"][self.replay_index]["inputs"]
self.replay["inputs"][self.replay_index]["frames"] = self.replay["inputs"][self.replay_index]["frames"] - 1
if self.replay["inputs"][self.replay_index]["frames"] == 0 and self.replay_index < table.getn(self.replay["inputs"]) then
self.replay_index = self.replay_index + 1
end
local input_copy = {}
for input, value in pairs(self.inputs) do
input_copy[input] = value
end
self.game:update(input_copy, self.ruleset)
self.game.grid:update()
DiscordRPC:update({
details = "Viewing a replay",
state = self.game.name,
largeImageKey = "ingame-"..self.game:getBackground().."00"
})
end
end
function ReplayScene:render()
self.game:draw(self.paused)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setFont(font_3x5_3)
love.graphics.printf("REPLAY", 0, 0, 635, "right")
end
function ReplayScene:onInputPress(e)
if (
e.input == "menu_back" or
e.input == "menu_decide" or
e.input == "retry"
) then
self.game:onExit()
loadSave()
love.math.setRandomSeed(os.time())
scene = (
(e.input == "retry") and
ReplayScene(
self.retry_replay, self.retry_mode,
self.retry_ruleset, self.secret_inputs
) or ReplaySelectScene()
)
elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then
self.paused = not self.paused
if self.paused then pauseBGM()
else resumeBGM() end
end
end
return ReplayScene

222
scene/replay_select.lua Normal file
View File

@@ -0,0 +1,222 @@
local ReplaySelectScene = Scene:extend()
ReplaySelectScene.title = "Replays"
local binser = require 'libs.binser'
current_replay = 1
function ReplaySelectScene:new()
-- reload custom modules
initModules()
-- load replays
replays = {}
replay_file_list = love.filesystem.getDirectoryItems("replays")
for i=1,#replay_file_list do
local data = love.filesystem.read("replays/"..replay_file_list[i])
local new_replay = binser.deserialize(data)[1]
replays[#replays + 1] = new_replay
end
table.sort(replays, function(a, b)
return a["timestamp"] > b["timestamp"]
end)
self.display_error = false
if table.getn(replays) == 0 then
self.display_warning = true
current_replay = 1
else
self.display_warning = false
if current_replay > table.getn(replays) then
current_replay = 1
end
end
self.menu_state = {
replay = current_replay,
}
self.das = 0
DiscordRPC:update({
details = "In menus",
state = "Choosing a replay",
largeImageKey = "ingame-000"
})
end
function ReplaySelectScene:update()
switchBGM(nil) -- experimental
if self.das_up or self.das_down or self.das_left or self.das_right then
self.das = self.das + 1
else
self.das = 0
end
if self.das >= 15 then
local change = 0
if self.das_up then
change = -1
elseif self.das_down then
change = 1
elseif self.das_left then
change = -9
elseif self.das_right then
change = 9
end
self:changeOption(change)
self.das = self.das - 4
end
DiscordRPC:update({
details = "In menus",
state = "Choosing a replay",
largeImageKey = "ingame-000"
})
end
function ReplaySelectScene:render()
love.graphics.draw(
backgrounds[0],
0, 0, 0,
0.5, 0.5
)
-- Same graphic as mode select
--love.graphics.draw(misc_graphics["select_mode"], 20, 40)
love.graphics.setFont(font_3x5_4)
love.graphics.print("SELECT REPLAY", 20, 35)
if self.display_warning then
love.graphics.setFont(font_3x5_3)
love.graphics.printf(
"You have no replays.",
80, 200, 480, "center"
)
love.graphics.setFont(font_3x5_2)
love.graphics.printf(
"Come back to this menu after playing some games. " ..
"Press any button to return to the main menu.",
80, 250, 480, "center"
)
return
elseif self.display_error then
love.graphics.setFont(font_3x5_3)
love.graphics.printf(
"You are missing this mode or ruleset.",
80, 200, 480, "center"
)
love.graphics.setFont(font_3x5_2)
love.graphics.printf(
"Come back after getting the proper mode or ruleset. " ..
"Press any button to return to the main menu.",
80, 250, 480, "center"
)
return
end
love.graphics.setColor(1, 1, 1, 0.5)
love.graphics.rectangle("fill", 3, 258, 634, 22)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setFont(font_3x5_2)
for idx, replay in ipairs(replays) do
if(idx >= self.menu_state.replay-9 and idx <= self.menu_state.replay+9) then
local display_string = os.date("%c", replay["timestamp"]).." - "..replay["mode"].." - "..replay["ruleset"]
if replay["level"] ~= nil then
display_string = display_string.." - Level: "..replay["level"]
end
if replay["timer"] ~= nil then
display_string = display_string.." - Time: "..formatTime(replay["timer"])
end
if #display_string > 75 then
display_string = display_string:sub(1, 75) .. "..."
end
love.graphics.printf(display_string, 6, (260 - 20*(self.menu_state.replay)) + 20 * idx, 640, "left")
end
end
end
function ReplaySelectScene:onInputPress(e)
if (self.display_warning or self.display_error) and e.input then
scene = TitleScene()
elseif e.type == "wheel" then
if e.y ~= 0 then
self:changeOption(-e.y)
end
elseif e.input == "menu_decide" or e.scancode == "return" then
current_replay = self.menu_state.replay
-- Same as mode decide
playSE("mode_decide")
-- Get game mode and ruleset
local mode
local rules
for key, value in pairs(game_modes) do
if value.name == replays[self.menu_state.replay]["mode"] then
mode = value
break
end
end
for key, value in pairs(rulesets) do
if value.name == replays[self.menu_state.replay]["ruleset"] then
rules = value
break
end
end
if mode == nil or rules == nil then
self.display_error = true
return
end
-- TODO compare replay versions to current versions for Cambridge, ruleset, and mode
scene = ReplayScene(
replays[self.menu_state.replay],
mode,
rules
)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
self.das_up = true
self.das_down = nil
self.das_left = nil
self.das_right = nil
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
self.das_down = true
self.das_up = nil
self.das_left = nil
self.das_right = nil
elseif e.input == "left" or e.scancode == "left" then
self:changeOption(-9)
self.das_left = true
self.das_right = nil
self.das_up = nil
self.das_down = nil
elseif e.input == "right" or e.scancode == "right" then
self:changeOption(9)
self.das_right = true
self.das_left = nil
self.das_up = nil
self.das_down = nil
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
scene = TitleScene()
end
end
function ReplaySelectScene:onInputRelease(e)
if e.input == "up" or e.scancode == "up" then
self.das_up = nil
elseif e.input == "down" or e.scancode == "down" then
self.das_down = nil
elseif e.input == "right" or e.scancode == "right" then
self.das_right = nil
elseif e.input == "left" or e.scancode == "left" then
self.das_left = nil
end
end
function ReplaySelectScene:changeOption(rel)
local len = table.getn(replays)
self.menu_state.replay = Mod1(self.menu_state.replay + rel, len)
playSE("cursor")
end
return ReplaySelectScene

View File

@@ -20,7 +20,7 @@ function SettingsScene:new()
self.menu_state = 1 self.menu_state = 1
DiscordRPC:update({ DiscordRPC:update({
details = "In settings", details = "In settings",
state = settingsidle[math.random(#settingsidle)], state = settingsidle[love.math.random(#settingsidle)],
largeImageKey = "settings", largeImageKey = "settings",
}) })
end end

View File

@@ -86,7 +86,7 @@ function StickConfigScene:onInputPress(e)
if not config.input then config.input = {} end if not config.input then config.input = {} end
config.input.joysticks = self.new_input config.input.joysticks = self.new_input
saveConfig() saveConfig()
scene = had_config and InputConfigScene() or TitleScene() scene = had_config and InputConfigScene() or ArcadeScene()
elseif e.scancode == "delete" or e.scancode == "backspace" then elseif e.scancode == "delete" or e.scancode == "backspace" then
-- retry -- retry
self.input_state = 1 self.input_state = 1

View File

@@ -5,6 +5,7 @@ TitleScene.restart_message = false
local main_menu_screens = { local main_menu_screens = {
ModeSelectScene, ModeSelectScene,
ReplaySelectScene,
SettingsScene, SettingsScene,
CreditsScene, CreditsScene,
ExitScene, ExitScene,
@@ -43,9 +44,9 @@ function TitleScene:new()
self.text_flag = false self.text_flag = false
DiscordRPC:update({ DiscordRPC:update({
details = "In menus", details = "In menus",
state = mainmenuidle[math.random(#mainmenuidle)], state = mainmenuidle[love.math.random(#mainmenuidle)],
largeImageKey = "1year", largeImageKey = "icon2",
largeImageText = version.." | Thanks for 1 year!" largeImageText = version
}) })
end end
@@ -59,27 +60,42 @@ function TitleScene:update()
else self.y_offset = 310 - self.frames end else self.y_offset = 310 - self.frames end
end end
local block_offsets = {
{color = "M", x = 0, y = 0},
{color = "G", x = 32, y = 0},
{color = "Y", x = 64, y = 0},
{color = "B", x = 0, y = 32},
{color = "O", x = 0, y = 64},
{color = "C", x = 32, y = 64},
{color = "R", x = 64, y = 64}
}
function TitleScene:render() function TitleScene:render()
love.graphics.setFont(font_3x5_4) love.graphics.setFont(font_3x5_4)
love.graphics.setColor(1, 1, 1, 1 - self.snow_bg_opacity) love.graphics.setColor(1, 1, 1, 1 - self.snow_bg_opacity)
love.graphics.draw(
backgrounds["title_no_icon"], -- title, title_night
0, 0, 0,
0.5, 0.5
)
-- 490, 192
for _, b in ipairs(block_offsets) do
love.graphics.draw(
blocks["2tie"][b.color],
490 + b.x, 192 + b.y, 0,
2, 2
)
end
--[[ --[[
love.graphics.draw(
backgrounds["title"],
0, 0, 0,
0.5, 0.5
)
]]
love.graphics.draw(
backgrounds["title_night"],
0, 0, 0,
0.5, 0.5
)
love.graphics.draw( love.graphics.draw(
misc_graphics["icon"], misc_graphics["icon"],
460, 170, 0, 490, 192, 0,
2, 2 2, 2
) )
love.graphics.printf("Thanks for 1 year!", 430, 280, 160, "center") ]]
--love.graphics.printf("Thanks for 1 year!", 430, 280, 160, "center")
love.graphics.setFont(font_3x5_2) love.graphics.setFont(font_3x5_2)
love.graphics.setColor(1, 1, 1, self.snow_bg_opacity) love.graphics.setColor(1, 1, 1, self.snow_bg_opacity)
@@ -125,8 +141,6 @@ function TitleScene:onInputPress(e)
playSE("cursor") playSE("cursor")
elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then
love.event.quit() love.event.quit()
-- no winter easter egg for now
--[[
else else
self.text = self.text .. (e.scancode or "") self.text = self.text .. (e.scancode or "")
if self.text == "ffffff" then if self.text == "ffffff" then
@@ -135,7 +149,6 @@ function TitleScene:onInputPress(e)
largeImageKey = "snow" largeImageKey = "snow"
}) })
end end
]]
end end
end end

1
start_win32.bat Normal file
View File

@@ -0,0 +1 @@
dist\win32\love.exe .

1
start_win64.bat Normal file
View File

@@ -0,0 +1 @@
dist\windows\love.exe .

View File

@@ -182,6 +182,19 @@ function Grid:clearSpecificRow(row)
end end
end end
function Grid:clearBlock(x, y)
self.grid[x+1][y+1] = empty
end
function Grid:clearBottomRows(num)
local old_isRowFull = self.isRowFull
self.isRowFull = function(self, row)
return row >= self.height + 1 - num
end
self:clearClearedRows()
self.isRowFull = old_isRowFull
end
function Grid:applyPiece(piece) function Grid:applyPiece(piece)
if piece.big then if piece.big then
self:applyBigPiece(piece) self:applyBigPiece(piece)

View File

@@ -7,6 +7,7 @@ local playedGoSE = false
local Grid = require 'tetris.components.grid' local Grid = require 'tetris.components.grid'
local Randomizer = require 'tetris.randomizers.randomizer' local Randomizer = require 'tetris.randomizers.randomizer'
local BagRandomizer = require 'tetris.randomizers.bag' local BagRandomizer = require 'tetris.randomizers.bag'
local binser = require 'libs.binser'
local GameMode = Object:extend() local GameMode = Object:extend()
@@ -15,7 +16,12 @@ GameMode.hash = ""
GameMode.tagline = "" GameMode.tagline = ""
GameMode.rollOpacityFunction = function(age) return 0 end GameMode.rollOpacityFunction = function(age) return 0 end
function GameMode:new(secret_inputs) function GameMode:new()
self.replay_inputs = {}
self.random_low, self.random_high = love.math.getRandomSeed()
self.random_state = love.math.getRandomState()
self.save_replay = config.gamesettings.save_replay == 1
self.grid = Grid(10, 24) self.grid = Grid(10, 24)
self.randomizer = Randomizer() self.randomizer = Randomizer()
self.piece = nil self.piece = nil
@@ -114,8 +120,64 @@ function GameMode:initialize(ruleset)
self.lock_on_hard_drop = ({ruleset.harddrop_lock, self.instant_hard_drop, true, false})[config.gamesettings.manlock] self.lock_on_hard_drop = ({ruleset.harddrop_lock, self.instant_hard_drop, true, false})[config.gamesettings.manlock]
end end
function GameMode:saveReplay()
-- Save replay.
local replay = {}
replay["inputs"] = self.replay_inputs
replay["random_low"] = self.random_low
replay["random_high"] = self.random_high
replay["random_state"] = self.random_state
replay["mode"] = self.name
replay["ruleset"] = self.ruleset.name
replay["timer"] = self.frames
replay["score"] = self.score
replay["level"] = self.level
replay["lines"] = self.lines
replay["gamesettings"] = config.gamesettings
replay["secret_inputs"] = self.secret_inputs
replay["timestamp"] = os.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 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
end
end
love.filesystem.write("replays/"..replay_number..".crp", binser.serialize(replay))
end
function GameMode:addReplayInput(inputs)
-- check if inputs have changed since last frame
if not equals(self.prev_inputs, inputs) then
-- insert new inputs into replay inputs table
local new_inputs = {}
new_inputs["inputs"] = {}
new_inputs["frames"] = 1
for key, value in pairs(inputs) do
new_inputs["inputs"][key] = value
end
self.replay_inputs[#self.replay_inputs + 1] = new_inputs
else
-- add 1 to input frame counter
self.replay_inputs[#self.replay_inputs]["frames"] = self.replay_inputs[#self.replay_inputs]["frames"] + 1
end
end
function GameMode:update(inputs, ruleset) function GameMode:update(inputs, ruleset)
if self.game_over or self.completed then if self.game_over or self.completed then
if self.save_replay and self.game_over_frames == 0 then
self:saveReplay()
end
self.game_over_frames = self.game_over_frames + 1 self.game_over_frames = self.game_over_frames + 1
return return
end end
@@ -129,6 +191,8 @@ function GameMode:update(inputs, ruleset)
end end
end end
if self.save_replay then self:addReplayInput(inputs) end
-- advance one frame -- advance one frame
if self:advanceOneFrame(inputs, ruleset) == false then return end if self:advanceOneFrame(inputs, ruleset) == false then return end
@@ -334,7 +398,16 @@ end
function GameMode:onGameOver() function GameMode:onGameOver()
switchBGM(nil) switchBGM(nil)
love.graphics.setColor(0, 0, 0, 1 - 2 ^ (-self.game_over_frames / 30)) local alpha = 0
local animation_length = 120
if self.game_over_frames < animation_length then
-- Show field for a bit, then fade out.
alpha = math.pow(2048, self.game_over_frames/animation_length - 1)
elseif self.game_over_frames < 2 * animation_length then
-- Keep field hidden for a short time, then pop it back in (for screenshots).
alpha = 1
end
love.graphics.setColor(0, 0, 0, alpha)
love.graphics.rectangle( love.graphics.rectangle(
"fill", 64, 80, "fill", 64, 80,
16 * self.grid.width, 16 * (self.grid.height - 4) 16 * self.grid.width, 16 * (self.grid.height - 4)
@@ -598,11 +671,18 @@ function GameMode:getHighScoreData()
end end
function GameMode:animation(x, y, skin, colour) function GameMode:animation(x, y, skin, colour)
-- Animation progress where 0 = start and 1 = end
local progress = 1
if self.last_lcd ~= 0 then
progress = (self.last_lcd - self.lcd) / self.last_lcd
end
-- Convert progress through the animation into an alpha value, with easing
local alpha = 1 - progress ^ 2
return { return {
1, 1, 1, 1, 1, 1,
-0.25 + 1.25 * (self.lcd / self.last_lcd), alpha,
skin, colour, skin, colour,
48 + x * 16, y * 16 48 + x * 16, y * 16
} }
end end
@@ -615,7 +695,55 @@ function GameMode:drawLineClearAnimation()
-- params: block x, y, skin, colour -- params: block x, y, skin, colour
-- returns: table with RGBA, skin, colour, x, y -- returns: table with RGBA, skin, colour, x, y
-- Fadeout (default) -- Quadratic Fadeout (default)
--[[
function animation(x, y, skin, colour)
-- Animation progress where 0 = start and 1 = end
local progress = 1
if self.last_lcd ~= 0 then
progress = (self.last_lcd - self.lcd) / self.last_lcd
end
-- Convert progress through the animation into an alpha value, with easing
local alpha = 1 - progress ^ 2
return {
1, 1, 1,
alpha,
skin, colour,
48 + x * 16, y * 16
}
end
--]]
-- Flashy Fadeout
--[[
function animation(x, y, skin, colour)
-- Animation progress where 0 = start and 1 = end
local progress = 1
if self.last_lcd ~= 0 then
progress = (self.last_lcd - self.lcd) / self.last_lcd
end
-- Change this number to change "bounciness"
local bounce = 13
-- Convert progress through the animation into an alpha value
local alpha = 0
-- Cutoff is arbitrary: corresponds to level 500 in Marathon A2
if self.last_lcd > 25 then
-- Goes up and down: looks better when animation is long
alpha = 1 - (bounce * progress^3 - 1.5 * bounce * progress^2 + (0.5 * bounce + 1) * progress)
else
-- Always decreasing: looks better when animation is short
alpha = 1 - progress * progress
end
return {
1, 1, 1,
alpha,
skin, colour,
48 + x * 16, y * 16
}
end
--]]
-- Fadeout
--[[ --[[
function animation(x, y, skin, colour) function animation(x, y, skin, colour)
return { return {
@@ -904,7 +1032,7 @@ function GameMode:drawCustom() end
function GameMode:drawIfPaused() function GameMode:drawIfPaused()
love.graphics.setFont(font_3x5_3) love.graphics.setFont(font_3x5_3)
love.graphics.printf("GAME PAUSED!", 64, 160, 160, "center") love.graphics.printf("PAUSED!", 64, 160, 160, "center")
end end
-- transforms specified in here will transform the whole screen -- transforms specified in here will transform the whole screen

View File

@@ -309,7 +309,7 @@ local mroll_points = {10, 20, 30, 100}
local grade_conversion = { local grade_conversion = {
[0] = 0, [0] = 0,
1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7,
7, 8, 8, 8, 9, 9, 9, 10, 11, 12, 12, 7, 8, 8, 8, 9, 9, 9, 10, 11, 12,
12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
17 17
} }
@@ -354,8 +354,7 @@ function MarathonA3Game:getAggregateGrade()
return math.min( return math.min(
self.section_cool_grade + self.section_cool_grade +
math.floor(self.roll_points / 100) + math.floor(self.roll_points / 100) +
grade_conversion[self.grade], grade_conversion[self.grade]
self.roll_frames > 3238 and 32 or 31
) )
end end

View File

@@ -101,6 +101,7 @@ function SurvivalA2Game:onLineClear(cleared_row_count)
self.clear = true self.clear = true
if new_level < 999 then if new_level < 999 then
self.game_over = true self.game_over = true
return
end end
end end
self.level = new_level self.level = new_level

View File

@@ -13,7 +13,7 @@ function BagRandomizer:generatePiece()
table.insert(self.bag, v) table.insert(self.bag, v)
end end
end end
local x = math.random(table.getn(self.bag)) local x = love.math.random(table.getn(self.bag))
return table.remove(self.bag, x) return table.remove(self.bag, x)
end end

View File

@@ -10,7 +10,7 @@ function Bag7Randomizer:generatePiece()
if next(self.bag) == nil then if next(self.bag) == nil then
self.bag = {"I", "J", "L", "O", "S", "T", "Z"} self.bag = {"I", "J", "L", "O", "S", "T", "Z"}
end end
local x = math.random(table.getn(self.bag)) local x = love.math.random(table.getn(self.bag))
return table.remove(self.bag, x) return table.remove(self.bag, x)
end end

View File

@@ -6,7 +6,7 @@ function Bag7NoSZOStartRandomizer:shuffleBag()
local b = self.bag local b = self.bag
local ln = #b local ln = #b
for i = 1, ln do for i = 1, ln do
local j = math.random(i, ln) local j = love.math.random(i, ln)
b[i], b[j] = b[j], b[i] b[i], b[j] = b[j], b[i]
end end
end end

View File

@@ -8,8 +8,13 @@ function Sequence:initialize()
end end
function Sequence:generatePiece() function Sequence:generatePiece()
local piece = string.sub(self.sequence, self.counter + 1, self.counter + 1) local piece
self.counter = (self.counter + 1) % string.len(self.sequence) if type(self.sequence) == "string" then
piece = string.sub(self.sequence, self.counter + 1, self.counter + 1)
else
piece = self.sequence[self.counter + 1]
end
self.counter = (self.counter + 1) % (#self.sequence)
return piece return piece
end end

View File

@@ -10,11 +10,11 @@ end
function History4RollsRandomizer:generatePiece() function History4RollsRandomizer:generatePiece()
if self.first then if self.first then
self.first = false self.first = false
return self:updateHistory(({"L", "J", "I", "T"})[math.random(4)]) return self:updateHistory(({"L", "J", "I", "T"})[love.math.random(4)])
else else
local shapes = {"I", "J", "L", "O", "S", "T", "Z"} local shapes = {"I", "J", "L", "O", "S", "T", "Z"}
for i = 1, 4 do for i = 1, 4 do
local x = math.random(7) local x = love.math.random(7)
if not inHistory(shapes[x], self.history) or i == 4 then if not inHistory(shapes[x], self.history) or i == 4 then
return self:updateHistory(shapes[x]) return self:updateHistory(shapes[x])
end end

View File

@@ -10,11 +10,11 @@ end
function History6RollsRandomizer:generatePiece() function History6RollsRandomizer:generatePiece()
if self.first then if self.first then
self.first = false self.first = false
return self:updateHistory(({"L", "J", "I", "T"})[math.random(4)]) return self:updateHistory(({"L", "J", "I", "T"})[love.math.random(4)])
else else
local shapes = {"I", "J", "L", "O", "S", "T", "Z"} local shapes = {"I", "J", "L", "O", "S", "T", "Z"}
for i = 1, 6 do for i = 1, 6 do
local x = math.random(7) local x = love.math.random(7)
if not inHistory(shapes[x], self.history) or i == 6 then if not inHistory(shapes[x], self.history) or i == 6 then
return self:updateHistory(shapes[x]) return self:updateHistory(shapes[x])
end end

View File

@@ -28,12 +28,12 @@ end
function History6Rolls35PoolRandomizer:generatePiece() function History6Rolls35PoolRandomizer:generatePiece()
local index, x local index, x
if self.first then if self.first then
index = math.random(20) index = love.math.random(20)
x = self.pool[index] x = self.pool[index]
self.first = false self.first = false
else else
for i = 1, 6 do for i = 1, 6 do
index = math.random(#self.pool) index = love.math.random(#self.pool)
x = self.pool[index] x = self.pool[index]
if not inHistory(x, self.history) or i == 6 then if not inHistory(x, self.history) or i == 6 then
break break

View File

@@ -16,7 +16,7 @@ function Randomizer:initialize()
end end
function Randomizer:generatePiece() function Randomizer:generatePiece()
return self.possible_pieces[math.random(7)] return self.possible_pieces[love.math.random(7)]
end end
return Randomizer return Randomizer

View File

@@ -209,7 +209,7 @@ function Ruleset:initializePiece(
local colours local colours
if table.equalvalues( if table.equalvalues(
self.colourscheme, {"I", "J", "L", "O", "S", "T", "Z"} table.keys(self.colourscheme), {"I", "J", "L", "O", "S", "T", "Z"}
) then ) then
colours = ({self.colourscheme, ColourSchemes.Arika, ColourSchemes.TTC})[config.gamesettings.piece_colour] colours = ({self.colourscheme, ColourSchemes.Arika, ColourSchemes.TTC})[config.gamesettings.piece_colour]
else else