Code
--[[
Quake shear - a Quake by slice with shearing by Marie Suchard
based on Rav3n Quake R and Quake slice V1.3
]]--
--- options there VVVV
maxLoss=0.5 --minimum percentage loss when pulling. ie 5% of 10000 is 500pts
pullingCI=0.9 --clash importance while pulling
doFuze=-1 --run fuze when score after qstabilize is close to best (negative - if gain after qstab)
maxns=8 -- maximum number of slices
fastQstab=false --if true ony 1s1w as stabilize after pull
--- end of options ^^^
local function _abs(value)
if value < 0 then
value = -value
end
return value
end
math=
{
abs = _abs,
}
function Score()
return current.GetScore()
end
P = print --a short
p=P
CI=behavior.SetClashImportance
segCount = structure.GetCount() --always the same
function qStab()
selection.SelectAll()
CI(0.1)
Wiggle("s",1)
if fastQstab==false then
CI(0.4)
Wiggle("wa",1)
CI(1)
Wiggle("s",1)
end
CI(1)
Wiggle()
end
function FuzeEnd()
CI(1)
Wiggle("wa",1)
Wiggle("s",1)
Wiggle()
SaveBest()
end
function Fuze1(ci1,ci2)
CI(ci1)
Wiggle("s",1)
CI(ci2)
Wiggle("wa",1)
end
function Fuze2(ci1,ci2)
CI(ci1)
Wiggle("wa",1)
CI(1)
Wiggle("wa",1)
CI(ci2)
Wiggle("wa",1)
end
function reFuze(scr)
local s=Score()
if s<scr then
save.Quickload(4)
else
scr=s
save.Quicksave(4)
end
return scr
end
function Fuze()
local scr=Score()
save.Quicksave(4)
selection.SelectAll()
Fuze1(0.3,0.6) FuzeEnd()
scr=reFuze(scr)
Fuze2(0.3,1) SaveBest()
scr=reFuze(scr)
Fuze1(0.05,1) SaveBest()
scr=reFuze(scr)
Fuze2(0.7,0.5) FuzeEnd()
scr=reFuze(scr)
Fuze1(0.07,1) SaveBest()
reFuze(scr)
end
bestScore=Score()
function SaveBest()
local s=Score()
local g=s-bestScore
if g>0 then
P("Gained another ",round(g)," pts.")
bestScore=s
save.Quicksave(3)
end
end
function Wiggle(how, iters, minppi) --score conditioned recursive wiggle/shake
if how==nil then how="wa" end
if iters==nil then iters=6 end
if minppi==nil then minppi=0.04 end
if iters>0 then
iters=iters-1
local sp=Score()
if how == "s" then structure.ShakeSidechainsSelected(1)
elseif how == "wb" then structure.WiggleSelected(2,true,false)
elseif how == "ws" then structure.WiggleSelected(2,false,true)
elseif how == "wa" then structure.WiggleSelected(2)
end
local ig=Score()-sp
if ig > minppi then return Wiggle(how, iters, minppi) end --recurence tail call ;]
end
end
function bandstr(str) --set all band strengt
for i=1, band.GetCount() do
band.SetStrength(i, str)
end
end
function delBands() --delete all bands
band.DeleteAll()
end
function down(x)--cut all after comma
return x-x%1
end
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function SaveRB()
save.Quicksave(4)
recentbest.Restore()
SaveBest()
save.Quickload(4)
end
function Quakel()--a Quake
--freeze.UnfreezeAll()
save.Quicksave(3)
P("Starting Quake shear. Start score: ",round(qsc))
selection.DeselectAll()
local loss=math.abs(down(Score()*maxLoss/100))
P("Pulling until loss of ",loss," pts.")
untrois=1
for ns=1,maxns do
for sl=1 ,ns do
delBands()
maxl=0 unl=0 deuxl=0 maxr=0 troisl=0 quatrel=0
for i=1,segCount-1 do
local liun=structure.GetDistance(i,un)
for j=i+1,segCount do
local ljun=structure.GetDistance(j,un)
local lij=structure.GetDistance(i,j)
if liun>=(sl-1)*max /ns and liun<=sl*max/ns
and ljun>=(sl-1)*max /ns and ljun<=sl*max/ns then
if lij> maxl then
unl=i deuxl=j maxl=lij
end -- great than maxl
end -- in the slice
end --j
end --i
if unl>0 and deuxl>0 and maxl>0 then
for i=1,segCount-1 do
local liun=structure.GetDistance(i,un)
local litrois=structure.GetDistance(i,unl)
if litrois< maxl/2 +2 and litrois > maxl/2 - 2 then
for j=i+1,segCount do
local ljun=structure.GetDistance(i,un)
local ljtrois=structure.GetDistance(j,unl)
if ljtrois< maxl/2 +2 and ljtrois > maxl/2 - 2 then
local lij=structure.GetDistance(i,j)
if liun>=(sl-1)*max /ns and liun<=sl*max/ns
and ljun>=(sl-1)*max /ns and ljun<=sl*max/ns then
if lij> maxr then
troisl=i quatrel=j maxr=lij
end -- great than maxr
end --
end -- in the slice
end --j
end --if middle
end --i
end
if ns==1 then trois=troisl end
untrois=-1*untrois
print(sl,'/',ns,'/',maxns,' pole1: ', unl, ' pole2: ', deuxl, ' mountain1: ', troisl, ' moutain2: ',quatrel)
if unl>0 and deuxl>0 and maxl>0 and troisl>0 and quatrel>0 then --check possibility
for y=1,segCount do
local lyun=structure.GetDistance(y,un)
if lyun>=(sl-1)*max /ns and lyun<=sl*max/ns then
if (structure.GetDistance(y,troisl) - structure.GetDistance(y,quatrel) ) * untrois <0
then
mins=deuxl
autre=unl
else
mins=unl
autre=deuxl
end
if math.abs(y-mins)>0 and math.abs(y-autre) >0 and structure.GetDistance (y,mins)-structure.GetDistance (y,autre) > 3 then
band.Add(y,mins,autre,structure.GetDistance (y,mins),3.14159265/2,0)
band.SetGoalLength(band.GetCount(),structure.GetDistance (y,mins)-3)
end -- not the pole, not the center
end -- in the slice
end -- y
end -- check possibility
if band.GetCount()>0 then --check do we have any band
selection.SelectAll()
behavior.SetClashImportance(pullingCI)
recentbest.Save()
for str=1,2,0.5 do--search enough band strenght to move
recentbest.Restore()--because sometimes it makes points during pull :D
ss=Score()
bandstr(str)
structure.WiggleSelected(1,true,false)
if ss-Score()>loss then break end
end
behavior.SetClashImportance(1)
delBands()
SaveRB() --because sometimes it missing fractions
recentbest.Save() --after pulling
qStab()
if bestScore-Score()<doFuze then
SaveBest()
Fuze()
end
SaveBest()
save.Quickload(3) --load best state
P("Current score: ",round(Score())," Total gain: ",round(Score()-qsc))
end
end -- slice
end -- number of slice
end -- quake
max=0 un=0 deux=0
P("Searching for central axe...")
for i=1,segCount-1 do
for j=2,segCount do
local len=structure.GetDistance(i,j)
if len > max then
un=i
deux=j
max=len
end
end
end
--main call
qsc=Score() --starting score
Quakel()
un=trois --other side
Quakel()
--end of script