14
.github/workflows/main.yml
vendored
14
.github/workflows/main.yml
vendored
@@ -143,7 +143,8 @@ jobs:
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -216,7 +217,8 @@ jobs:
|
||||
build-ios:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -297,6 +299,7 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -380,7 +383,8 @@ jobs:
|
||||
build-macos-appstore:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -464,7 +468,8 @@ jobs:
|
||||
build-macos-portable:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -560,6 +565,7 @@ jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: ${{ !always() }}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
|
||||
Submodule Zframework updated: 20a5757a9c...4aa87c6147
9
conf.lua
9
conf.lua
@@ -2,6 +2,15 @@ SYSTEM=love._os if SYSTEM=='OS X' then SYSTEM='macOS' end
|
||||
MOBILE=SYSTEM=='Android' or SYSTEM=='iOS'
|
||||
FNNS=SYSTEM:find'\79\83'-- What does FNSF stand for? IDK so don't ask me lol
|
||||
|
||||
if SYSTEM=='Web' then
|
||||
local oldRead=love.filesystem.read
|
||||
function love.filesystem.read(name,size)
|
||||
if love.filesystem.getInfo(name) then
|
||||
return oldRead(name,size)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function love.conf(t)
|
||||
local identity='Techmino'
|
||||
local msaa=0
|
||||
|
||||
15
main.lua
15
main.lua
@@ -10,8 +10,7 @@
|
||||
Instructions:
|
||||
1. I made a framework called Zframework, *most* code in Zframework are not directly relevant to game;
|
||||
2. "xxx" are texts for reading by player, 'xxx' are string values just used in program;
|
||||
3. Some goto statement are used for better performance. All goto-labes have detailed names so don't be afraid;
|
||||
4. Except "gcinfo" function of lua itself, other "gc" are short for "graphics";
|
||||
3. Except "gcinfo" function of lua itself, other "gc" are short for "graphics";
|
||||
]]--
|
||||
|
||||
|
||||
@@ -560,16 +559,15 @@ applySettings()
|
||||
|
||||
-- Load replays
|
||||
for _,fileName in next,fs.getDirectoryItems('replay') do
|
||||
if fileName:sub(12,12):match("[a-zA-Z]") then
|
||||
if fileName:sub(12,12):match("[a-zA-Z]") then repeat
|
||||
local date,mode,version,player,seed,setting,mod
|
||||
local fileData=fs.read('replay/'..fileName)
|
||||
local success,fileData=true,fs.read('replay/'..fileName)
|
||||
date, fileData=STRING.readLine(fileData)date=date:gsub("[a-zA-Z]","")
|
||||
mode, fileData=STRING.readLine(fileData)mode=MODE_UPDATE_MAP[mode] or mode
|
||||
version,fileData=STRING.readLine(fileData)
|
||||
player, fileData=STRING.readLine(fileData) if player=="Local Player" then player="Stacker" end
|
||||
local success
|
||||
success,fileData=pcall(love.data.decompress,'string','zlib',fileData)
|
||||
if not success then goto BREAK_cannotParse end
|
||||
if not success then break end
|
||||
seed, fileData=STRING.readLine(fileData)
|
||||
setting,fileData=STRING.readLine(fileData)setting=JSON.decode(setting)
|
||||
mod, fileData=STRING.readLine(fileData)mod=JSON.decode(mod)
|
||||
@@ -578,7 +576,7 @@ for _,fileName in next,fs.getDirectoryItems('replay') do
|
||||
not mod or
|
||||
not mode or
|
||||
#mode==0
|
||||
then goto BREAK_cannotParse end
|
||||
then break end
|
||||
|
||||
fs.remove('replay/'..fileName)
|
||||
local newName=fileName:sub(1,10)..fileName:sub(15)
|
||||
@@ -597,8 +595,7 @@ for _,fileName in next,fs.getDirectoryItems('replay') do
|
||||
)
|
||||
)
|
||||
fileName=newName
|
||||
end
|
||||
::BREAK_cannotParse::
|
||||
until true end
|
||||
local rep=DATA.parseReplay('replay/'..fileName)
|
||||
table.insert(REPLAY,rep)
|
||||
end
|
||||
|
||||
@@ -65,14 +65,19 @@ local function _getScore(field,cb,cy)
|
||||
local hole=0
|
||||
|
||||
for i=cy+#cb-1,cy,-1 do
|
||||
local full=true
|
||||
for j=1,10 do
|
||||
if field[i][j]==0 then
|
||||
goto CONTINUE_notFull
|
||||
-- goto CONTINUE_notFull
|
||||
full=false
|
||||
break
|
||||
end
|
||||
end
|
||||
discardRow(rem(field,i))
|
||||
clear=clear+1
|
||||
::CONTINUE_notFull::
|
||||
if full then
|
||||
-- ::CONTINUE_notFull::
|
||||
discardRow(rem(field,i))
|
||||
clear=clear+1
|
||||
end
|
||||
end
|
||||
if #field==0 then-- PC
|
||||
return 1e99
|
||||
|
||||
@@ -376,22 +376,26 @@ function DATA.parseReplay(fileName,ifFull)
|
||||
return DATA.parseReplayData(fileName,fileData,ifFull)
|
||||
end
|
||||
function DATA.parseReplayData(fileName,fileData,ifFull)
|
||||
local success,metaData,rep
|
||||
local success,metaData
|
||||
local rep={-- unavailable replay object
|
||||
fileName=fileName,
|
||||
available=false,
|
||||
}
|
||||
|
||||
if not (fileData and #fileData>0) then goto BREAK_cannotParse end
|
||||
if not (fileData and #fileData>0) then return rep end-- goto BREAK_cannotParse
|
||||
|
||||
-- Decompress file
|
||||
success,fileData=pcall(love.data.decompress,'string','zlib',fileData)
|
||||
if not success then goto BREAK_cannotParse end
|
||||
if not success then return rep end-- goto BREAK_cannotParse
|
||||
|
||||
-- Load metadata
|
||||
metaData,fileData=STRING.readLine(fileData)
|
||||
metaData=JSON.decode(metaData)
|
||||
if not metaData then goto BREAK_cannotParse end
|
||||
if not metaData then return rep end-- goto BREAK_cannotParse
|
||||
|
||||
-- Convert ancient replays
|
||||
metaData.mode=MODE_UPDATE_MAP[metaData.mode] or metaData.mode
|
||||
if not MODES[metaData.mode] then goto BREAK_cannotParse end
|
||||
if not MODES[metaData.mode] then return rep end-- goto BREAK_cannotParse
|
||||
|
||||
-- Create replay object
|
||||
rep={
|
||||
@@ -409,13 +413,6 @@ function DATA.parseReplayData(fileName,fileData,ifFull)
|
||||
tasUsed=metaData.tasUsed,
|
||||
}
|
||||
if ifFull then rep.data=fileData end
|
||||
do return rep end
|
||||
|
||||
-- Create unavailable replay object
|
||||
::BREAK_cannotParse::
|
||||
return {
|
||||
fileName=fileName,
|
||||
available=false,
|
||||
}
|
||||
return rep
|
||||
end
|
||||
return DATA
|
||||
|
||||
@@ -76,15 +76,17 @@ return {
|
||||
D.rankPts=1
|
||||
for i=1,#P.field do
|
||||
local h=getOpenHole(i)
|
||||
local flag
|
||||
for j=1,10 do
|
||||
if P.field[i][j]>0 and h==j then goto post_pts_calc end
|
||||
if P.field[i][j]==0 and h~=j then goto post_pts_calc end
|
||||
if P.field[i][j]>0 and h==j then flag=true break end-- goto post_pts_calc
|
||||
if P.field[i][j]==0 and h~=j then flag=true break end-- goto post_pts_calc
|
||||
end
|
||||
if i==#P.field then goto post_pts_calc end
|
||||
if P.field[i+1][h]==0 then goto post_pts_calc end
|
||||
if flag then break end
|
||||
if i==#P.field then break end-- goto post_pts_calc
|
||||
if P.field[i+1][h]==0 then break end-- goto post_pts_calc
|
||||
D.rankPts=D.rankPts+1
|
||||
end
|
||||
::post_pts_calc::
|
||||
-- ::post_pts_calc::
|
||||
generateGuide(D.rankPts+20)
|
||||
end
|
||||
}
|
||||
|
||||
@@ -981,7 +981,7 @@ do-- function resetGameData(args)
|
||||
GAME.replaying=true
|
||||
else
|
||||
GAME.frameStart=args:find'n' and 0 or 180-SETTING.reTime*60
|
||||
GAME.seed=seed or math.random(1046101471,2662622626)
|
||||
GAME.seed=seed or math.random(1046101471)
|
||||
GAME.pauseTime=0
|
||||
GAME.pauseCount=0
|
||||
GAME.saved=false
|
||||
|
||||
@@ -652,7 +652,7 @@ do-- Userdata tables
|
||||
showSpike=true,
|
||||
highCam=true,
|
||||
nextPos=true,
|
||||
fullscreen=true,
|
||||
fullscreen=SYSTEM~='Web',
|
||||
portrait=false,
|
||||
msaa=0,
|
||||
bg='on',
|
||||
|
||||
@@ -77,16 +77,19 @@ function Player:createLockFX()
|
||||
for i=1,#CB do
|
||||
local y=self.curY+i-1
|
||||
local L=self.clearedRow
|
||||
local skip
|
||||
for j=1,#L do
|
||||
if L[j]==y then goto CONTINUE_skip end
|
||||
if L[j]==y then skip=true break end-- goto CONTINUE_skip
|
||||
end
|
||||
y=-30*y
|
||||
for j=1,#CB[1] do
|
||||
if CB[i][j] then
|
||||
ins(self.lockFX,{30*(self.curX+j-2),y,0,t})
|
||||
if not skip then
|
||||
y=-30*y
|
||||
for j=1,#CB[1] do
|
||||
if CB[i][j] then
|
||||
ins(self.lockFX,{30*(self.curX+j-2),y,0,t})
|
||||
end
|
||||
end
|
||||
end
|
||||
::CONTINUE_skip::
|
||||
-- ::CONTINUE_skip::
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -610,6 +613,7 @@ do-- function Player:dropPosition(x,y,size)
|
||||
vy=vy+.0626
|
||||
self:setPosition(x,y,size)
|
||||
if y>2600 then
|
||||
table.remove(PLAYERS,TABLE.find(PLAYERS,self))
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -1041,16 +1045,20 @@ function Player:_checkClear(field,start,height,CB,CX)
|
||||
|
||||
h=h+1
|
||||
-- Row filled
|
||||
local full=true
|
||||
for x=1,10 do
|
||||
if field[h][x]<=0 then
|
||||
goto CONTINUE_notFull
|
||||
full=false
|
||||
break-- goto CONTINUE_notFull
|
||||
end
|
||||
end
|
||||
cc=cc+1
|
||||
if field[h].garbage then gbcc=gbcc+1 end
|
||||
ins(self.clearingRow,h-cc+1)
|
||||
ins(self.clearedRow,h)
|
||||
::CONTINUE_notFull::
|
||||
if full then
|
||||
cc=cc+1
|
||||
if field[h].garbage then gbcc=gbcc+1 end
|
||||
ins(self.clearingRow,h-cc+1)
|
||||
ins(self.clearedRow,h)
|
||||
end
|
||||
-- ::CONTINUE_notFull::
|
||||
end
|
||||
return cc,gbcc
|
||||
end
|
||||
@@ -1265,20 +1273,22 @@ function Player:hold_norm(ifpre)
|
||||
y=y+(#C.bk-#H.bk)*.5
|
||||
|
||||
local iki=phyHoldKickX[x==int(x)]
|
||||
local success
|
||||
for Y=int(y),ceil(y+.5) do
|
||||
for i=1,#iki do
|
||||
local X=x+iki[i]
|
||||
if not self:ifoverlap(H.bk,X,Y) then
|
||||
x,y=X,Y
|
||||
goto BREAK_success
|
||||
success=true
|
||||
break
|
||||
end
|
||||
end
|
||||
if success then break end
|
||||
end
|
||||
-- <for-else> All test failed, interrupt with sound
|
||||
if not success then -- All test failed, interrupt with sound
|
||||
SFX.play('drop_cancel')
|
||||
do return end
|
||||
-- <for-end>
|
||||
::BREAK_success::
|
||||
return
|
||||
end
|
||||
|
||||
self.spinLast=false
|
||||
|
||||
@@ -1332,20 +1342,22 @@ function Player:hold_swap(ifpre)
|
||||
y=y+(#C.bk-#H.bk)*.5
|
||||
|
||||
local iki=phyHoldKickX[x==int(x)]
|
||||
for Y=int(y),ceil(y+.5) do
|
||||
for i=1,#iki do
|
||||
local X=x+iki[i]
|
||||
if not self:ifoverlap(H.bk,X,Y) then
|
||||
x,y=X,Y
|
||||
goto BREAK_success
|
||||
local success
|
||||
for Y=int(y),ceil(y+.5) do
|
||||
for i=1,#iki do
|
||||
local X=x+iki[i]
|
||||
if not self:ifoverlap(H.bk,X,Y) then
|
||||
x,y=X,Y
|
||||
success=true
|
||||
break
|
||||
end
|
||||
end
|
||||
if success then break end
|
||||
end
|
||||
end
|
||||
-- <for-else> All test failed, interrupt with sound
|
||||
if not success then -- All test failed, interrupt with sound
|
||||
SFX.play('finesseError')
|
||||
do return end
|
||||
-- <for-end>
|
||||
::BREAK_success::
|
||||
return
|
||||
end
|
||||
|
||||
self.spinLast=false
|
||||
|
||||
@@ -2508,90 +2520,92 @@ local function update_alive(P,dt)
|
||||
local stopAtFalling
|
||||
|
||||
-- Falling animation
|
||||
if P.falling>0 then
|
||||
stopAtFalling=true
|
||||
P:_updateFalling(P.falling-1)
|
||||
repeat
|
||||
if P.falling>0 then
|
||||
goto THROW_stop
|
||||
end
|
||||
end
|
||||
|
||||
-- Update block state
|
||||
if P.control then
|
||||
-- Try spawn new block
|
||||
if not P.cur then
|
||||
if not stopAtFalling and P.waiting>0 then
|
||||
P.waiting=P.waiting-1
|
||||
stopAtFalling=true
|
||||
P:_updateFalling(P.falling-1)
|
||||
if P.falling>0 then
|
||||
break-- goto THROW_stop
|
||||
end
|
||||
if P.waiting<=0 then
|
||||
P:popNext()
|
||||
end
|
||||
goto THROW_stop
|
||||
end
|
||||
|
||||
-- Natural block falling
|
||||
if P.cur then
|
||||
if P.curY>P.ghoY then
|
||||
local D=P.dropDelay
|
||||
local dist-- Drop distance
|
||||
if D>1 then
|
||||
D=D-1
|
||||
if P.keyPressing[7] and P.downing>=ENV.sddas then
|
||||
D=D-ceil(ENV.drop/ENV.sdarr)
|
||||
end
|
||||
if D<=0 then
|
||||
dist=1
|
||||
P.dropDelay=(D-1)%ENV.drop+1
|
||||
else
|
||||
P.dropDelay=D
|
||||
goto THROW_stop
|
||||
end
|
||||
elseif D==1 then-- We don't know why dropDelay is 1, so checking ENV.drop>1 is neccessary
|
||||
if ENV.drop>1 and P.downing>=ENV.sddas and (P.downing-ENV.sddas)%ENV.sdarr==0 then
|
||||
dist=2
|
||||
else
|
||||
dist=1
|
||||
end
|
||||
-- Reset drop delay
|
||||
P.dropDelay=ENV.drop
|
||||
else-- High gravity case (>1G)
|
||||
-- Add extra 1 if time to auto softdrop
|
||||
if P.downing>ENV.sddas and (P.downing-ENV.sddas)%ENV.sdarr==0 then
|
||||
dist=1/D+1
|
||||
else
|
||||
dist=1/D
|
||||
end
|
||||
-- Update block state
|
||||
if P.control then
|
||||
-- Try spawn new block
|
||||
if not P.cur then
|
||||
if not stopAtFalling and P.waiting>0 then
|
||||
P.waiting=P.waiting-1
|
||||
end
|
||||
if P.waiting<=0 then
|
||||
P:popNext()
|
||||
end
|
||||
break-- goto THROW_stop
|
||||
end
|
||||
|
||||
-- Limit dropping to ghost at max
|
||||
dist=min(dist,P.curY-P.ghoY)
|
||||
|
||||
-- Drop and create FXs
|
||||
if ENV.moveFX and ENV.block and dist>1 then
|
||||
for _=1,dist do
|
||||
P:createMoveFX('down')
|
||||
P.curY=P.curY-1
|
||||
-- Natural block falling
|
||||
if P.cur then
|
||||
if P.curY>P.ghoY then
|
||||
local D=P.dropDelay
|
||||
local dist-- Drop distance
|
||||
if D>1 then
|
||||
D=D-1
|
||||
if P.keyPressing[7] and P.downing>=ENV.sddas then
|
||||
D=D-ceil(ENV.drop/ENV.sdarr)
|
||||
end
|
||||
if D<=0 then
|
||||
dist=1
|
||||
P.dropDelay=(D-1)%ENV.drop+1
|
||||
else
|
||||
P.dropDelay=D
|
||||
break-- goto THROW_stop
|
||||
end
|
||||
elseif D==1 then-- We don't know why dropDelay is 1, so checking ENV.drop>1 is neccessary
|
||||
if ENV.drop>1 and P.downing>=ENV.sddas and (P.downing-ENV.sddas)%ENV.sdarr==0 then
|
||||
dist=2
|
||||
else
|
||||
dist=1
|
||||
end
|
||||
-- Reset drop delay
|
||||
P.dropDelay=ENV.drop
|
||||
else-- High gravity case (>1G)
|
||||
-- Add extra 1 if time to auto softdrop
|
||||
if P.downing>ENV.sddas and (P.downing-ENV.sddas)%ENV.sdarr==0 then
|
||||
dist=1/D+1
|
||||
else
|
||||
dist=1/D
|
||||
end
|
||||
end
|
||||
|
||||
-- Limit dropping to ghost at max
|
||||
dist=min(dist,P.curY-P.ghoY)
|
||||
|
||||
-- Drop and create FXs
|
||||
if ENV.moveFX and ENV.block and dist>1 then
|
||||
for _=1,dist do
|
||||
P:createMoveFX('down')
|
||||
P.curY=P.curY-1
|
||||
end
|
||||
else
|
||||
P.curY=P.curY-dist
|
||||
end
|
||||
|
||||
P.spinLast=false
|
||||
P:freshBlock('fresh')
|
||||
P:checkTouchSound()
|
||||
else
|
||||
P.curY=P.curY-dist
|
||||
end
|
||||
|
||||
P.spinLast=false
|
||||
P:freshBlock('fresh')
|
||||
P:checkTouchSound()
|
||||
else
|
||||
P.lockDelay=P.lockDelay-1
|
||||
if P.lockDelay>=0 then
|
||||
goto THROW_stop
|
||||
end
|
||||
P:drop(true)
|
||||
if P.bot then
|
||||
P.bot:lockWrongPlace()
|
||||
P.lockDelay=P.lockDelay-1
|
||||
if P.lockDelay>=0 then
|
||||
break-- goto THROW_stop
|
||||
end
|
||||
P:drop(true)
|
||||
if P.bot then
|
||||
P.bot:lockWrongPlace()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
::THROW_stop::
|
||||
until true
|
||||
-- ::THROW_stop::
|
||||
|
||||
-- B2B bar animation
|
||||
if P.b2b1~=P.b2b then
|
||||
@@ -2911,16 +2925,20 @@ function Player:lose(force)
|
||||
self:dropPosition()
|
||||
freshPlayerPosition('update')
|
||||
|
||||
local finished=true
|
||||
for i=1,#PLY_ALIVE-1 do
|
||||
if PLY_ALIVE[i].group==0 or PLY_ALIVE[i].group~=PLY_ALIVE[i+1].group then
|
||||
goto BREAK_notFinished
|
||||
finished=false
|
||||
break-- goto BREAK_notFinished
|
||||
end
|
||||
end
|
||||
-- Only 1 people or only 1 team survived, they win
|
||||
for i=1,#PLY_ALIVE do
|
||||
PLY_ALIVE[i]:win()
|
||||
if finished then
|
||||
for i=1,#PLY_ALIVE do
|
||||
PLY_ALIVE[i]:win()
|
||||
end
|
||||
end
|
||||
::BREAK_notFinished::
|
||||
-- ::BREAK_notFinished::
|
||||
end
|
||||
end
|
||||
--------------------------<\Event>--------------------------
|
||||
|
||||
@@ -65,13 +65,15 @@ local seqGenerators={
|
||||
local r
|
||||
for _=1,hisLen do-- Reroll up to [hisLen] times
|
||||
r=rndGen:random(len)
|
||||
local rollAgain
|
||||
for i=1,hisLen do
|
||||
if r==history[i] then
|
||||
goto CONTINUE_rollAgain
|
||||
rollAgain=true
|
||||
break-- goto CONTINUE_rollAgain
|
||||
end
|
||||
end
|
||||
do break end
|
||||
::CONTINUE_rollAgain::
|
||||
if not rollAgain then break end
|
||||
-- ::CONTINUE_rollAgain::
|
||||
end
|
||||
if history[1]~=0 then
|
||||
P:getNext(seq0[r])
|
||||
@@ -128,16 +130,21 @@ local seqGenerators={
|
||||
-- print"======================"
|
||||
-- Pick a mino from pool
|
||||
local tryTime=0
|
||||
::REPEAT_pickAgain::
|
||||
local r=_poolPick()-- Random mino-index in pool
|
||||
for i=1,len do
|
||||
if r==history[i] then
|
||||
tryTime=tryTime+1
|
||||
if tryTime<hisLen then
|
||||
goto REPEAT_pickAgain
|
||||
local r
|
||||
repeat-- ::REPEAT_pickAgain::
|
||||
local pickAgain
|
||||
r=_poolPick()-- Random mino-index in pool
|
||||
for i=1,len do
|
||||
if r==history[i] then
|
||||
tryTime=tryTime+1
|
||||
if tryTime<hisLen then
|
||||
pickAgain=true
|
||||
break-- goto REPEAT_pickAgain
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not pickAgain then break end
|
||||
until true
|
||||
|
||||
-- Give mino to player & update history
|
||||
if history[1]~=0 then
|
||||
|
||||
@@ -38,13 +38,15 @@ local function restart()
|
||||
end
|
||||
local function checkBoard(b,p)
|
||||
for i=1,8 do
|
||||
local testNextLine
|
||||
for j=1,3 do
|
||||
if b[lines[i][j]]~=p then
|
||||
goto CONTINUE_testNextLine
|
||||
testNextLine=true
|
||||
break-- goto CONTINUE_testNextLine
|
||||
end
|
||||
end
|
||||
do return true end
|
||||
::CONTINUE_testNextLine::
|
||||
if not testNextLine then return true end
|
||||
-- ::CONTINUE_testNextLine::
|
||||
end
|
||||
end
|
||||
local function full(L)
|
||||
|
||||
@@ -127,8 +127,9 @@ local function checkLink(x1,y1,x2,y2)
|
||||
while ruy>1 and not field[ruy-1][x2] do ruy=ruy-1 end
|
||||
while rdy<field.r and not field[rdy+1][x2] do rdy=rdy+1 end
|
||||
for y=max(luy,ruy),min(ldy,rdy) do
|
||||
for x=x1+1,x2-1 do if field[y][x] then goto CONTINUE_nextRow end end
|
||||
do
|
||||
local nextLine
|
||||
for x=x1+1,x2-1 do if field[y][x] then nextLine=true break end end-- goto CONTINUE_nextRow
|
||||
if not nextLine then
|
||||
local len=abs(x1-x2)+abs(y-y1)+abs(y-y2)
|
||||
if len<bestLen then
|
||||
bestLen=len
|
||||
@@ -138,7 +139,7 @@ local function checkLink(x1,y1,x2,y2)
|
||||
addPoint(bestLine,x2,y2)
|
||||
end
|
||||
end
|
||||
::CONTINUE_nextRow::
|
||||
-- ::CONTINUE_nextRow::
|
||||
end
|
||||
end
|
||||
-- X-Y-X Check
|
||||
@@ -150,8 +151,9 @@ local function checkLink(x1,y1,x2,y2)
|
||||
while dlx>1 and not field[y2][dlx-1] do dlx=dlx-1 end
|
||||
while drx<field.c and not field[y2][drx+1] do drx=drx+1 end
|
||||
for x=max(ulx,dlx),min(urx,drx) do
|
||||
for y=y1+1,y2-1 do if field[y][x] then goto CONTINUE_nextCol end end
|
||||
do
|
||||
local nextLine
|
||||
for y=y1+1,y2-1 do if field[y][x] then nextLine=true break end end-- goto CONTINUE_nextCol
|
||||
if not nextLine then
|
||||
local len=abs(y1-y2)+abs(x-x1)+abs(x-x2)
|
||||
if len<bestLen then
|
||||
bestLen=len
|
||||
@@ -161,7 +163,7 @@ local function checkLink(x1,y1,x2,y2)
|
||||
addPoint(bestLine,x2,y2)
|
||||
end
|
||||
end
|
||||
::CONTINUE_nextCol::
|
||||
-- ::CONTINUE_nextCol::
|
||||
end
|
||||
end
|
||||
return bestLine
|
||||
|
||||
@@ -153,32 +153,34 @@ function player:click(y,x)
|
||||
SFX.play('touch')
|
||||
|
||||
local merged
|
||||
::REPEAT_merge::
|
||||
local cur=self.board[y][x]
|
||||
local b1=TABLE.shift(self.board)
|
||||
self.mergedTiles={}
|
||||
local count=self:merge(b1,cur,y,x)
|
||||
if count>2 then
|
||||
merged=true
|
||||
self.board=b1
|
||||
b1[y][x]=cur+1
|
||||
repeat-- ::REPEAT_merge::
|
||||
local repeating
|
||||
local cur=self.board[y][x]
|
||||
local b1=TABLE.shift(self.board)
|
||||
self.mergedTiles={}
|
||||
local count=self:merge(b1,cur,y,x)
|
||||
if count>2 then
|
||||
merged=true
|
||||
self.board=b1
|
||||
b1[y][x]=cur+1
|
||||
|
||||
if cur+1>self.maxTile then
|
||||
self.maxTile=cur+1
|
||||
if self.maxTile>=6 then
|
||||
ins(self.progress,("%s - %.3fs"):format(self.maxTile,TIME()-player.startTime))
|
||||
if cur+1>self.maxTile then
|
||||
self.maxTile=cur+1
|
||||
if self.maxTile>=6 then
|
||||
ins(self.progress,("%s - %.3fs"):format(self.maxTile,TIME()-player.startTime))
|
||||
end
|
||||
SFX.play('reach')
|
||||
end
|
||||
SFX.play('reach')
|
||||
end
|
||||
|
||||
local getScore=4^cur*count
|
||||
self.score=self.score+getScore
|
||||
TEXT.show(getScore,player.x+self.selectX*100-50,player.y+self.selectY*100-50,40,'score',1.626/math.log(getScore,3))
|
||||
for i=1,#self.mergedTiles do
|
||||
newMergeFX(self.mergedTiles[i][1],self.mergedTiles[i][2],cur+1)
|
||||
local getScore=4^cur*count
|
||||
self.score=self.score+getScore
|
||||
TEXT.show(getScore,player.x+self.selectX*100-50,player.y+self.selectY*100-50,40,'score',1.626/math.log(getScore,3))
|
||||
for i=1,#self.mergedTiles do
|
||||
newMergeFX(self.mergedTiles[i][1],self.mergedTiles[i][2],cur+1)
|
||||
end
|
||||
repeating=true-- goto REPEAT_merge
|
||||
end
|
||||
goto REPEAT_merge
|
||||
end
|
||||
until not repeating
|
||||
|
||||
ins(self.nexts,self:newTile())
|
||||
|
||||
|
||||
@@ -104,20 +104,23 @@ function scene.keyDown(key,isRep)
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local str=sys.getClipboardText()
|
||||
local args=str:sub((str:find(":") or 0)+1):split("!")
|
||||
if #args<4 then goto THROW_fail end
|
||||
if not (
|
||||
DATA.pasteQuestArgs(args[1]) and
|
||||
DATA.pasteSequence(args[2]) and
|
||||
DATA.pasteMission(args[3])
|
||||
) then goto THROW_fail end
|
||||
TABLE.cut(FIELD)
|
||||
FIELD[1]=DATA.newBoard()
|
||||
for i=4,#args do
|
||||
if args[i]:find("%S") and not DATA.pasteBoard(args[i],i-3) and i<#args then goto THROW_fail end
|
||||
end
|
||||
MES.new('check',text.importSuccess)
|
||||
do return end
|
||||
::THROW_fail::MES.new('error',text.dataCorrupted)
|
||||
repeat
|
||||
if #args<4 then break end-- goto THROW_fail
|
||||
if not (
|
||||
DATA.pasteQuestArgs(args[1]) and
|
||||
DATA.pasteSequence(args[2]) and
|
||||
DATA.pasteMission(args[3])
|
||||
) then break end-- goto THROW_fail
|
||||
TABLE.cut(FIELD)
|
||||
FIELD[1]=DATA.newBoard()
|
||||
for i=4,#args do
|
||||
if args[i]:find("%S") and not DATA.pasteBoard(args[i],i-3) and i<#args then break end-- goto THROW_fail
|
||||
end
|
||||
MES.new('check',text.importSuccess)
|
||||
return
|
||||
until true
|
||||
-- ::THROW_fail::
|
||||
MES.new('error',text.dataCorrupted)
|
||||
else
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -195,14 +195,17 @@ function scene.keyDown(key)
|
||||
local F=FIELD[page]
|
||||
local cleared=false
|
||||
for i=#F,1,-1 do
|
||||
local full
|
||||
for j=1,10 do
|
||||
if F[i][j]<=0 then goto CONTINUE_notFull end
|
||||
if F[i][j]<=0 then full=false break end-- goto CONTINUE_notFull
|
||||
end
|
||||
cleared=true
|
||||
SYSFX.newShade(3,200,660-30*i,300,30)
|
||||
SYSFX.newRectRipple(3,200,660-30*i,300,30)
|
||||
rem(F,i)
|
||||
::CONTINUE_notFull::
|
||||
if full then
|
||||
cleared=true
|
||||
SYSFX.newShade(3,200,660-30*i,300,30)
|
||||
SYSFX.newRectRipple(3,200,660-30*i,300,30)
|
||||
rem(F,i)
|
||||
end
|
||||
-- ::CONTINUE_notFull::
|
||||
end
|
||||
if cleared then
|
||||
SFX.play('clear_3',.8)
|
||||
|
||||
@@ -195,15 +195,19 @@ function scene.touchMove()
|
||||
for n=1,#keys do
|
||||
local B=keys[n]
|
||||
if B.ava then
|
||||
local nextKey
|
||||
for i=1,#L,2 do
|
||||
if (L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
|
||||
goto CONTINUE_nextKey
|
||||
nextKey=true
|
||||
break-- goto CONTINUE_nextKey
|
||||
end
|
||||
end
|
||||
PLAYERS[1]:releaseKey(n)
|
||||
VK.release(n)
|
||||
if not nextKey then
|
||||
PLAYERS[1]:releaseKey(n)
|
||||
VK.release(n)
|
||||
end
|
||||
-- ::CONTINUE_nextKey::
|
||||
end
|
||||
::CONTINUE_nextKey::
|
||||
end
|
||||
end
|
||||
function scene.keyDown(key,isRep)
|
||||
|
||||
@@ -109,15 +109,19 @@ function scene.touchMove()
|
||||
for n=1,#keys do
|
||||
local B=keys[n]
|
||||
if B.ava then
|
||||
local nextKey
|
||||
for i=1,#L,2 do
|
||||
if (L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
|
||||
goto CONTINUE_nextKey
|
||||
nextKey=true
|
||||
break-- goto CONTINUE_nextKey
|
||||
end
|
||||
end
|
||||
PLAYERS[1]:releaseKey(n)
|
||||
VK.release(n)
|
||||
if not nextKey then
|
||||
PLAYERS[1]:releaseKey(n)
|
||||
VK.release(n)
|
||||
end
|
||||
-- ::CONTINUE_nextKey::
|
||||
end
|
||||
::CONTINUE_nextKey::
|
||||
end
|
||||
end
|
||||
function scene.keyDown(key,isRep)
|
||||
|
||||
Reference in New Issue
Block a user