Code
--[[
------------------------------------------------
BandFuze Orange Guard v0.1
Adapted from MurloW's wonderful script BandFuze.
Orange Guard refers to protecting sidechains chosen by the player before the script starts,
and only allowing them to change to a prescribed list of Orange sidechains. Player should
FREEZE all sidechains they want to be guarded during the mutates, BEFORE starting the script.
v0.1:
Edit bandfuze code for readability, update wiggle function, remove call to "qStab", which
in this script is not a Rav3n-style quick stabilize but actually an extra fuze.
Establish lists of allowed (orange) AAs for each frozen sidechain.
Deselect the player's frozen sidechains prior to each mutate,
to prevent them from mutating.
After mutate, try each allowed AA on the protected sidechains; keep only gains.
At script end, re-freeze the sidechains the player had frozen before.
v0.2:
add printout at beginning of how many sidechains Orange Guard is protecting
reduce reporting of Orange Guard actions during script
add reporting of high score and filter score after each iteration
Future version - might add dialog for editing the lists of allowed AAs.
------------------------------------------------]]
------------------------------------------------
-- INITIALIZATION
------------------------------------------------
IterationMultiplier = 1.2 -- 2.4 --not used anywhere else
ItMu = IterationMultiplier -- used only in wig() function
if ItMu<=0 then ItMu=1 end
nSegs=structure.GetCount()
p=print
p("")
behavior.SetSlowFiltersDisabled(false)
oldbands = band.GetCount()
Qbands = 0
function score()
return current.GetScore()
end
function cut(x)
return x-x%0.000000001
end
startscore = score()
bestscore = startscore --only gets changed by Check() function, gets read several places
p(" Startscore: "..cut(startscore))
p(" Best score in quicksave slot 1, starting pose in slot 2 ")
--save.Quicksave(1) -- moved to main
--save.Quicksave(2) -- moved to main
maxCI=behavior.GetClashImportance()
if maxCI<0.1 then
maxCI = 1
end
p(" maxCI = "..maxCI)
--if AllAla then --made AllAla a function that returns a boolean, rather than a global variable
-- p(" No shaking, still mutating if checked.")
--end
function Seed() -- Rav3n_pl
seed=os.time()/math.abs(current.GetEnergyScore())
seed=seed%0.001
seed=1/seed
while seed<10000000 do seed=seed*10 end
seed=seed-seed%1
--p("Seed is: "..seed)
math.randomseed(seed)
end
Seed()
------------------------------------------------
-- END INITIALIZATION
------------------------------------------------
------------------------------------------------
-- ORANGE GUARD
------------------------------------------------
OG = {
Slot=77, --Quicksave slot used by this module
--define substitution lists
Protected={}, --Sparse table, keyed by residue number, returns true if that residue is protected.
AllowedList={}, --Sparse table, keyed by residue number, returns list of allowed AAs.
RulesList={ --[[Used only during Initialization - after that use AllowedList instead.
Sparse table keyed by AA, containing sparse tables keyed by secondary structure,
containing integer-keyed list of all allowed AAs for that position.
Each AA is allowed to be changed back to its original value regardless of SS.
'a' and 'p' allowed only in loops.
'm' allowed only in loops and helices.
'f' allowed anywhere there was already f, w, or y.
'w' and 'y' allowed only where there was already w or y.
]]
a={E={'a','i','l','v'}, H={'a','i','l','m','v'}, L={'a','i','l','m','p','v'}}, --allowed substitutions for alanine, by SS
c={E={'c','i','l','v'}, H={'c','i','l','m','v'}, L={'a','c','i','l','m','p','v'}}, --for cysteine, etc.
d={E={'d','i','l','v'}, H={'d','i','l','m','v'}, L={'a','d','i','l','m','p','v'}},
e={E={'e','i','l','v'}, H={'e','i','l','m','v'}, L={'a','e','i','l','m','p','v'}},
f={E={'f','i','l','v'}, H={'f','i','l','m','v'}, L={'a','f','i','l','m','p','v'}},
g={E={'g','i','l','v'}, H={'g','i','l','m','v'}, L={'a','g','i','l','m','p','v'}},
h={E={'h','i','l','v'}, H={'h','i','l','m','v'}, L={'a','h','i','l','m','p','v'}},
i={E={'i','l','v'}, H={'i','l','m','v'}, L={'a','i','l','m','p','v'}},
k={E={'i','k','l','v'}, H={'i','k','l','m','v'}, L={'a','i','k','l','m','p','v'}},
l={E={'i','l','v'}, H={'i','l','m','v'}, L={'a','i','l','m','p','v'}},
m={E={'i','l','m','v'}, H={'i','l','m','v'}, L={'a','i','l','m','p','v'}},
n={E={'i','l','n','v'}, H={'i','l','m','n','v'}, L={'a','i','l','m','n','p','v'}},
p={E={'i','l','p','v'}, H={'i','l','m','p','v'}, L={'a','i','l','m','p','v'}},
q={E={'i','l','q','v'}, H={'i','l','m','q','v'}, L={'a','i','l','m','p','q','v'}},
r={E={'i','l','r','v'}, H={'i','l','m','r','v'}, L={'a','i','l','m','p','r','v'}},
s={E={'i','l','s','v'}, H={'i','l','m','s','v'}, L={'a','i','l','m','p','s','v'}},
t={E={'i','l','t','v'}, H={'i','l','m','t','v'}, L={'a','i','l','m','p','t','v'}},
v={E={'i','l','v'}, H={'i','l','m','v'}, L={'a','i','l','m','p','v'}},
w={E={'f','i','l','v','w','y'}, H={'f','i','l','m','v','w','y'}, L={'a','f','i','l','m','p','v','w','y'}},
y={E={'f','i','l','v','w','y'}, H={'f','i','l','m','v','w','y'}, L={'a','f','i','l','m','p','v','w','y'}},
}
}
function OG.Init()
--build lists of frozen sidechains and AAs allowed for each one
local OGCount = 0
for ii = 1, structure.GetCount() do
local BBFrozen, SCFrozen = freeze.IsFrozen(ii)
local AA = structure.GetAminoAcid(ii)
local SS = structure.GetSecondaryStructure(ii)
if (SCFrozen or (AA=='g' and BBFrozen)) then
OG.Protected[ii] = true
OG.AllowedList[ii] = OG.RulesList[AA][SS]
freeze.Unfreeze(ii, true, true) --frozen backbones are not preserved
OGCount = OGCount + 1
end
end
print("Orange Guard is protecting "..OGCount.." amino acids.")
end
function OG.Cleanup()
for segnum, value in pairs(OG.Protected) do --this is how you loop over a sparse table
local AA = structure.GetAminoAcid(segnum)
if AA=='g' then
freeze.Freeze(segnum, true, false)
else
freeze.Freeze(segnum, false, true)
end
end
end
function OG.MutateSelected(iters)
print(" OG.MutateSelected")
local ProtectList={}
for segnum, value in pairs(OG.Protected) do
if selection.IsSelected(segnum) then
ProtectList[segnum] = true
selection.Deselect(segnum)
end
end
structure.MutateSidechainsSelected(iters)
local FiltersOff = behavior.GetFiltersDisabled()
if FiltersOff then
behavior.SetFiltersDisabled(false)
end
local SavedScore = current.GetScore()
local NewScore = SavedScore
save.Quicksave(OG.Slot)
--print(" score after general mutate: "..SavedScore)
--individually try substitutions on protected ones and save if better
for segnum, value in pairs(ProtectList) do
--print(" trying segment "..segnum)
for jj, AA in pairs(OG.AllowedList[segnum]) do
if structure.CanMutate(segnum, AA) then
structure.SetAminoAcid(segnum, AA)
NewScore = current.GetScore()
if NewScore > SavedScore then
save.Quicksave(OG.Slot)
SavedScore = NewScore
--print(" changed to "..AA..", new score "..SavedScore)
end
end
end
save.Quickload(OG.Slot)
end
behavior.SetFiltersDisabled(FiltersOff)
for segnum, value in pairs(ProtectList) do
selection.Select(segnum)
end
--print(" exit OG.MutateSelected")
--if any changes, re-run mutate?? not at this point, because mutate is slow
end
------------------------------------------------
-- END ORANGE GUARD
------------------------------------------------
function setCI(ci)
return behavior.SetClashImportance(ci)
end
function wig(how, it, iters, minppi)
behavior.SetSlowFiltersDisabled(true)
if how==nil then how="wa" end
--if minppi==nil then minppi=2 end
--if iters==nil then iters=2 end
if it==nil then it=10*ItMu end
it=math.ceil(it)
--if iters>0 then
--iters=iters-1
--local sp=score()
if how == "s" then
if not AllAla() then structure.ShakeSidechainsAll(1) end
elseif how == "wb" then structure.WiggleAll(it,true,false)
elseif how == "ws" then structure.WiggleAll(it,false,true)
elseif how == "wa" then structure.WiggleAll(it)
end
--if score()-sp > minppi and how ~= "s" then return wig(how, it, iters, minppi) end -- remove recursive wiggle, not needed since NewChapter
--end
behavior.SetSlowFiltersDisabled(false)
end
function Test()
--p(" Test")
save.Quicksave(93)
recentbest.Save()
sci=(math.random(maxCI*100)/100)
setCI(sci)
if (MutateOnce or MutateMany) then
--p(" Mutate CI:", sci)
selectMutables()
--structure.MutateSidechainsSelected(1)
OG.MutateSelected(1)
Check()
selection.DeselectAll()
else
--p(" Shake CI:", sci)
wig('s') Check()
end
setCI(maxCI)
wig()
Check()
setCI(maxCI/2)
wig("wa",5)
Check()
setCI(maxCI)
wig()
Check()
--qStab()
--Susume - per tokens, comment this out for better speed when all you want is the mutates
save.Quickload(93)
setCI(maxCI)
wig()
Check()
setCI(maxCI/2)
wig("wa",5)
Check()
setCI(maxCI)
wig()
Check()
recentbest.Restore()
Check()
if fuzt>=0 then
if score()>(bestscore-fuzt) then
Fuzit()
end
else
if score()>=(bestscore+FF) then
Fuzit()
end
end
local FiltersOff = behavior.GetFiltersDisabled()
behavior.SetFiltersDisabled(true)
local UnfilteredScore = score()
behavior.SetFiltersDisabled(false)
local FilteredScore = score()
local FilterBonus = FilteredScore - UnfilteredScore
p("Current filter bonus/penalty = "..FilterBonus)
p("Current score = "..FilteredScore)
p("Best score = "..bestscore)
behavior.SetFiltersDisabled(FiltersOff)
--p(" exit Test")
end
function qStab() -- this is actually another type of fuze, not a quick stabilize
setCI(maxCI/2)
wig("wa",5)
Check()
setCI(maxCI)
wig("s")
Check()
wig()
Check()
setCI(maxCI/2)
wig("wa",5)
Check()
setCI(maxCI)
wig()
Check()
wig('s')
Check()
wig()
Check()
end
function Fuze(Shortfuze) --called only from the wrapper Fuzit()
p(" Fuze, short = "..Shortfuze)
Check()
setCI(.05)
wig("s")
Check()
setCI(maxCI)
wig()
Check()
setCI(maxCI/3)
wig("wa",5)
Check()
if not Shortfuze then
setCI(.07)
wig("s")
Check()
setCI(maxCI)
wig()
Check()
setCI(maxCI/3)
wig("wa",5)
Check()
end
setCI(maxCI)
wig("s")
Check()
wig()
Check()
p(" exit Fuze")
end
function mutaFuze(Shortfuze) --called only from the wrapper Fuzit()
p(" mutaFuze, short = "..Shortfuze)
setCI(0.15)
selectMutables()
structure.MutateSidechainsSelected(1)
Check()
selection.DeselectAll()
setCI(maxCI)
wig()
Check()
setCI(maxCI/3)
wig("wa",4)
Check()
setCI(maxCI)
wig()
Check()
if not Shortfuze then
--setCI(0.2)
--wig("s")
--Check()
--setCI(maxCI)
--wig()
--Check()
setCI(maxCI/2)
wig()
Check()
setCI(0.87*maxCI)
selectMutables()
structure.MutateSidechainsSelected(1)
Check()
selection.DeselectAll()
end
wig("wa",9)
Check()
p(" exit mutaFuze")
end
function Fuzit() --calls Fuze or mutaFuze with 50% chance of a relatively shorter fuze
if (math.random(-100,100)>=0) then
local Shortfuze=false
else
local Shortfuze=true
end
if MutateMany then
mutaFuze(Shortfuze)
else
Fuze(Shortfuze)
end
end
function Check()
--p(" Check")
if (bestscore < score()) then
local gain = score() - bestscore
bestscore = score()
save.Quicksave(1)
p(" ",cut(gain),"pts. New score ",bestscore)
end
end
function AllAla() --returns true if the whole protein is alanine and/or glycine,
--and therefore need not be shaken
for i=1, structure.GetCount() do
local Taa=structure.GetAminoAcid(i)
if (Taa ~= 'a' and Taa ~= 'g') then
return false --found a shakeable sidechain, no need to keep looking
end
end
return true
end
function selectMutables()
for i=1,nSegs do
if structure.IsMutable(i) == true then selection.Select(i) end
end
end
function End(errmsg)
if done then
return
end
done=true
if string.find(errmsg,"Cancelled") then
p("")
p(" User cancel.")
Result()
p("")
else
Result()
p("")
p(errmsg)
end
OG.Cleanup()
return errmsg
end
function Result()
behavior.SetSlowFiltersDisabled(false)
recentbest.Restore()
Check()
save.Quickload(1)
Delbands()
Tgain = (bestscore-startscore)
if Tgain<0.008 then
p(" No change.. :/ ")
else
p(" Startscore: "..cut(startscore))
p(" Score: "..cut(score()))
p(" Total gain: "..cut(Tgain).." pts.")
end
setCI(maxCI)
end
function bandpull(minBS,maxBS)
--p(" bandpull")
if KeepBands then
band.EnableAll()
end
local StartScore=score()
local perc=math.random(80,200)/100
local loss=((perc*StartScore)/100)
--p(" Min. loss: "..perc.."%, "..cut(loss),"points.")
local lastBS=minBS
for str=lastBS,maxBS, 0.1 do
if KeepBandStrength then
startband = oldbands+1
else
startband = 1
end
for i=startband, band.GetCount() do
band.SetStrength(i, str)
end
wig('wb',5,1,500) -- wig extra params used: 1 means do not recurse the wiggle,
-- 500 indicates how many points minimum change to recurse the wiggle,
-- but the 1 overrides it so it doesn't recurse in any case
if (StartScore-score()>=loss) or (score()>bestscore+1) then
if band.GetCount()>(nSegs/10)*2 then
lastBS=str-0.1
if lastBS<minBS then lastBS=minBS end
else
lastBS=minBS
end
break
end
end
--p(" exit bandpull")
end
function bandage()
--p(" bandage")
if KeepBandStrength then
startband = oldbands+1
else
startband = 1
end
if bloat==true then
for i=startband, band.GetCount() do
band.SetGoalLength(i,band.GetLength(i)+4)
end
else
for i=startband, band.GetCount() do
local leng=band.GetLength(i)
local perc=math.random(20,50)
local loss=((perc*leng)/100)
band.SetGoalLength(i,band.GetLength(i)-loss)
end
end
--p(" exit bandage")
end
function spacebands(amnt)
--p(" spacebands")
local zeBands=math.random(amnt)+Qbands
if zeBands<1 then zeBands = 1 end
while band.GetCount()<zeBands do
segO = math.random(nSegs)
OsegC=1
while structure.IsLocked(segO)==true do
segO=math.random(nSegs)
OsegC=OsegC+1
if OsegC>25 then
break
end
end
if ZL==true then
rho=0.2
else
rho=math.random(10)
end
theta = math.random(100,314.159)/100
phi = math.random(100,314.159)/100
if phi<1 then
phi=phi+1
end
if theta<1 then
theta=theta+1
end
if segO<=nSegs and segO>=1 then
if segO==nSegs then
segX = segO-1
segY = segO-2
elseif segO==1 then
segX = segO+1
segY = segO+2
else
segX = segO-1
segY = segO+1
end
if segX>nSegs then
segX=nSegs-1
end
if segY>nSegs then
segY=nSegs-1
end
if segY<1 then
segY=1
end
if segX<1
then segX=1
end
--[[
p(segX,"X")
p(segY,"Y")
p(segO,"O")
p(theta,"theta")
p(phi,"phi")
]]
lb=band.Add(segO, segX, segY, rho, theta, phi)
--local lb=band.GetCount()
if ZL==true then
band.SetGoalLength(lb,math.random(1))
band.SetStrength(lb,math.random(10))
else
band.SetGoalLength(lb,math.random(band.GetLength(lb)*2))
end
end
end
--p(" exit spacebands")
end
function Delbands()
for db = band.GetCount(), oldbands+1, -1 do
band.Delete(db)
end
end
function Dia()
if band.GetCount()~=0 then Bands=true end
local HasMutables = false
for i=1, nSegs do
if structure.IsMutable(i) then
HasMutables = true
break
end
end
opt = dialog.CreateDialog("Options.")
opt.maxci=dialog.AddSlider("MaxCI:",maxCI,0.1,1,2)
opt.Qq=dialog.AddCheckbox(" Quake.",true)
opt.Bs=dialog.AddCheckbox(" BiS.",true)
opt.Cmb=dialog.AddCheckbox(" Combine Quake and BiS.",false)
opt.Sk=dialog.AddCheckbox(" Shock.",true)
opt.Tg=dialog.AddCheckbox(" Tailgrab.",true)
opt.fu = dialog.AddLabel("Fuzing threshold (negative value is gain)")
opt.fuz = dialog.AddSlider("", -50, -100, 100, 1)
if Bands then
opt.KB=dialog.AddCheckbox("Keep original bands", true)
opt.KBE=dialog.AddCheckbox("Keep enabled always",false)
opt.KBSTR=dialog.AddCheckbox("Keep original strength and goal length", true)
end
if HasMutables then
opt.mut=dialog.AddCheckbox("Mutate once, after bands",true)
opt.muta=dialog.AddCheckbox("Mutate after bands and in fuze",false) -- once or twice randomly chosen every run
end
opt.ok = dialog.AddButton("Go go!",1)
dialog.Show(opt)
QQ=opt.Qq.value
BiS=opt.Bs.value
Shock=opt.Sk.value
TG=opt.Tg.value
Combo=opt.Cmb.value
fuzt=opt.fuz.value
maxCI=opt.maxci.value
if Bands then
KeepBands=opt.KB.value
KeepBandsEnabled=opt.KBE.value
KeepBandStrength=opt.KBSTR.value
end
if HasMutables then
MutateOnce=opt.mut.value
MutateMany=opt.muta.value
end
if fuzt<=0 then
FF = (-1*fuzt)
end
return MutateOnce, MutateMany, maxCI, fuzt, FF, BiS, QQ, TG, Shock, Combo
end
function ZLb()
if Combo==false then
if BiS then
p(" BiS ")
for i=1, 2 do
spacebands(nSegs/2)
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
bandpull(0.2,1)
Delbands()
if not KeepBandsEnabled then band.DisableAll() end
Test()
end
--p(" exit BiS")
end--bis
end--combo false
ZL=true
if Shock then
p(" Shock ")
for u=1, 2 do
spacebands(nSegs/2)
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
if KeepBands then
band.EnableAll()
end
wig('wb',5,1) --wig extra param used to indicate not to recurse the wiggle
Delbands()
if not KeepBandsEnabled then
band.DisableAll()
end
Test()
end
--p(" exit Shock")
end
ZL=false
end
function BandAcross()
p(" TailGrab ")
for i=1, nSegs do
if structure.IsLocked(i)==false then
first=i
break
end
end
for u=nSegs, 1, -1 do
if structure.IsLocked(u)==false then
last=u
break
end
end
band.AddBetweenSegments(first,last)
bandage()
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
bandpull(0.2,1.4)
Delbands()
if not KeepBandsEnabled then
band.DisableAll()
end
Test()
RM=math.random(-100,100)
if RM>=0 then
bloat=false
else
bloat=true
end
band.AddBetweenSegments(nSegs/2,first)
band.AddBetweenSegments(nSegs/2,last)
bandage()
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
bandpull(0.2,1.4)
Delbands()
if not KeepBandsEnabled then
band.DisableAll()
end
Test()
--p(" end TailGrab")
end
function Quake()
if Combo then
p(" Combo ")
for i=1, 4 do
RM=math.random(-100,100)
if RM>=0 then
bloat=false
else
bloat=true
end
nrR=math.random(1, 19)
for u=1, nrR do
seg1=math.random(1,nSegs)
seg2=math.random(1,nSegs)
while structure.IsLocked(seg1) do
seg1=math.random(1,nSegs)
end
while structure.IsLocked(seg2) do
seg2=math.random(1,nSegs)
end
while seg1==seg2 do
seg1=math.random(1,nSegs)
end
band.AddBetweenSegments(seg1,seg2)
end
bandage()
Qbands=band.GetCount()
spacebands(10)
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
bandpull(0.2,2)
Delbands()
if not KeepBandsEnabled then
band.DisableAll()
end
end -- Combo for loop
--p(" end Combo")
else --not Combo
p(" Quake ")
for i=1, 2 do
RM=math.random(-100,100)
if RM>=0 then
bloat=false
else
bloat=true
end
nrR=math.random(1, 19)
for u=1, nrR do
seg1=math.random(1,nSegs)
seg2=math.random(1,nSegs)
while structure.IsLocked(seg1) do
seg1=math.random(1,nSegs)
end
while structure.IsLocked(seg2) do
seg2=math.random(1,nSegs)
end
while seg1==seg2 do
seg1=math.random(1,nSegs)
end
band.AddBetweenSegments(seg1,seg2)
end -- u loop
bandage()
pci=(math.random(maxCI*100)/100)
setCI(pci)
--p(" Wiggle CI:", pci)
bandpull(0.2,2)
Delbands()
if not KeepBandsEnabled then
band.DisableAll()
end
end --quake loop
--p(" end Quake")
end --combo T/F
Test()
end
function main()
OG.Init()
save.Quicksave(1)
save.Quicksave(2)
Dia()
if not KeepBands then
band.DeleteAll()
oldbands=0
end
while true do
if QQ or Combo then
Quake()
end
ZLb()
if TG then
BandAcross()
end
save.Quickload(1)
end
end
err=xpcall(main,End)