Icon representing a recipe

Recipe: Tvdl VoidCrushers 3.0.1 B

created by Mike Cassidy

Profile


Name
Tvdl VoidCrushers 3.0.1 B
ID
100732
Shared with
Public
Parent
Tvdl VoidCrushers 3.0.1
Children
None
Created on
February 25, 2015 at 19:33 PM UTC
Updated on
February 25, 2015 at 19:33 PM UTC
Description

Temp fix for Exploration Bug
Wiggle Factor added

Best for


Code


--[[ Voids Killer by rav3n_pl script is searching for possible banding across voids. Because we not have any voids detection in Lua, I do some math to find them Not always perfect, but mostly works :) Tvdl: 09-01-2012 Added extra option to pull all the bands in one go, pulls harder, if wanted, on hydro's Works also as a stabelizer (like Hydrophobic script) Compacts the protein Warning: when used allatonce will accept a loss If so the previous score is in slot 3 Tvdl: 12-07-2012 - Made totally V2 MDC: 2-19-2014 Added Wiggle Factor ]]-- -- Handy shorts module if current.GetExplorationMultiplier == nil then normal = 0 end CI=behavior.SetClashImportance segCnt=structure.GetCount() segCnt2=segCnt while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 end -- Score functions function Score() if normal==nil or normal==true then -- FIX for big negatives local total= current.GetEnergyScore() if total < -999999 and total > -1000001 then total=SegScore() end return total else return current.GetScore() end end function SegScore() local total=8000 for i=1,segCnt2 do total=total+current.GetSegmentEnergyScore(i) end return total end function RBScore() if normal then return recentbest.GetEnergyScore() else return recentbest.GetScore() end end function round3(x)--cut all afer 3-rd place return x-x%0.001 end bestScore=Score() function SaveBest() local g=Score()-bestScore if g>0 then if g>0.01 then print("Gained another "..round3(g).." pts.") end bestScore=Score() save.Quicksave(3) end end -- New WiggleFactor WF=1 -- Wiggle function -- Optimized due to Susumes ideas -- Note the extra parameter to be used if only selected parts must be done function Wiggle(how, iters, minppi,onlyselected) --score conditioned recursive wiggle/shake --fixed a bug, absolute difference is the threshold now if how==nil then how="wa" end if iters==nil then iters=3 end if minppi==nil then minppi=0.1 end if onlyselected==nil then onlyselected=false end local wf=1 if maxCI then wf=WF end --print("Wiggle FactorA= ",WF) --if iters>0 then --iters=iters-1 local sp=Score() if onlyselected then if how == "s" then -- Shake is not considered to do much in second or more rounds structure.ShakeSidechainsSelected(1) return elseif how == "wb" then structure.WiggleSelected(2*wf*iters,true,false) elseif how == "ws" then structure.WiggleSelected(2*wf*iters,false,true) elseif how == "wa" then structure.WiggleSelected(2*wf*iters,true,true) end else if how == "s" then -- Shake is not considered to do much in second or more rounds structure.ShakeSidechainsAll(1) return elseif how == "wb" then structure.WiggleAll(2*wf*iters,true,false) elseif how == "ws" then structure.WiggleAll(2*wf*iters,false,true) elseif how == "wa" then structure.WiggleAll(2*wf*iters,true,true) end end --if math.abs(Score()-sp) > minppi then return Wiggle(how, iters, minppi,onlyselected) end --end end -- end of handy shorts module -- Standard Fuze module -- Picks up all gains by using recentbest function FuzeEnd() CI(1) Wiggle("wa",1) Wiggle("s",1) Wiggle() if RBScore()> Score() then recentbest.Restore() end 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,slot) local s=Score() if s<scr then save.Quickload(slot) else scr=s save.Quicksave(slot) end return scr end function Fuze(slot) local scr=Score() recentbest.Save() Fuze1(0.3,0.6) FuzeEnd() scr=reFuze(scr,slot) Fuze2(0.3,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() scr=reFuze(scr,slot) Fuze1(0.05,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() scr=reFuze(scr,slot) Fuze2(0.7,0.5) FuzeEnd() scr=reFuze(scr,slot) Fuze1(0.07,1) if RBScore()>Score() then recentbest.Restore() end SaveBest() reFuze(scr,slot) if RBScore()>Score() then recentbest.Restore() end SaveBest() end -- end standard Fuze module -- Distance lib -- distances={} distScore=Score() function getDist() -- 1 dim for speed if #distances<1 or distScore ~= Score() then distScore=Score() distances[1]=0 print("Calculating distances...") for i=1,segCnt do --filling table for j=i+1,segCnt do --not counting from beginning - not need :) distances[i*segCnt+j]=structure.GetDistance(i,j) end end print("Done") end end function dist(a,b) if a==b then return 0 end if a>b then a,b=b,a end return distances[a*segCnt+b] end -- Safe band module ExistingBands=band.GetCount() function disableExistingBands() for i=1,ExistingBands do band.Disable(i) end end function enableExistingBands() for i=1,ExistingBands do band.Enable(i) end end function bandDisableAll() for i=ExistingBands+1,band.GetCount() do band.Disable(i) end end function bandEnableAll() for i=ExistingBands+1,band.GetCount() do band.Enable(i) end end function bandDeleteAll() for i=ExistingBands+1,band.GetCount() do band.Delete(ExistingBands+1) end end function bandSetStrengthAll(str) for i=ExistingBands+1,band.GetCount() do band.SetStrength(i,str) end end function bandGetCount() return band.GetCount()-ExistingBands end -- end safe band module function down(x) return x-x%1 end function qStab() 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 math.randomseed(Score()) math.random(100) -- Because first random is not random function Sort(tab,items) for x=1,items do for y=x+1,#tab do if tab[x][2]>tab[y][2] then tab[x],tab[y]=tab[y],tab[x] end end end return tab end function mkBand(a) --make band if found void in area of that segment print("Banding segment "..a) getDist() local t={}--there we store possible segments local first=1 if allatonce then first=a+2 end if first > segCnt then return false end for b=first,segCnt do --test all segments if useRegionBool[a] or useRegionBool[b] then local ab=dist(a,b) --distance between segments if ab>minLength and ab < maxLength and math.abs(a-b) >= minDist then --no void if less --p(a," ",b," ",ab) local void=true for c=1,segCnt do --searhing that is any segment between them local ac=dist(a,c) local bc=dist(b,c) if ac~=0 and bc~=0 and ac<ab and bc<ab and ac>4 and bc>4 then if ac+bc<ab+1.5 then void=false break --no void there for sure end end end if void==true and (not allatonce or a<b) then t[#t+1]={a,b} end end end end if #t>0 then print("Found "..#t.." possible bands across voids") for i=1,#t do local s=t[i][1] local e=t[i][2] band.AddBetweenSegments(s,e) local d=dist(s,e) d=d-compFrac if d<3 then d=3 end if d>20 then d=20 end local bnr=band.GetCount() band.SetGoalLength(bnr,d) if allatonce then if structure.IsHydrophobic(s) or structure.IsHydrophobic(e) then band.SetStrength(bnr,pullextrahydro*allBS) else band.SetStrength(bnr,allBS) end end end else print("No voids found") end end function SaveRB() if RBScore() > Score() then save.Quicksave(9) recentbest.Restore() SaveBest() save.Quickload(9) end end function Pull(List) disableExistingBands() if List==nil then for i=1,segCnt do mkBand(i) end else for i=1,#List do mkBand(List[i]) end end if bandGetCount()>0 then CI(pullingCI) -- Make an estimation of the required strength if lastAllBS > 0 then lastBS=lastAllBS/bandGetCount() end if lastBS < minBS then lastBS=minBS end if lastBS > maxBS then lastBS=maxBS end recentbest.Save() local loss=math.abs(down(Score()*maxLoss/100)) for str=lastBS,maxBS,0.11 do --search enough band strenght to move recentbest.Restore() ss=Score() if not allatonce then bandSetStrengthAll(str) end Wiggle("wb",1) if ss-Score()>loss then lastAllBS=(str-0.1)*bandGetCount() break end end bandDeleteAll() SaveRB() --because sometimes it missing fractions print("Stabilizing...") CI(1) recentbest.Save() --after pulling qStab() if bestScore-Score()<doFuze or allatonce then SaveBest() print("Fuzing....") Fuze(4) end if not allatonce then save.Quickload(3) --load best state end print("Current score: "..round3(Score()).." Total gain: "..round3(Score()-qsc)) end end function KillVoids() save.Quicksave(3) qsc=Score() if allatonce then lastBS=allBS minBS=allBS maxBS=allBS end lastBS=minBS local s={} print("Starting Void Crusher v3.0.0 by Tvdl (base is from rav3n_pl)") print("Start score:"..round3(qsc)) getDist() --calculate distances now if #Speclist > 0 then for i=1,#Speclist do s[#s+1]={Speclist[i], current.GetSegmentEnergyScore(Speclist[i])} end else for i=1,segCnt do s[#s+1]={i, current.GetSegmentEnergyScore(i)} end end if Vworst==true then Sort(s,#s) end if Vrandom==true then for i=1,#s do local r=math.random(#s) s[i],s[r]=s[r],s[i] end end if allatonce then Pull() else local Speclist2={} --Clear list for i=1,#s/Combinum do print("Kill "..i.." of "..(#s-#s%Combinum)/Combinum.." started.") for j=1,Combinum do Speclist2[j]=s[Combinum*i-Combinum+j][1] end Pull(Speclist2) end end end -- Segment set and list module -- Notice that most functions assume that the sets are well formed -- (=ordered and no overlaps) -- 02-05-2012 TvdL Free to use for non commercial purposes function SegmentListToSet(list) local result={} local f=0 local l=-1 table.sort(list) for i=1,#list do if list[i] ~= l+1 and list[i] ~= l then -- note: duplicates are removed if l>0 then result[#result+1]={f,l} end f=list[i] end l=list[i] end if l>0 then result[#result+1]={f,l} end --print("list to set") --SegmentPrintSet(result) return result end function SegmentSetToList(set) local result={} for i=1,#set do --print(set[i][1],set[i][2]) for k=set[i][1],set[i][2] do result[#result+1]=k end end return result end function SegmentCleanSet(set) -- Makes it well formed return SegmentListToSet(SegmentSetToList(set)) end function SegmentInvertSet(set,maxseg) -- Gives back all segments not in the set -- maxseg is added for ligand local result={} if maxseg==nil then maxseg=structure.GetCount() end if #set==0 then return {{1,maxseg}} end if set[1][1] ~= 1 then result[1]={1,set[1][1]-1} end for i=2,#set do result[#result+1]={set[i-1][2]+1,set[i][1]-1} end if set[#set][2] ~= maxseg then result[#result+1]={set[#set][2]+1,maxseg} end return result end function SegmentInList(s,list) table.sort(list) for i=1,#list do if list[i]==s then return true elseif list[i]>s then return false end end return false end function SegmentInSet(set,s) for i=1,#set do if s>=set[i][1] and s<=set[i][2] then return true elseif s<set[i][1] then return false end end return false end function SegmentJoinList(list1,list2) local result=list1 if result == nil then return list2 end for i=1,#list2 do result[#result+1]=list2[i] end table.sort(result) return result end function SegmentJoinSet(set1,set2) return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentCommList(list1,list2) local result={} table.sort(list1) table.sort(list2) if #list2==0 then return result end local j=1 for i=1,#list1 do while list2[j]<list1[i] do j=j+1 if j>#list2 then return result end end if list1[i]==list2[j] then result[#result+1]=list1[i] end end return result end function SegmentCommSet(set1,set2) return SegmentListToSet(SegmentCommList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentSetMinus(set1,set2) return SegmentCommSet(set1,SegmentInvertSet(set2)) end function SegmentPrintSet(set) print(SegmentSetToString(set)) end function SegmentSetToString(set) local line = "" for i=1,#set do if i~=1 then line=line..", " end line=line..set[i][1].."-"..set[i][2] end return line end function SegmentSetInSet(set,sub) if sub==nil then return true end -- Checks if sub is a proper subset of set for i=1,#sub do if not SegmentRangeInSet(set,sub[i]) then return false end end return true end function SegmentRangeInSet(set,range) if range==nil or #range==0 then return true end local b=range[1] local e=range[2] for i=1,#set do if b>=set[i][1] and b<=set[i][2] then return (e<=set[i][2]) elseif e<=set[i][1] then return false end end return false end function SegmentSetToBool(set) local result={} for i=1,structure.GetCount() do result[i]=SegmentInSet(set,i) end return result end --- End of Segment Set module -- Module Find Segment Types function FindMutables() local result={} for i=1,structure.GetCount() do if structure.IsMutable(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindFrozen() local result={} for i=1,structure.GetCount() do if freeze.IsFrozen(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindLocked() local result={} for i=1,structure.GetCount() do if structure.IsLocked(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindSelected() local result={} for i=1,structure.GetCount() do if selection.IsSelected(i) then result[#result+1]=i end end return SegmentListToSet(result) end function FindAAtype(aa) local result={} for i=1,structure.GetCount() do if structure.GetSecondaryStructure(i)== aa then result[#result+1]=i end end return SegmentListToSet(result) end function FindAminotype(at) -- This one returns a list not a set local result={} for i=1,structure.GetCount() do if structure.GetAminoAcid(i) == at then result[#result+1]=i end end return result end -- end Module Find Segment Types -- Module AskSelections -- 02-05-2012 Timo van der Laan, Free to use for non commercial purposes function AskForSelections(title,mode) local result={{1,structure.GetCount()}} -- All segments if mode == nil then mode={} end if mode.askloops==nil then mode.askloops=true end if mode.asksheets==nil then mode.asksheets=true end if mode.askhelixes==nil then mode.askhelixes=true end if mode.askligands==nil then mode.askligands=false end if mode.askselected==nil then mode.askselected=true end if mode.asknonselected==nil then mode.asknonselected=true end if mode.askmutateonly==nil then mode.askmutateonly=true end if mode.askignorelocks==nil then mode.askignorelocks=true end if mode.askignorefrozen==nil then mode.askignorefrozen=true end if mode.askranges==nil then mode.askranges=true end if mode.defloops==nil then mode.defloops=true end if mode.defsheets==nil then mode.defsheets=true end if mode.defhelixes==nil then mode.defhelixes=true end if mode.defligands==nil then mode.defligands=false end if mode.defselected==nil then mode.defselected=false end if mode.defnonselected==nil then mode.defnonselected=false end if mode.defmutateonly==nil then mode.defmutateonly=false end if mode.defignorelocks==nil then mode.defignorelocks=false end if mode.defignorefrozen==nil then mode.defignorefrozen=false end local Errfound=false repeat local ask = dialog.CreateDialog(title) if Errfound then ask.E1=dialog.AddLabel("Try again, ERRORS found, check output box") result={{1,structure.GetCount()}} --reset start Errfound=false end if mode.askloops then ask.loops = dialog.AddCheckbox("Work on loops",mode.defloops) elseif not mode.defloops then ask.noloops= dialog.AddLabel("Loops will be auto excluded") end if mode.askhelixes then ask.helixes = dialog.AddCheckbox("Work on helixes",mode.defhelixes) elseif not mode.defhelixes then ask.nohelixes= dialog.AddLabel("Helixes will be auto excluded") end if mode.asksheets then ask.sheets = dialog.AddCheckbox("Work on sheets",mode.defsheets) elseif not mode.defsheets then ask.nosheets= dialog.AddLabel("Sheets will be auto excluded") end if mode.askligands then ask.ligands = dialog.AddCheckbox("Work on ligands",mode.defligands) elseif not mode.defligands then ask.noligands= dialog.AddLabel("Ligands will be auto excluded") end if mode.askselected then ask.selected = dialog.AddCheckbox("Work only on selected",mode.defselected) end if mode.asknonselected then ask.nonselected = dialog.AddCheckbox("Work only on nonselected",mode.defnonselected) end if mode.askmutateonly then ask.mutateonly = dialog.AddCheckbox("Work only on mutateonly",mode.defmutateonly) end if mode.askignorelocks then ask.ignorelocks =dialog.AddCheckbox("Dont work on locked ones",true) elseif mode.defignorelocks then ask.nolocks=dialog.AddLabel("Locked ones will be auto excluded") end if mode.askignorefrozen then ask.ignorefrozen = dialog.AddCheckbox("Dont work on frozen",true) elseif mode.defignorefrozen then ask.nofrozen=dialog.AddLabel("Frozen ones will be auto excluded") end if mode.askranges then ask.R1=dialog.AddLabel("Or put in segmentranges. Above selections also count") ask.ranges=dialog.AddTextbox("Ranges","") end ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then -- We start with all the segments including ligands if mode.askloops then mode.defloops=ask.loops.value end if not mode.defloops then result=SegmentSetMinus(result,FindAAtype("L")) end if mode.asksheets then mode.defsheets=ask.sheets.value end if not mode.defsheets then result=SegmentSetMinus(result,FindAAtype("E")) end if mode.askhelixes then mode.defhelixes=ask.helixes.value end if not mode.defhelixes then result=SegmentSetMinus(result,FindAAtype("H")) end if mode.askligands then mode.defligands=ask.ligands.value end if not mode.defligands then result=SegmentSetMinus(result,FindAAtype("M")) end if mode.askignorelocks then mode.defignorelocks=ask.ignorelocks.value end if mode.defignorelocks then result=SegmentSetMinus(result,FindLocked()) end if mode.askignorefrozen then mode.defignorefrozen=ask.ignorefrozen.value end if mode.defignorefrozen then result=SegmentSetMinus(result,FindFrozen()) end if mode.askselected then mode.defselected=ask.selected.value end if mode.defselected then result=SegmentCommSet(result,FindSelected()) end if mode.asknonselected then mode.defnonselected=ask.nonselected.value end if mode.defnonselected then result=SegmentCommSet(result,SegmentInvertSet(FindSelected())) end if mode.askranges and ask.ranges.value ~= "" then local rangetext=ask.ranges.value local function Checknums(nums) -- Now checking if #nums%2 ~= 0 then print("Not an even number of segments found") return false end for i=1,#nums do if nums[i]==0 or nums[i]>structure.GetCount() then print("Number "..nums[i].." is not a segment") return false end end return true end local function ReadSegmentSet(data) local nums = {} local NoNegatives='%d+' -- - is not part of a number local result={} for v in string.gfind(data,NoNegatives) do table.insert(nums, tonumber(v)) end if Checknums(nums) then for i=1,#nums/2 do result[i]={nums[2*i-1],nums[2*i]} end result=SegmentCleanSet(result) else Errfound=true result={} end return result end local rangelist=ReadSegmentSet(rangetext) if not Errfound then result=SegmentCommSet(result,rangelist) end end end until not Errfound return result end -- end of module AskSelections Version="3.0.0" function askMode() local ask = dialog.CreateDialog("Voidcrusher "..Version.." Runmode") ask.l1=dialog.AddLabel("Run specified number of kills at a time") ask.Combi = dialog.AddSlider("Nr of segments: ",Combinum,1,10,0) ask.allatonce=dialog.AddCheckbox("Or pull all in one go",allatonce) ask.l3=dialog.AddLabel("Or do multiple runs on 1 to 6 segments") ask.multi=dialog.AddSlider("Repeat multi",multi,0,20,0) ask.l2 = dialog.AddLabel("The choices above also apply if selections are made") ask.selected=dialog.AddCheckbox("Set selection where to pull from",false) ask.selection=dialog.AddCheckbox("Select segments where 1 bandend must be",false) ask.l4 = dialog.AddLabel("Modify fine tuning options, depended on mode") ask.WF = dialog.AddSlider("WiggleFactor:",WF,1,5,0) --print("Wiggle FactorB= ",ask.WF.value) ask.modOptions=dialog.AddCheckbox("Modify options",false) ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then Combinum=ask.Combi.value allatonce=ask.allatonce.value multi=ask.multi.value WF=ask.WF.value -- print("Wiggle FactorC= ",ask.WF.value) if ask.selected.value then local SelMode={} SelMode.askligands=true --override the defaults SelMode.defligands=true SelMode.defignorelocks=false SelMode.defignorefrozen=false local PullFrom=AskForSelections("Set where to pull from",SelMode) for i=1,segCnt do if SegmentInSet(PullFrom,i) then Speclist[#Speclist+1]=i end end end if ask.selection.value then local SelMode={} SelMode.askligands=true --override the defaults SelMode.defligands=true SelMode.askignorelocks=false SelMode.defignorelocks=true SelMode.defignorefrozen=false useRegion=AskForSelections("At least one bandend must be",SelMode) else useRegion={{1,segCnt}} useRegion=SegmentSetMinus(useRegion,FindLocked()) end useRegionBool=SegmentSetToBool(useRegion) if ask.modOptions.value then AskOptions() end if multi > 0 then allatonce=false for i=1,multi do for j=1,6 do Combinum=j KillVoids() end end else KillVoids() end end end function AskOptions() local ask = dialog.CreateDialog("Finetune options Voidcrusher "..Version) if not allatonce or #Speclist > 0 then ask.l1=dialog.AddLabel("Band strength during pull") ask.BandsAbsMin=dialog.AddSlider("Minimum",minBS,0.1,1,2) ask.BandsAbsMax=dialog.AddSlider("Maximum",maxBS,0.1,2,2) end if not allatonce then ask.l2=dialog.AddLabel("Order of treatement") ask.random=dialog.AddCheckbox("Random",Vrandom) ask.worst=dialog.AddCheckbox("Worst first",Vworst) ask.l3=dialog.AddLabel("Pull harder if loss is less") ask.maxLoss=dialog.AddSlider("Percentage",maxLoss,0,2,1) ask.l4 = dialog.AddLabel("Run fuze if qstab is close to recent best") ask.doFuze = dialog.AddSlider("Neg, only after gain",doFuze,-10,20,1) else ask.l11=dialog.AddLabel("Band strength to pull with") ask.allBS = dialog.AddSlider("Band strength",allBS,0.1,1,2) ask.l21 = dialog.AddLabel("Multiplier to pull hydro's more") ask.hydro = dialog.AddSlider("Hydro factor: ",pullextrahydro,0.5,3,1) end ask.lx1= dialog.AddLabel("Maximum band length") ask.maxLength=dialog.AddSlider("maxLength",maxLength,15,100,1) ask.l5 = dialog.AddLabel("Class importance while pulling") ask.CI = dialog.AddSlider("Class importance",pullingCI,0.3,1,2) ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0) if dialog.Show(ask) > 0 then if not allatonce or #Speclist > 0 then minBS=ask.BandsAbsMin.value maxBS=ask.BandsAbsMax.value end if not allatonce then maxLoss=ask.maxLoss.value Vrandom=ask.random.value Vworst=ask.worst.value doFuze=ask.doFuze.value else allBS=ask.allBS.value pullextrahydro=ask.hydro.value end maxLength=ask.maxLength.value pullingCI=ask.CI.value end end --- OPTIONS THERE! vvv useRegion={} useRegionBool={} minDist=15 --minimum segment distance minLength=10 --minimum spatial distance maxLength=50 --maximum spatial distance fastQstab = true --1s1w then true, double if false compFrac=3 --how much shorter band should be -- Defaults here VVV Vworst=false --start form worst scoring one Vrandom=true --true --go it in random order -- if both are false then it will band form 1st to last multi=0 -- Multirun overrides all other options Combinum=1 -- Nr of segments to be treated in 1 go doFuze=5 --run fuzes when close to saved best (negative - run if gain after qstab) pullingCI=0.90 --clash importance during pull Speclist={} minBS=0.12 --absolute minimum band strength maxBS=1 --absolute maximum band strength maxLoss=1 --pull till perc loss (ie 1 on 10`000 ptsy = pull till 100 pt loss after pull) -- New options allatonce=false --false -- set to true if all at once pullextrahydro=1.3 --multiplier for extra pull on hydro segments allBS=0.12 -- strength if all lastAllBS=0 lastBS=minBS --END OF OPTIONS ^^^ function Cleanup(err) print("Resetting CI and best score, removing extra bands") save.Quickload(3) CI(1) bandDeleteAll() print(err) end xpcall(askMode,Cleanup)

Comments