Code
-- recipe constants
flag={
selected=false,
doMutate=false,
useBands=false
}
-- library functions
recipe.Loop = function(func, single_slot, ...)
single_slot:reset()
repeat
func(...)
until not single_slot:test_score()
single_slot:restore()
end
recipe.OnExit = function(err)
if err=='Cancelled' then
print('\ncancelled')
else
print(err)
end
save.Quickload(1)
end
save.SingleSlot = {
formats = {
old = ">> %s loop. score : %.3f. total gain: %.3f points",
current = ">> %s loop. score : %.3f. gain: %.3f points"
},
new = function(self, name, slot)
self.name = name
self.slot = slot
self:reset()
return self
end,
reset = function(self)
self.current = current.GetScore()
self.old = current.GetScore()
save.Quicksave(self.slot)
end,
test_score = function(self)
local temp_score = current.GetScore()
local test = temp_score>self.current
if test then
save.Quicksave(self.slot)
self:report('current', temp_score)
self.current=temp_score
end
return test
end,
report = function(self, report_type, s)
local s = s or current.GetScore()
local fmt = self.formats[report_type]
print(string.format(fmt, self.name, s, s-self[report_type]))
end,
show = function(self)
print(string.format('current best: %.3f', self.current))
end,
restore = function(self)
save.Quickload(self.slot)
end,
}
save.MultiSlot = {
new = function(self, name, first_slot, max_slots)
self.name = name
self.first_slot = first_slot
self.max_slots = max_slots
self:reset()
return self
end,
reset = function(self)
self.current = current.GetScore()
self.scores = {}
end,
sortasc = function(a, b) return a[2] > b[2] end,
_write_slot = function(self, index, slot, score)
local score = score or current.GetScore()
save.Quicksave(slot)
self.scores[index] = {slot, score}
end,
store = function(self)
local index, slot
if #self.scores < self.max_slots then
index = #self.scores+1
slot = #self.scores+self.first_slot
self:_write_slot(index, slot)
else
index = #self.scores
slot = self.scores[index][1]
local old_score = self.scores[index][2]
local score = current.GetScore()
if score > old_score then
self:_write_slot(index, slot, score)
end
end
table.sort(self.scores, self.sortasc)
end,
}
save.ScoreManager = {
new = function(self, slot)
self.next_slot = slot or 1
return self
end,
_clone_obj = function(self, obj)
local clone = {}
for k, v in pairs(obj) do clone[k] = v end
return clone
end,
make_single = function(self, name)
local new_single = save.SingleSlot:new(name, self.next_slot)
new_single = self:_clone_obj(new_single)
self.next_slot = self.next_slot+1
return new_single
end,
make_multi = function(self, name, n_slots)
local new_multi = save.MultiSlot:new(name, self.next_slot, n_slots)
new_multi = self:_clone_obj(new_multi)
self.next_slot = self.next_slot+n_slots
return new_multi
end,
}
structure.Wiggle = {
funcs = {
shake={
[0] = structure.ShakeSidechainsAll,
[1] = structure.ShakeSidechainsSelected,
[10] = structure.MutateSidechainsAll,
[11] = structure.MutateSidechainsSelected,
},
wiggle={
[0] = structure.WiggleAll,
[1] = structure.WiggleSelected,
[10] = structure.WiggleAll,
[11] = structure.WiggleSelected,
}
},
new = function(self)
self.selected = false
self.mutate = false
self.wp_is_high = behavior.GetWigglePower() == 'h'
print('wiggle power is high: '..tostring(self.wp_is_high))
self.step = self.wp_is_high and .025 or .05
self.compress = self.wp_is_high and self.compress_hard or self.compress_regular
self:_set_binflag()
self:_set_funcs()
return self
end,
set = function(self, val)
self[val] = true
self:_set_binflag()
self:_set_funcs()
end,
unset = function(self, val)
self[val] = false
self:_set_binflag()
self:_set_funcs()
end,
_set_binflag = function(self)
--~ for k,v in pairs(self) do print(k,v) end
sel = self.selected and 1 or 0
mut = self.mutate and 10 or 0
self.binflag = sel + mut
end,
_set_funcs = function(self)
self.shake_func = self.funcs.shake[self.binflag]
self.wiggle_func = self.funcs.wiggle[self.binflag]
end,
shake = function(self, iters)
--~ print('shake', self.binflag)
--~ for k,v in pairs(self) do print(k,v) end
self.shake_func(iters)
end,
wiggle = function(self, iters, iter)
iters=iters or 1
iter=iter or 1
local iter_score=current.GetScore()
self.wiggle_func(iters)
if (current.GetScore()-iter_score)>(self.step*(1+iter)) then
self:wiggle(iters+1, iter+1)
end
end,
compress_hard = function(self)
behavior.SetSidechainHBondImportance(3)
behavior.SetClashImportance(.02)
self.shake_func(1)
behavior.SetSidechainHBondImportance(1)
behavior.SetBackboneHBondImportance(3)
behavior.SetClashImportance(.25)
self:wiggle(1)
behavior.SetBackboneHBondImportance(1)
behavior.SetClashImportance(1)
end,
compress_regular = function(self)
behavior.SetClashImportance(.02)
self.shake_func(1)
behavior.SetClashImportance(.25)
self:wiggle(1)
behavior.SetClashImportance(1)
end,
decompress = function(self)
self:wiggle(1)
self.shake_func(1)
self:wiggle(3)
end,
fuse = function(self)
old_step=self.step
self.step=.1
self:compress()
self.step=old_step
self:decompress()
end,
}
function FastRelax()
local CIs={.02,.25,1}
for _, ci in ipairs(CIs) do
behavior.SetClashImportance(ci)
wiggle_manager:shake(1)
wiggle_manager:wiggle(1)
end
wiggle_manager:wiggle(3)
end
function Mutate()
if not flag.doMutate then return end
mutate_score:reset()
wiggle_manager:set('mutate')
wiggle_manager:shake(1)
wiggle_manager:unset('mutate')
wiggle_manager:wiggle(3)
mutate_score:test_score()
mutate_score:restore()
end
function UseBands()
if not flag.useBands then return end
print('band cycle')
band.EnableAll()
wiggle_manager:compress()
band.DisableAll()
wiggle_manager:decompress()
end
function FRoSt(slot, score)
iters=iters+1
print('start frost cycle #'..iters)
UseBands()
main_score:test_score()
Mutate()
print("fast relax")
FastRelax()
main_score:test_score()
Mutate()
print("black fuse")
recipe.Loop(wiggle_manager.fuse, blackfuse_score, wiggle_manager)
Mutate()
main_score:test_score()
main_score:report('old')
print()
end
function DoDialogStuff()
dlg=dialog.CreateDialog('FRoSt')
dlg.selected=dialog.AddCheckbox("selected only", flag.selected)
dlg.doMutate=dialog.AddCheckbox("mutate", flag.doMutate)
dlg.useBands=dialog.AddCheckbox("use my bands", flag.useBands)
dlg.ok=dialog.AddButton("ok", 1)
dlg.cancel=dialog.AddButton("cancel", 0)
if dialog.Show(dlg) > 0 then
flag.selected=dlg.selected.value
flag.doMutate=dlg.doMutate.value
flag.useBands=dlg.useBands.value
end
end
function main()
iters=0
DoDialogStuff()
wiggle_manager = structure.Wiggle:new()
if flag.selected then wiggle_manager:set('selected') end
local slot_manager = save.ScoreManager:new()
main_score = slot_manager:make_single('main')
main_score:show()
frost_score = slot_manager:make_single('frost')
blackfuse_score = slot_manager:make_single('black fuse')
if flag.doMutate then mutate_score = slot_manager:make_single('mutate') end
print()
recipe.Loop(FRoSt, frost_score)
main_score:restore()
end
xpcall(main, recipe.OnExit)
--~ main()