240 lines
7.1 KiB
Lua
240 lines
7.1 KiB
Lua
local ins,rem=table.insert,table.remove
|
|
local yield=coroutine.yield
|
|
|
|
local seqGenerators={
|
|
none=function() while true do yield() end end,
|
|
bag=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local bag={}
|
|
while true do
|
|
if #bag==0 then
|
|
for i=1,len do
|
|
bag[i]=seq0[len-i+1]
|
|
end
|
|
end
|
|
yield(rem(bag,rndGen:random(#bag)))
|
|
end
|
|
end,
|
|
bagES=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local bag=TABLE.shift(seq0)
|
|
do-- Get a good first-bag
|
|
-- Shuffle
|
|
for i=1,len-1 do ins(bag,rem(bag,rndGen:random(len-i+1))) end
|
|
-- Skip Uncomfortable minoes
|
|
for _=1,len-1 do
|
|
if
|
|
bag[1]==1 or bag[1]==2 or bag[1]==6 or bag[1]==8 or bag[1]==9 or
|
|
bag[1]==12 or bag[1]==13 or
|
|
bag[1]==17 or bag[1]==18 or
|
|
bag[1]==23 or bag[1]==24
|
|
then
|
|
ins(bag,rem(bag,1))
|
|
else
|
|
break
|
|
end
|
|
end
|
|
-- Finish
|
|
for i=1,len do yield(bag[i]) end
|
|
end
|
|
bag={}
|
|
while true do
|
|
if #bag==0 then
|
|
for i=1,len do
|
|
bag[i]=seq0[len-i+1]
|
|
end
|
|
end
|
|
yield(rem(bag,rndGen:random(#bag)))
|
|
end
|
|
end,
|
|
his=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local hisLen=math.ceil(len*.5)
|
|
local history=TABLE.new(0,hisLen)
|
|
while true do
|
|
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
|
|
rollAgain=true
|
|
break-- goto CONTINUE_rollAgain
|
|
end
|
|
end
|
|
if not rollAgain then break end
|
|
-- ::CONTINUE_rollAgain::
|
|
end
|
|
if history[1]~=0 then
|
|
yield(seq0[r])
|
|
end
|
|
rem(history,1)
|
|
ins(history,r)
|
|
end
|
|
end,
|
|
hisPool=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local hisLen=math.ceil(len*.5)
|
|
local history=TABLE.new(0,hisLen)-- Indexes of mino-index
|
|
|
|
local poolLen=5*len
|
|
local droughtTimes=TABLE.new(len,len)-- Drought times of seq0
|
|
local pool={} for i=1,len do for _=1,5 do ins(pool,i) end end-- 5 times indexes of seq0
|
|
local function _poolPick()
|
|
local r=rndGen:random(poolLen)
|
|
local res=pool[r]
|
|
|
|
-- Find droughtest(s) minoes
|
|
local droughtList={1}-- Droughtst minoes' indexes of seq0
|
|
local maxTime=droughtTimes[1]
|
|
for i=2,len do
|
|
if droughtTimes[i]>maxTime then
|
|
maxTime=droughtTimes[i]
|
|
if #droughtList==1 then
|
|
droughtList[1]=i
|
|
else
|
|
droughtList={i}
|
|
end
|
|
elseif droughtTimes[i]==maxTime then
|
|
ins(droughtList,i)
|
|
end
|
|
end
|
|
|
|
-- Update droughtTimes
|
|
for i=1,len do droughtTimes[i]=droughtTimes[i]+1 end
|
|
droughtTimes[res]=0
|
|
|
|
-- Update pool
|
|
-- print("Rem "..res)
|
|
pool[r]=droughtList[rndGen:random(#droughtList)]
|
|
-- print("Add "..pool[r])
|
|
|
|
return res
|
|
end
|
|
|
|
while true do
|
|
-- print"======================"
|
|
-- Pick a mino from pool
|
|
local tryTime=0
|
|
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
|
|
if not pickAgain then break end
|
|
until true
|
|
|
|
-- Give mino to player & update history
|
|
if history[1]~=0 then
|
|
yield(seq0[r])
|
|
end
|
|
rem(history,1)
|
|
ins(history,r)
|
|
-- print("Player GET: "..r)
|
|
-- print("History: "..table.concat(history,","))
|
|
-- local L=TABLE.new("",len)
|
|
-- for _,v in next,pool do L[v]=L[v].."+" end
|
|
-- for i=1,#L do print(i,droughtTimes[i],L[i]) end
|
|
end
|
|
end,
|
|
c2=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local weight=TABLE.new(0,len)
|
|
|
|
while true do
|
|
local maxK=1
|
|
for i=1,len do
|
|
weight[i]=weight[i]*.5+rndGen:random()
|
|
if weight[i]>weight[maxK] then
|
|
maxK=i
|
|
end
|
|
end
|
|
weight[maxK]=weight[maxK]/3.5
|
|
yield(seq0[maxK])
|
|
end
|
|
end,
|
|
rnd=function(rndGen,seq0)
|
|
if #seq0==1 then
|
|
local i=seq0[1]
|
|
while true do
|
|
yield(i)
|
|
end
|
|
else
|
|
local len=#seq0
|
|
local last=0
|
|
while true do
|
|
local r=rndGen:random(len-1)
|
|
if r>=last then
|
|
r=r+1
|
|
end
|
|
yield(seq0[r])
|
|
last=r
|
|
end
|
|
end
|
|
end,
|
|
mess=function(rndGen,seq0)
|
|
while true do
|
|
yield(seq0[rndGen:random(#seq0)])
|
|
end
|
|
end,
|
|
reverb=function(rndGen,seq0)
|
|
local bufferSeq,bag={},{}
|
|
while true do
|
|
if #bag==0 then
|
|
for i=1,#seq0 do bufferSeq[i]=seq0[i] end
|
|
repeat
|
|
local r=rem(bufferSeq,rndGen:random(#bag))
|
|
local p=1
|
|
repeat
|
|
ins(bag,r)
|
|
p=p-.15-rndGen:random()
|
|
until p<0
|
|
until #bufferSeq==0
|
|
for i=1,#bag do
|
|
bufferSeq[i]=bag[i]
|
|
end
|
|
end
|
|
yield(rem(bag,rndGen:random(#bag)))
|
|
end
|
|
end,
|
|
loop=function(rndGen,seq0)
|
|
local len=#seq0
|
|
local bag={}
|
|
while true do
|
|
if #bag==0 then
|
|
for i=1,len do
|
|
bag[i]=seq0[len-i+1]
|
|
end
|
|
end
|
|
yield(rem(bag))
|
|
end
|
|
end,
|
|
fixed=function(rndGen,seq0)
|
|
for i=#seq0,1,-1 do
|
|
yield(seq0[i])
|
|
end
|
|
end,
|
|
}
|
|
return function(s)-- Return a piece-generating function for player P
|
|
if type(s)=='function' then
|
|
return s
|
|
elseif type(s)=='string' and seqGenerators[s] then
|
|
return seqGenerators[s]
|
|
else
|
|
MES.new('warn',
|
|
type(s)=='string' and
|
|
"No sequence mode called "..s or
|
|
"Wrong sequence generator"
|
|
)
|
|
return seqGenerators.bag
|
|
end
|
|
end
|