Code
--[[
Ebola Rebuild
Scripted by Jean-Bob
Brainstormed by LAlliance Francophone
Based mainly on Rav3n_pl recipes (DRW+GAB)
Dialog taken from Timo van der Laan's DRW
------------------------------
GAB - Genetic Algorythm on Bands by Rav3n_pl
based on CartoonVillan and Crashguard303 scripts
21/3/2013: corrected bug unwanted negative scores + clarifying user interface BK
10/4/13: multilingual options BK
28/4/2013: bug 'nil value' fixed
10/6/13 Filter optimization+mute desactivation on all prot
8/7/13 Replaced "other" by "density"
13/1/2014 Fixed slot 1 to slot 100 for better yield
31/1/2014 Adapted for NC, ver 1.12.2
02/02/2014 Adapted Qstab ver 1.12.3 nc
02/02/2014 Negative score bug
07/02/2014 added ideality score
09/02/2014 attempt to optimize wiggle for New Chapter
01/03/2014 added reference score
30/03/2014 bug negative score on skip fuze mode hopefully fixed + better GAB dialog
8/11/2014 v1.12.5 Changed Shake by QuickShake + note management
30/11/2015 v1.12.6 added Longer rebuild first
]]--
-- User variables
uo={ --user options. Very long table but useful to restore script
lang="en", -- New BK 10/4/13
recipeName="EbolaRebuild",
numSegs=10, -- Number of segments per zone
contSegsMax=6, -- Max number of contiguous segments to analyse
contSegsMin=3, -- Min number of contiguous segments to analyse
maxContSegs=10, -- Number of contiguous segments to not exceed (loop mode)
longfirst=false, --true -- Reverse the search, long ones first
wholeProt=false, -- whole protein rebuild
zoneWalk=false, -- walk into forceZone in the order of segments instead of scores
autoGab=false, -- Run Gab automatically if the fuse gained some points
gabThresh=30, -- Threshold for Gab launching
rebuildBest=false, -- Best segments rebuild
rebuildNum=11, -- Number of rebuilds to do -- reduce this to save time -- NC: rebuid is better, can be reduced now
solsPerScore=3, -- Number of best solutions to test after rebuild
rebuildCI=0, -- clash importance during rebuild
rebuildLoops=true, -- Transfor protein to loop
scoreFilter=20, -- Minimum score for launching GAB
passGAB=false, -- Do not launch GAB
allowLoss=false, -- Allow loss in a complete cycle
lossThresh=1, -- Amount of allowed loss -- Etait 100, passe a 1 BK 19/3
fastMode=false, -- Enable fuse
minRebuild=1500, -- Minimal score below the maximal score to accept the rebuild
maxRebuild=.001, -- Minimal score above the maximal score to accept the rebuild
fastFuse=true, -- Use 1 fuse instead of 5
verbose=false, -- More information in the output window if true
PROBABLEFILTER=false, -- new BK 8/5/2013
OriginalFilterSetting=behavior.GetSlowFiltersDisabled(), -- new BK 8/5/2013
-- Automatic options used for the script saving
resumeScript=false,
curSeg=0,
segs=0,
curArray='',
stIndex=2,
scoringMode="Backbone",
subscores={},
forceZoneStr='',
forceZone={},
maxVal=-10, -- Mean maximum score for taking the segments into account
-- GAB options:
energy = false, -- True to find energy in exploratory puzzles. False works on every puzzles
pullCI = 0.55, -- Clash Importance during pull mode
maxCI = 1, -- maximum during the script
fastQstab = true, -- Only 1 shake and 1 wiggle in pull mode if true -- BK 11/6: default, no option
fuzeThresh = 10, -- Launch fuse if next to the highscore
qstabThresh = 1, -- Launch qstab if score is lower than otherwise, only wiggle
useLigand = false, --Use ligand if true
onlyMutable = false, -- If true use ONLY every mutable
mutateOnce = false, -- If true use mutate(1) instead of shake in qstab
mutateOnceCI = 0.21, -- Mutate with this CI
mutateAlways = false, -- If true use mutate(1) instead of each shake -- BK not used 11/6/2013
preciseBands=true, -- If false only use random bands
herd= -- options herd
{
breedBest = 3, --Number of best critters to breed
keepBest = 5, -- Number of best critters to keep
breedBastards = 2, -- Number of best critters to produce bastards
firstGen = 10, -- Number of critters in first generation
newRandom = 4, -- Number of random critters added for each generation
maxGen= 3, -- Maximum of generations
shuffle = true, -- Launch critters in random order
--After x generations that dont increase the score :
renew=1, -- create a completely random generation
maxBadGen=2, -- Stop the script after X generations that dont increase the score
},
critter= --critter options
{
minBands=2, --minimum bands
maxBands=5, --maximum bands
keepScore = -50 , -- Critters with lower score dont go to the next generation
breedScore= -20, -- Minimal score to do some kids. Bastards always breed
maxLoss=0, -- Maximum loss per critter
totalLoss=0, -- Maximum loss per generation
giveUp=200, -- Next critter if under this threshold
keepConditions=true, -- Next critter if a condition is lost
},
bands= --bands options
{
minStr=0.3, --minimum band str
maxStr=1.1, --maximum band str
minChng = 3, -- minimum change of band len according to current distance
maxUp = 6.1, -- maximum change up (push)
maxDn = 6.9, -- maximum change down (pull)
minSkip = 5, --minimum segment distance
minDist = 4, --minimum spatial distance
minLen = 2, --minimum length of created band
}
}-- end of userOptions
function setlanguage()-- New BK 10/4/13
local player=user.GetPlayerName()
local group=user.GetGroupName()
if group=="L'Alliance Francophone" or player==("marie_s" or "roukess" or "bruno.kestemont") then
uo.lang="fr"
else
uo.lang="en"
end
return uo.lang
end
function multilingual(lang)-- New BK 10/4/13
if lang=="fr" then
-- translation table. do NOT replace %-letter combos
i18n={
ask={
ok="OK",
cancel="Annuler",
options={
mainTitle="Options Ebola Rebuild",
l1="Zones",
contSegsMin="Segments min",
contSegsMax="Segments max",
numSegs="Test pires",
wholeProt="Toute la protine",
l2="Reconstructions",
rebuildNum="Recons./zone",
solsPerScore="Solutions/zone",
l3="Dclenchement de GAB",
scoreFilter="Filtre GAB",
passGAB ="Ne pas lancer GAB",
l4="Score",
allowLoss="Autoriser la perte",
lossThresh="Seuil perte",
l5="Autres",
rebuildLoops ="Transformer la protine en loops",
fastMode ="Pas de Fuze (beaucoup plus rapide)", -- BK 11/6/13
fastFuse="Fuze rapide (plus rapide, moins de points)",
mutateOnce="Muter au lieu de secouer", -- BK 11/6/13 was mutate once but we do not use mutate always in this version
resumeScript="Reprendre avec options du dernier arrt", -- BK 11/6/13
advanced="Plus",
GABOptions="GAB"
},
gab={
mainTitle="Options GAB",
l1="Gnrations",
totalLoss="Perte max GAB",
maxGen="Max gnrations",
l2="Max gnrations sans gain pour :",
renew="Lancer bandes non cibl.",
maxBadGen="Stopper",
l3="Critters",
firstGen="Crits 1r gn.",
maxLoss="Perte max/crit",
giveUp="Seuil abandon",
keepConditions="Conserver les conditions",
fuzeThresh="Seuil Fuze",
l4="Autre",
l5="Utiliser Ligand options : 0-jamais, 1-hasard, 2-toujours",
useLigand="Utiliser Ligand"
},
advanced={
mainTitle="Options avances",
l1="Filtres de reconstruction",
minRebuild="Filtre infrieur",
maxRebuild="Filtre suprieur",
l2="Gestion des sous-scores",
l3="Scores : 1-all, 2-backbone 3-sidechain, 4-other",
stIndex="Type de score",
l4="Forcer zone",
l5="Format: Dbut1,Fin1-Dbut2,Fin2...",
forceZoneStr="Zone force :",
zoneWalk ="Parcourir la zone force dans l'ordre",
l6="Lancement automatique de GAB",
autoGab="Autoriser GAB se lancer automatiquement",
gabThresh ="Seuil lancement",
l7="Autres",
rebuildCI="Clash recons.",
preciseBands="Bandes cibles",
rebuildBest="Reconstruire les meilleurs segments",
longfirst="Commencer par les plus grands, segments",
verbose="Afficher plus d'informations"
}
},
recipe={
sb=">>> Encore %.3f points gagner. Score : %.3f.",
gb1="Sauvegarde des bandes impossible. Dsactivation.",
gb2="Bandes sauvegardes. Suppression.",
tsc=">> Gain : %.3f points. Score : %.3f.",
tso1="Solution %i. Score : %.3f.",
tso2a="Lancement automatique de GAB.",
tso2b="Gain GAB auto : %.3f. Score : %.3f.",
tso3="chec de la solution. Poursuite du script.",
tso4="Meilleure solution. Score : %.3f.",
tso5="chec de la reconstruction, passage la zone suivante.",
dlr="* Reconstruction #%i.",
dlr2=">>> Microgain sauvegard.",
is1="Aucun segment ne correspond aux critres demands.",
is2="Reconstruction de toute la molcule.",
is3="tat du script restaur.",
e1="Zones de %i segments contigus.",
e2="Reconstruction des segments %i-%i.",
e3="* Score de la zone : %.3f.",
e4="* Donnes :",
e5="ATTENTION Perte autorise. Score : %.3f. Total : -%.3f.", -- BK 19/3/2013
e6="Gain total Ebola: %.3f. Score : %.3f.", --- ajoute Ebola BK 19/3/13
e7="Segment gel dtect. Passage la zone suivante.",
m1="Reprise du script.",
m2="Dbut Ebola Rebuild. Mode : %q. Score : %.3f.",
m3a="Traitement des paramtres initiaux termin.",
m3b="Parcours systmatique de la protine.",
fh="Cration de %i cratures alatoires...",
critter="%s : %i bandes.",
ab="* Impossible de crer de bandes. Arrt de GAB.",
sh1="Lancement de %i cratures...",
sh2a="Crature %s : %.3f.",
sh2b="Critres non respects. Abandon.",
bh="Appariement...",
g1="Lancement de GAB.",
g2="* Gnration : %i. Score : %.3f. Gain : %.3f",
g3="Cration d'une gnration entirement alatoire...",
g4="* Score final GAB : %.3f. Gain GAB: %.3f.", -- BK 20/3/13
lw1="Rtablissement du meilleur score.",
lw2="Rtablissement de la structure secondaire.",
lw3="Rtablissement des bandes.",
lw4="Sauvegarde de l'tat du script.",
de1="Arrt utilisateur.",
de2="Erreur inattendue dtecte.",
de3="Ligne d'erreur : %i.",
de4="Message d'erreur : %s."
}
}
else
i18n={
ask={
ok="OK",
cancel="Cancel",
options={
mainTitle="Ebola Rebuild options",
l1="Zones",
contSegsMin="Segments min",
contSegsMax="Segments max",
numSegs="Try worst",
wholeProt="Whole protein",
l2="Rebuild",
rebuildNum="Rebuild/zone",
solsPerScore="Solutions/zone",
l3="Threshold for GAB",
scoreFilter="GAB Filter",
passGAB ="Do not launch GAB",
l4="Score",
allowLoss="Allow loss",
lossThresh="loss threshold",
l5="Others",
rebuildLoops ="Transform protein to loop",
fastMode ="Skip Fuse (much faster)", -- BK 11/6/13
fastFuse="Fast Fuse (faster, less points)",
mutateOnce="Mutate instead of shake", -- BK 11/6/13 was mutate once but we do not use mutate always in this version
resumeScript="Continue with former options",
advanced="More",
GABOptions="GAB"
},
gab={
mainTitle="GAB Options",
l1="Generations",
totalLoss="GAB max loss",
maxGen="Max generations",
l2="Max generations without gain for :",
renew="Start full random",
maxBadGen="Stop",
l3="Critters",
firstGen="Crits 1r gen.",
maxLoss="Loss max/crit",
giveUp="Give up threshold",
keepConditions="Keep conditions",
fuzeThresh="Fuse threshold",
l4="Other",
l5="Use Ligand options : 0-Never, 1-Random, 2-Allways",
useLigand="Use Ligand"
},
advanced={
mainTitle="Advanced options",
l1="Rebuild filter",
minRebuild="Min filter",
maxRebuild="Max filter",
l2="Subscore management",
l3="Scores : 1-all, 2-backbone 3-sidechain, 4-other",
stIndex="Score type",
l4="Force zone",
l5="Format: Start1,End1-Start2,End2...",
forceZoneStr="Forced zone :",
zoneWalk ="Walk in the forced zone",
l6="Launch automatically GAB",
autoGab="Allow GAB to be automatically launched",
gabThresh ="Launch threshold",
l7="Others",
rebuildCI="Clash rebuild",
preciseBands="Precise bands",
rebuildBest="Rebuild best segments",
longfirst="Longest rebuild first",
verbose="Display more informations"
}
},
recipe={
sb=">>> Still %.3f points to gain. Score : %.3f.",
gb1="Impossible to save bands. Disabling.",
gb2="Bands saved. Deleting.",
tsc=">> Gain : %.3f points. Score : %.3f.",
tso1="Solution %i. Score : %.3f.",
tso2a="Launching GAB.",
tso2b="Gain GAB auto : %.3f. Score : %.3f.",
tso3="Fail of the solution.",
tso4="Best solution. Score : %.3f.",
tso5="Fail of the rebuild, next zone.",
dlr="* Rebuild #%i.",
dlr2=">>> Microgain saved.",
is1="No segment fit to the requested critter.",
is2="Whole protein rebuild.",
is3="Script state loaded.",
e1=" %i contiguous segments zone.",
e2="Rebuild of segments %i-%i.",
e3="* Zone score : %.3f.",
e4="* Data :",
e5="WARNING: Loss allowed. Score : %.3f. Total : -%.3f.", -- BK 19/3/2013
e6="Total Ebola gain: %.3f. Score : %.3f.", --- ajoute Ebola BK 19/3/13
e7="Frozen segment detected. Next zone.",
m1="Script recovered.",
m2="Start of Ebola Rebuild. Mode : %q. Score : %.3f.",
m3a="Initial parameters treatment completed.",
m3b="Whole protein walking.",
fh="Creating %i random critters...",
critter="%s : %i bands.",
ab="* Impossible to create bands. GAB stopped.",
sh1="Launching %i critters...",
sh2a="Critter %s : %.3f.",
sh2b="Unrespected critter. Give up.",
bh="Breeding...",
g1="Launching GAB.",
g2="* Generation : %i. Score : %.3f. Gain : %.3f",
g3="Create a completely random generation",
g4="* GAB final score : %.3f. Total Gain: %.3f.", -- idem BK
lw1="Loading Highscore....",
lw2="Loading secondary structure...",
lw3="Loading bands...",
lw4="Saving script state", -- added BK 21/3/13
de1="User stop.",
de2="unexpected error detected.",
de3="Error line: %i.",
de4="Error : %s."
}
}
end
return
end
-- Zones d'action de GAB
DoNotUse={} -- zones qui ne doivent pas recevoir de bandes. utiliser des zones du type {segDebut,segFin}
AlwaysUse={} -- zones toujours utilises. utiliser des zones du type {segDebut,segFin}
UseSegments={} -- utiliser seulement ces segments. sparer les numros des segments par des virgules
-- bands by secondary structure
use={
Sheet=true, --set false to not band sheets
Helix=true, --set false to not band helices
Loop=true, --set false to not band loops
}
checkBoth=false --check both ends to above, if false only one end need to be true
-- variables recette
segments=structure.GetCount()
--print("DEBUG: segments= "..segments)
subscores={ --select given score parts for calculating worst/best areas
{"clashing", "packing", "hiding", "bonding", "backbone", "sidechain", "disulfides", "density", "ideality", "reference"}, -- 1:All
{"clashing", "packing", "backbone", "ideality"}, -- 2:Backbone 07/02/2014
{"hiding", "bonding", "sidechain"}, -- 3:Sidechain
{"density", "reference"}, -- 4:Other
mode={"All", "Backbone", "Sidechain", "Other"}
}
uo.subscores=subscores
gabSlot=uo.solsPerScore+2
rbSlot=uo.solsPerScore+4
fuseSlot=uo.solsPerScore+5
score={ --global scores
best=current.GetEnergyScore(),
start=current.GetEnergyScore(),
cycle=0,
fuse=0,
recentbest=0
}
flag={ --global flags
mutable=false,
ligand=false,
gab=false,
selected=false,
mutate=false,
points=false,
save=false,
recentbest=false,
bands=false,
locked=false
}
index={ --global tables
mutable={},
ligand={},
frozens={},
bands={},
bndCnt=0, --if bands can't be saved, disable them and store their count
score={},
subscore={},
scoreTypes={},
bounds={1, segments}
}
-- core helpers
function GenerateSeed()--calculate REALLY good seed from current score
--local seed=recipe.GetRandomSeed() --NOT WORKING on windowz!!!
seed=os.time()
seed=1/seed
while seed<10^9 do seed=seed*10 end
seed=math.floor(seed)
math.randomseed(seed)
s1=structure.GetDistance(math.random(segments),math.random(segments))
s2=structure.GetDistance(math.random(segments),math.random(segments))
s3=structure.GetDistance(math.random(segments),math.random(segments))
seed=s1*seed^(1/s2)/s3
while seed<10^9 do seed=seed*10 end
seed=math.floor(seed)
--~ p("Seed is: "..seed)
math.randomseed(seed)
end
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function tlist(t) --table walk & unpack
local i, n=0, #t
return function ()
i=i+1
if i<=n then return unpack(t[i]) end
end
end
function tslice(array, len)
local tempArray={}
for i=1, len do tempArray[i]=array[i] end
return tempArray
end
function randf(n1,n2) -- returns random float between n1,n2
return math.random()*(n2-n1)+n1 --float between
end
function trand(arr) return arr[math.random(#arr)] end
function tobool(val)
local res
if type(val)=='number' then
if val==0 then res=false
elseif val==1 then res=true
else res=nil end
elseif type(val)=='string' then
if val=='false' then res=false
elseif val=='true' then res=true
else res=nil end
else res=nil end
return res
end
function SortL(a, b) return a[2]<b[2] end -- sort lower first
function SortH(a, b) return a[2]>b[2] end -- sort higher first
function SortC(a, b)
if #critters==0 then return false
else
local ac=critters[a] -- added BK 26/3/13
local bc=critters[b]-- added BK 26/3/13
if ac==nil or bc==nil then return false --added BK 27/4/13 against nil bug
else return ac.score<bc.score-- changed BK 26/3/13 -- SILL nil BUG here !!
end
end
end -- sort critters BUG nil BK 26/3/13
function puzzleprop() -- simplified version to identify filtered puzzles-- new BK 8/5/2013
local descrTxt=puzzle.GetDescription()
local puzzletitle=puzzle.GetName()
if #descrTxt>0 and (descrTxt:find("filter") or descrTxt:find("filters")) then
PROBABLEFILTER=true
end
return
end
puzzleprop() -- new BK 8/5/2013
-- game helpers
segCnt=structure.GetCount()
function p(printAlways, fmt, ...) --Lua = thebest, thebest, thebest
if not uo.verbose and not printAlways then return end -- more or less details
if #arg==0 then print(fmt or '')
elseif arg==nil then return--print(fmt or '')-- added BK 23/3/13 -- supressed empty lines 11/6/2013
elseif fmt==nil then return--print('')-- added BK 23/3/13 -- supressed empty lines 11/6/2013
else print(string.format(fmt, unpack(arg))) end
end
function Score()--return score, exploration too
return uo.energy and current.GetEnergyScore() or current.GetScore()
end
function CI(c)
if c>uo.maxCI then c=uo.maxCI end
behavior.SetClashImportance(c)
end
--START Archive in Notes, -- New 8/11/2014
function SelectNote(recipename)
store={}
store.label=recipename or "" -- edit here the recipe name
store.note_number=structure.GetCount()
for seg=structure.GetCount(),1,-1 do
if structure.GetNote(seg)~="" then break end
store.note_number=seg
end
print(string.format("Recording results in Note for segment %i",store.note_number))
store.starting_score=current.GetScore()
--structure.SetNote(store.note_number,string.format("(%s) %.3f + FSP",user.GetPlayerName(),store.starting_score))
end
SelectNote(recipename)
function WhriteNote(loop_nb) -- all inits are in SelectNote function
local loop_count= loop_nb or 1
structure.SetNote(store.note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),store.starting_score,store.label,loop_count,current.GetScore()))
end
--END Archive in Notes
--START quick save algorithm
function QuickShake(val)
--[[------------------------------------------------------------------------------------------------
-- Algorithm for faster shake
REFERENCES
1. N/A
Copyright (C) 2014 Seagat2011 <http://fold.it/port/user/1992490>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
$Id$
------------------------------------------------------------------------------------------------]]--
--[[
v1
- Inception
1.2
- Loops until nogain
]]--
local val= val or 1
local idx = 1
local idx2 = structure.GetCount ()
local hash = {}
local cs = current.GetScore ()
--print ( 'Quick Shake Algorithm v1.2 SG2011 - Current Score: '..cs )
local function New ( obj )
return obj -- pass-new-obj-by-value
end
local _gses = New ( current.GetSegmentEnergySubscore )
local function SmartShake ( iters )
local gain = true
while (gain) do
gain = false
for i=idx,idx2 do
local ci = _gses ( i,'clashing' )
if ci < _gses ( i,'hiding' ) and
ci < _gses ( i,'packing' ) and
ci < _gses ( i,'ideality' ) and
ci < _gses ( i,'sidechain') and
ci < _gses ( i,'bonding' ) and
ci < _gses ( i,'other' ) and
ci < _gses ( i,'reference') then
selection.Select ( i )
end -- test ci --
end -- loop --
if selection.GetCount () then
local css = current.GetScore ()
structure.ShakeSidechainsSelected ( iters )
selection.DeselectAll ()
if current.GetScore () > css then
gain = true
end -- test --
end -- test --
end -- loopf --
end
structure.SmartShake = SmartShake
structure.SmartShake ( val )
--print ( 'Done.' )
end
--END quick save algorithm
function Wiggle(how, iterW, fminppi) -- recursive wiggle
how=how or "wa"
iterW=iterW or 2 --nb d'iterations wiggle au debut
fminppi=fminppi or 1 -- factor minppi+/-nb de recursive wiggle
local cminppi=.005 --constant minppi
local ws=0
if flag.selected then ws=ws+1 end
if uo.mutateAlways or flag.mutate then ws=ws+10 end
function wShake()
if ws==0 then structure.ShakeSidechainsAll(1)
elseif ws==1 then QuickShake(1)
elseif ws==10 then structure.MutateSidechainsAll(1)
elseif ws==11 then structure.MutateSidechainsSelected(1)
end
end
function wWiggle()
if PROBABLEFILTER then behavior.SetSlowFiltersDisabled(true) end-- new BK 8/5/2013, always disable filter here
local b, s= true, true
if how=='wb' then s=false end
if ws==1 then structure.WiggleSelected(iterW, b, s)
else structure.WiggleAll(iterW, b, s)
end
if PROBABLEFILTER then behavior.SetSlowFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
end
if how=='s' then
wShake()
else
local sp=Score()
wWiggle()
if (Score()-sp)>(cminppi*(1+fminppi)) then -- minppi de plus en plus severe
Wiggle(how, iterW+1, fminppi+1) -- compense par cycles de plus en plus nombreux
end
end
how="wa"--reinitialiser les valeurs globales 09/02/2014
iterW=2 --
fminppi=1 --
end
function FuzeEnd()
CI(1)
Wiggle("s") -- quickshake
Wiggle("wa",30,.005) -- 09/02/2014
recentbest.Restore()
srb()
end
function Fuze1(ci1,ci2)
save.Quickload(fuseSlot)
recentbest.Save()
CI(ci1)
Wiggle("s")
CI(ci2)
Wiggle("wa",2,0.5)
FuzeEnd()
end
function Fuze2(ci1,ci2)
save.Quickload(fuseSlot)
recentbest.Save()
CI(ci1)
Wiggle("wa",1,0.5)
CI(1)
Wiggle("wa",6,0.5)
recentbest.Restore()
CI(ci2)
Wiggle("wa",1,0.5)
CI(1)
Wiggle("wa",10,.01) --09/02/2014
recentbest.Restore()
FuzeEnd()
end
function Fuze()
--~ p("*** GAB Fuzing...")
score.fuse=Score()
--~ selection.SelectAll()
save.Quicksave(fuseSlot)
if uo.fastFuse then
Fuze2(0.25,.55)
else
Fuze1(0.3,0.6)
Fuze1(0.02,1)
Fuze2(0.25,.55)
Fuze2(0.7,0.5)
Fuze2(0.5,0.7)
end
end
function srb()
local s=Score()
if s<=score.fuse then
save.Quickload(fuseSlot)
else
score.fuse=s
save.Quicksave(fuseSlot)
if flag.gab then
SaveBest()
else
TestScore(true) --sauver dans 100
end
end
end
function SaveBest()
local s=Score()
local g=s-bestScore
if g>0 then
if g>0.01 then
if s<=score.best then
p(true, i18n.recipe.sb, score.best-s, s)
else TestScore(true) end--sauver dans 100
end
bestScore=s
save.Quicksave(gabSlot)
end
end
function SaveRB()
local rb=recentbest.GetScore()
if rb>bestScore then
save.Quicksave(rbSlot)
recentbest.Restore()
ManageBands()
SaveBest()
save.Quickload(rbSlot)
recentbest.Save()
end
end
function Qstab() --adapted from tvdl BK 02/02/2014
--selection.SelectAll()--new
-- Do not accept qstab losses
recentbest.Save()--new
if uo.mutateOnce then
CI(uo.mutateOnceCI)
structure.MutateSidechainsSelected(1)
else
CI(0.02)
Wiggle("s")
--structure.ShakeSidechainsSelected(1)--new
end
if not uo.fastQstab then
CI(0.25)
Wiggle("wa",1,0.5)
CI(1)
Wiggle("s")
end
CI(1)
Wiggle("wa",30,.005)
recentbest.Restore() --new
end
function IsFrozen(seg)
a, b=freeze.IsFrozen(seg)
return a or b
end
function SetToLoop()
save.SaveSecondaryStructure()
selection.SelectAll()
structure.SetSecondaryStructureSelected("l")
selection.DeselectAll()
end
function DetectLigand()
local lastSeg1=structure.GetCount()
local lastSeg2=lastSeg1
while structure.GetSecondaryStructure(lastSeg1)=="M" do
flag.ligand=true
lastSeg1=lastSeg1-1
end
if lastSeg1+1==lastSeg2 then index.ligand={lastSeg2}
else index.ligand={lastSeg1, lastSeg2} end
end
function puzzleproblems()
local descrTxt=puzzle.GetDescription()
--p(descrTxt)
local puzzletitle=puzzle.GetName()
--p(puzzletitle)
if #puzzletitle>0 and puzzletitle:find("713") then
PROBLEMATIC=true
end
end
function DetectLock()
puzzleproblems()
if not PROBLEMATIC then
local start, stop=unpack(index.bounds)
while structure.IsLocked(start) do start=start+1 flag.locked=true end
while structure.IsLocked(stop) do stop=stop-1 flag.locked=true end
index.bounds={start, stop}
else
flag.locked=true
EmergencyAsk()
end
end
function EmergencyAsk()
local ask=dialog.CreateDialog("Ebola emergency options")
repeat
ask.l100=dialog.AddLabel("Unable to deal with this strange puzzle")
ask.l101=dialog.AddLabel("You should cancel Ebola")
ask.l1=dialog.AddLabel("Forcer zone (format: Dbut1,Fin1)")
ask.forceZoneStr=dialog.AddTextbox("Zone force :",uo.forceZoneStr)
ask.OK = dialog.AddButton("OK",1) ask.Cancel = dialog.AddButton("Cancel",0)
askresult=dialog.Show(ask)
if askresult > 0 then
if ask.forceZoneStr.value~='' then
for a,b in ask.forceZoneStr.value:gmatch('(%d+),(%d+)') do
table.insert(uo.forceZone,{a,b})
end
else
uo.forceZone={}
end
SetAndFlag(ask, 'forceZoneStr')
end
until askresult<2
return askresult > 0
end
function DetectMutables()
local muts={}
for i=1,segments do
if structure.IsMutable(i) then
flag.mutable=true
table.insert(muts, i)
end
end
index.mutable={muts[1], muts[#muts]}
end
function DetectFrozens()
for i=1, segments do
if IsFrozen(i) then table.insert(index.frozens, i) end
end
end
function GetSegFromDist(seg, dist)
local hasPassed, len, targetSeg=false, 0, 0
for i=1, segments do
hasPassed, len=pcall(structure.GetDistance,i,seg)
if not hasPassed then return false
else
if len==dist then return i end
end
end
end
function GetBands()
if band.GetCount()==0 then return end
local isOK=true
for i=1, band.GetCount() do
rope=band.AddToBandEndpoint(1,i)
len1=band.GetLength(i)
len2=band.GetLength(rope)
band.Delete(rope)
bandEnd1=GetSegFromDist(1, len2)
if not bandEnd1 then isOK=false break end
bandEnd2=GetSegFromDist(bandEnd1, len1)
if not bandEnd2 then isOK=false break end
table.insert(index.bands,{bandEnd1, bandEnd2})
end
if not isOK then
p(true, i18n.recipe.gb1)
index.bands={}
index.bndCnt=band.GetCount()
band.DisableAll()
else
p(true, i18n.recipe.gb2)
band.DeleteAll()
end
end
function RestoreBands()
if #index.bands==0 then return end
for end1, end2 in tlist(index.bands) do
band.AddBetweenSegments(end1, end2)
end
end
function RestoreFrozens()
if #index.frozens==0 then return end
for i=1, #index.frozens do selection.Select(index.frozens[i]) end
freeze.FreezeSelected(true, true)
selection.DeselectAll()
end
function SelectSphere(start, stop, size)
size=size or 12
for j=start, stop do
for i=1, segments do
if structure.GetDistance(j, i)<size then selection.Select(i) end
end
end
end
function SetCleanType(val)
if tonumber(val)~=nil then return tonumber(val)
elseif tobool(val)~=nil then return tobool(val)
else return val end
end
function ConcatArray(array, depth)
local s=''
local depth=depth or 1
local sep={' ',',','|'}
for key, val in pairs(array) do
if type(val)=='table' then
s=s..key..sep[depth+1]..ConcatArray(val, depth+1)..sep[depth]
else
s=s..key..':'..tostring(val)..sep[depth]
end
end
return s:sub(1,#s-1)
end
function RebuildArray(str, depth)
local arr={}
local depth=depth or 1
local sep={' ',',','|','%^'}
local subpat=''
for i=1, depth do subpat=subpat..sep[i] end
pattern="([^"..subpat.."]+)"
for entity in string.gmatch(str, pattern) do
if entity:find(sep[depth+1]) then
key=string.match(entity,"([^"..sep[depth+1].."]+)")
local len=#key
key=SetCleanType(key)
arr[key]=RebuildArray(entity:sub(len+2,#entity), depth+1)
else
key, val=string.match(entity,"([%w]+):([^"..subpat.."]+)")
if not key then
key=string.match(entity,"([%w]+):")
val=''
end
arr[SetCleanType(key)]=SetCleanType(val)
end
end
return arr
end
-- fin helpers
-- dbut Ebola
function SubScore(seg, scoreType)
scoreType=scoreType or "density"
if scoreType=='all' then return current.GetSegmentEnergyScore(seg)
else return current.GetSegmentEnergySubscore(seg,scoreType) end
end
function GenerateScoreTable()
index.score={} -- redondant ? BK ecrase ce qu'il y avait avant
index.subscore={} -- redondant ? BK ecrase ce qu'il y avait avant
local slot=1
local limit=0
if uo.solsPerScore%2==1 then limit=(uo.solsPerScore-1)/2
else limit=uo.solsPerScore/2-1 end
for i=1, uo.solsPerScore-limit do
slot=slot+1
table.insert(index.score,{slot, -math.huge})
end
for i=uo.solsPerScore-limit+2, uo.solsPerScore+1 do
slot=slot+1
table.insert(index.subscore,{slot, -math.huge})
end
for i=2, fuseSlot do save.Quicksave(i) end
end
function ReplaceLowest(arr, val)
if #arr==0 then return end
local flag=false
if val>arr[#arr][2] then
save.Quicksave(arr[#arr][1])
arr[#arr][2]=val
table.sort(arr, SortH)
flag=true
end
return arr, flag
end
function ScoreArea(seg, scoreType)
scoreType=scoreType or "density"
local tempScore=0
for i=seg, seg+uo.segs-1 do
tempScore=tempScore+SubScore(i, scoreType)
end
return tempScore
end
function StoreScore(seg)
local yetFlag=false -- don't keep same value twice
index.score, yetFlag=ReplaceLowest(index.score, Score())
if not yetFlag and #index.subscore>0 then
local mode = uo.stIndex~=4 and "clashing" or "density"
index.subscore, yetFlag=ReplaceLowest(
index.subscore, ScoreArea(seg, mode)
)
end
end
function TestScore(saveFlag)
local s=Score()
if s>score.best then
p(true, i18n.recipe.tsc, s-score.best, s)
score.best=s
WhriteNote() -- New 8/11/2014
if saveFlag then save.Quicksave(100) end
end
end
function FilterSegments(start, stop)
local isEmpty=true
local tempArray={}
for seg=start, stop-uo.segs do
local segscore=0
local data=''
for j, mode in ipairs(index.scoreTypes) do
local subscore=ScoreArea(seg, mode)
if subscore~=0 then
local areaIsGood=false
if uo.rebuildBest then
areaIsGood=(subscore/uo.segs)>uo.maxVal
else areaIsGood=(subscore/uo.segs)<=uo.maxVal
end
if areaIsGood then
segscore=segscore+subscore
data=data..'* '..mode..':'..subscore..'\n'
end
end
end
if segscore~=0 then
table.insert(tempArray,{seg, segscore, data})
isEmpty=false
end
end
local func=uo.rebuildBest and SortH or SortL
table.sort(tempArray,func)
if #tempArray<uo.numSegs then
uo.maxVal=uo.rebuildBest and uo.maxVal-5 or uo.maxVal+5
tempArray=FilterSegments(start, stop)
elseif #tempArray>uo.numSegs then
tempArray=tslice(tempArray, uo.numSegs)
end
return isEmpty and false or tempArray
end
function LaunchGab(seg)
if uo.preciseBands then
AlwaysUse={}
table.insert(AlwaysUse, {seg, seg+uo.segs-1})
end
if flag.ligand then
if uo.useLigand==0 then
segCnt=lastSeg1 -- was lastSeg but gave a nil bug line 1066-- BK 25/3/13
elseif uo.useLigand==2 then
table.insert(AlwaysUse, index.ligand)
end
end
GAB()
end
function TestSolutions(seg)
for i=2, uo.solsPerScore+1 do
save.Quickload(i)
if Score()~=score.cycle then
p(true, i18n.recipe.tso1, i-1, Score())
SelectSphere(seg,seg+uo.segs-1)
flag.selected=true
Wiggle('s')
flag.selected=false-- 02/02/2014
--structure.WiggleAll(25) -- BK 01/02/2014 nc
Wiggle("wa",30,.005) -- 09/02/2014 all
flag.selected=true-- 02/02/2014
local s=Score()
Fuze()-- selected TO DO: tester si pas mieux sur toute la prot
flag.selected=false
if uo.autoGab and Score()-s>uo.gabThresh then
p(true, i18n.recipe.tso2a)
s=Score()
LaunchGab(seg)
p(true, i18n.recipe.tso2b, Score()-s, s)
end
save.Quicksave(i)
TestScore(true) -- sauve en 100 si meilleur
else p(true, i18n.recipe.tso3) end
end
save.Quickload(2)
recentbest.Save()
for i=2, uo.solsPerScore+1 do save.Quickload(i) end
if flag.recentbest then save.Quickload(rbSlot) flag.recentbest=false end
recentbest.Restore()
local s=Score()
p(true, i18n.recipe.tso4, s)
if s>(score.best-uo.scoreFilter) and not uo.passGAB then
LaunchGab(seg)
else
p(true, i18n.recipe.tso5)
end
end
function DoLocalRebuild(seg)
for j=1, uo.rebuildNum do
p(false, i18n.recipe.dlr1, j)
save.Quickload(100)
selection.DeselectAll()
selection.SelectRange(seg,seg+uo.segs-1)
CI(uo.rebuildCI)
structure.RebuildSelected(1)
CI(1)
SelectSphere(seg,seg+uo.segs-1)
if uo.mutateOnce then flag.mutate=true end
flag.selected=true
Wiggle('s')
local sss=Score() -- new BK 02/02/2014 negative score bug
save.Quicksave(90) -- new BK 02/02/2014 negative score bug
flag.mutate=false
if not uo.fastMode then
local s=Score()
if (score.best-s)<uo.minRebuild or s>score.best then
Wiggle("wa",30,.005) --09/02/2014
if uo.mutateOnce then
flag.mutate=true
Wiggle('s')
Wiggle("wa",20,.1) --09/02/2014
flag.mutate=false
end
flag.selected=false
recentbest.Restore() -- added 02/02/2014 to fix negative score bug
s=Score()
if s<sss then save.Quickload(90) end -- new BK 02/02/2014 negative score bug
s=Score()
sss=Score()-- new BK 02/02/2014 negative score bug (reinitialisation)
save.Quicksave(90)-- new BK 02/02/2014 negative score bug
if math.abs(s-score.best)<uo.maxRebuild then --si a bouge dans un sens ou l'autre ?
--not an interesting solution, but a cent is a cent
if s>score.best and s>score.recentbest then
flag.recentbest=true
save.Quicksave(rbSlot)
p(false, i18n.recipe.dlr2)
score.recentbest=s
end
if s<sss then save.Quickload(90) end -- new BK 02/02/2014 negative score bug
else
StoreScore(seg)
TestScore(false)-- updates score.best , MAIS PAS slot100 ??? si rien n'a bouge
end
--else -- si solution pas dans les limites
--StoreScore(seg)-- BK 02/02/2014, on remplace quand meme une des 3 mauvaises solutions si possible
--TestScore(false) -- updates score.best , MAIS PAS slot100-- BK 02/02/2014
end
else
TestScore(true)-- updates score.best ET slot100 iff improvement
--TestScore(false) -- updates score.best , MAIS PAS slot100-- BK 30/03/2014
end
end -- Notons qu'a ce stade, on ne sauve rien dans 100, sauf si "rapide" TO DO: il y a un bug negatif en rapide !!!
end
function InitScript()
local start=1
local stop=segments
local array={}
if flag.mutable then
start, stop=unpack(index.mutable)
elseif flag.ligand then
stop=index.ligand[1]
elseif flag.locked then
start, stop=unpack(index.bounds)
end
local rebuildMode=0 -- normal mode
if #uo.forceZone>0 then rebuildMode=1
elseif uo.wholeProt then rebuildMode=2
elseif uo.resumeScript then rebuildMode=3
end
if rebuildMode==0 or rebuildMode==1 then
if rebuildMode==0 then
array=FilterSegments(start, stop, true)
elseif rebuildMode==1 then
for zs, ze in tlist(uo.forceZone) do --zone start, zone end
if ze-zs+2-uo.segs>0 then
for seg=zs, ze-uo.segs+1 do
local subscore=0
for j, mode in ipairs(index.scoreTypes) do
subscore=subscore+ScoreArea(seg, mode)
end
table.insert(array, {seg, subscore, ''})
end
end
end
if not uo.zoneWalk then
local func=uo.rebuildBest and SortH or SortL
table.sort(array,func)
end
end
if not array or #array<1 then
p(true, i18n.recipe.is1)
return false
end
stop=#array
elseif rebuildMode==2 then
stop=stop-uo.segs+1
for seg=start, stop do
table.insert(array, {seg, ScoreArea(seg)})
end
p(true, i18n.recipe.is2)
elseif rebuildMode==3 then
array=uo.curArray
start=uo.curSeg
if #array~=0 then stop=#array
elseif #uo.forceZone~=0 then stop=stop-uo.segs+1 end
uo.resumeScript=false
p(true, i18n.recipe.is3)
end
return start, stop, array
end
function Ebola()
p(true, '\n######################')
p(true, i18n.recipe.e1, uo.segs)
local startSeg, endSeg, lowSeg, areaScore, data
startSeg, endSeg, uo.curArray=InitScript()
if #uo.curArray<1 then return end
flag.points=true
for i=startSeg, endSeg do
uo.curSeg=i
if not uo.wholeProt then
lowSeg, areaScore, data=unpack(uo.curArray[i])
else lowSeg=i end
local hasLock=false
for j=lowSeg, lowSeg+uo.segs-1 do
if IsFrozen(j) or structure.IsLocked(j) then hasLock=true end
end
p(true, '--------')
p(true, i18n.recipe.e2, lowSeg, lowSeg+uo.segs-1)
if not uo.wholeProt then
score.cycle=Score()
p(false, i18n.recipe.e3, areaScore)
if #data>0 then
p(false, i18n.recipe.e4)
p(false, data)
end
p(false, '---')
end
if not hasLock then
GenerateScoreTable()
DoLocalRebuild(lowSeg)
selection.DeselectAll()
if not uo.fastMode then
TestSolutions(lowSeg)
end
TestScore(true) -- Sauver dans 100 ssi meilleur
local s=Score()
if uo.allowLoss and score.best-s<uo.lossThresh then
save.Quicksave(100) -- seul cas ou l'on sauve une perte dans 100 (sans changer score.best)
p(true, i18n.recipe.e5, s, score.best-s)
else
save.Quickload(100) -- reprendre le dernier meilleur
recentbest.Restore() -- added 30/03/2014 to fix negative score bug
TestScore(true) -- Sauver dans 100 ssi meilleur, added 30/03/2014 to fix negative score bug
p(true, i18n.recipe.e6, Score()-score.start, Score()) -- 30/03/2014 to fix negative score bug
end
else
p(true, i18n.recipe.e7)
end
end
end
function main()
setlanguage()-- New BK 10/4/13
multilingual(uo.lang)-- New BK 10/4/13
CI(1)
save.SaveSecondaryStructure()
recentbest.Save() -- New BK 24/6/2013
index.scoreTypes=subscores[uo.stIndex]
uo.scoringMode=subscores.mode[uo.stIndex]
GenerateSeed()
DetectLock()
DetectFrozens()
DetectMutables()
DetectLigand()
GetBands()
local saveTxt=structure.GetNote(1)
if #saveTxt>0 and saveTxt:find(uo.recipeName) then
flag.save=true
structure.SetNote(1,'')
end
if not AskOptions() then return end
if uo.resumeScript then
uo=RebuildArray(saveTxt)
uo.resumeScript=true
p(true, i18n.recipe.m1)
end
if uo.rebuildLoops then SetToLoop() end
save.Quicksave(100)
repeat
repeat
flag.points=false
p(true, i18n.recipe.m2, uo.scoringMode, score.best)
if not uo.resumeScript then loopStart=uo.contSegsMin
else loopStart=uo.segs end
for i=loopStart, uo.contSegsMax do
uo.segs=i
if uo.longfirst then uo.segs=uo.contSegsMax-i+loopStart end
Ebola()
end
until flag.points==false
if not uo.wholeProt then
p(true, i18n.recipe.m3a)
p(true, i18n.recipe.m3b)
uo.wholeProt=true
flag.points=true
end
until flag.points==false
LastWish()
end
-- fin Ebola
-- debut GAB
function ManageBands() --if bands can't be saved, prevent gab from deleting them
if index.bndCnt==0 then band.DeleteAll()
else
local bands=band.GetCount()
if bands>index.bndCnt then
for i=bands, index.bndCnt+1, -1 do band.Delete(i) end
end
end
band.DisableAll()
end
function ShuffleHerd()
if uo.herd.shuffle then
for i=1,#critters do
local r=math.random(#critters)
if r~=i then
critters[i],critters[r]=critters[r],critters[i]
end
end
end
end
function FillHerd() --fill up herd
local n=#critters
if n>0 then --fill up
n=uo.herd.newRandom
else --fresh herd
if uo.herd.maxGen~=1
and uo.herd.firstGen<uo.herd.keepBest then
n=uo.herd.breedBest + uo.herd.keepBest + uo.herd.breedBastards
else
n=uo.herd.firstGen
end
end
p(false, i18n.recipe.fs)
for i=1,n do AddCritter() end
end
function AddCritter() --create new random critter
local c={}
critterID=critterID+1
c.no=critterID
c.name=c.no..'-rnd'
c.bands={}
local r=math.random(uo.critter.minBands, uo.critter.maxBands)
for i=1,r do
table.insert(c.bands,AddBand())
end
table.insert(critters, c)
p(false, i18n.recipe.critter, c.name, #c.bands)
end
function AddBand() --create one random band
local cnt=0
local b={}
while true do --try till die
cnt=cnt+1
local s1=math.random(segCnt)
if uo.onlyMutable or #UseSegments>0 then
s1=trand(UseSegments)
end
local s2=math.random(segCnt)
if s1>s2 then s1,s2=s2,s1 end --swap
local bands=uo.bands
if CanBeUsed(s1,s2) then
local str=randf(bands.minStr,bands.maxStr)
local len=0
while true do --randomize correct distance
len=randf(-bands.maxDn,bands.maxUp)
if len<-bands.minChng
or len>bands.minChng
then break end
end
b={s1,s2,str,len}
break
end
if cnt>100 then
p(true, i18n.recipe.ab)
BreakScript() --there is no such function, so it crashes script
end
end
return b
end
function CanBeUsed(sg1,sg2) --checking end of bands
function ssCheck(ss)
local good=false
if use.Sheet and ss=="E" then good=true end
if use.Helix and ss=="H" then good=true end
if use.Loop and ss=="L" then good=true end
if uo.useLigand~=0 and ss=="M" then good=true end
return good
end
function AreGood(s1,s2) --check that s1 and s2 can be used
local ok=true
if s2-s1<uo.bands.minSkip then ok=false end
if ok and structure.GetDistance(s1,s2)<uo.bands.minDist then
ok=false end
return ok
end
local ok=AreGood(sg1,sg2)
if ok and #DoNotUse>0 then --none of 2 can be in that area
for start, stop in tlist(DoNotUse) do
for x=start, stop do
if x==sg1 or x==sg2 then
ok=false
break
end
end
if not ok then break end
end
end
if not ok then
return false --if false can`t be used
else
ok=false
if #UseSegments>0 then --at least one have to be there
for i=1, #UseSegments do
local r=UseSegments[i]
if r==sg1 or r==sg2 then
ok=true
break
end
end
else
ok=true
end
end
if ok then --check structure
ok=false
local ss1=structure.GetSecondaryStructure(sg1)
local ss2=structure.GetSecondaryStructure(sg2)
if checkBoth then
if ssCheck(ss1) and ssCheck(ss2) then ok=true end
else
if ssCheck(ss1) or ssCheck(ss2) then ok=true end
end
end
return ok
end
function ScoreHerd() --score all critters from herd
save.Quickload(gabSlot)
p(false, i18n.recipe.sh1, #critters)
save.Quicksave(gabSlot+1)
local herdScore=Score()
for i, crt in ipairs(critters) do
ManageBands()
local s=Score() --start score
for seg1, seg2, str, len in tlist(crt.bands) do
local a1=5
local a2=5
if seg1==segments then a1=6 end
if seg2==segments then a2=6 end
local ss1=structure.GetSecondaryStructure(seg1)
local ss2=structure.GetSecondaryStructure(seg2)
if ss1=='M' then a1=math.random(structure.GetAtomCount(seg1))
elseif ss2=='M' then a2=math.random(structure.GetAtomCount(seg2))
else
if structure.GetAminoAcid(seg1)=='g' then a1=0 end
if structure.GetAminoAcid(seg2)=='g' then a2=0 end
end
local bc=band.AddBetweenSegments(seg1,seg2,a1,a2)
band.SetStrength(bc,str)
local goalLen=structure.GetDistance(seg1,seg2)+len
if goalLen<uo.bands.minLen then goalLen=uo.bands.minLen end
band.SetGoalLength(bc,goalLen)
end
local conditions=current.AreConditionsMet()
selection.SelectAll()
CI(uo.pullCI)
recentbest.Save()
Wiggle('wb',2,0.5)
ManageBands()
SaveRB()
CI(1)
local test=true
if uo.critter.keepConditions then
if conditions then test=current.AreConditionsMet() end
end
local delta=s-Score()
test=uo.critter.giveUp>delta and test
if test then
if math.abs(delta) > uo.qstabThresh then Qstab()
else Wiggle("wa",30,.005) --09/02/2014
end
SaveRB()
if (bestScore-Score())<uo.fuzeThresh then Fuze() end
end
local s2=Score()
p(false, i18n.recipe.sh2a, crt.name, s2-s)
if not test then p(false, i18n.recipe.sh2b) end
if uo.critter.maxLoss>0 then
if s2>herdScore-uo.critter.maxLoss then
if s2<bestScore-uo.critter.totalLoss then
save.Quickload(gabSlot)
else
save.Quicksave(gabSlot+1)
herdScore=s2
end
else
save.Quickload(gabSlot+1)
end
else
save.Quickload(gabSlot)
end
end
save.Quickload(gabSlot)
end
function BreedCritters(mom,dad,t) --breed 2 critters. bands are taken randomly
local kid={}
critterID=critterID+1
kid.no=critterID
kid.name=kid.no.."-"..t..mom.no..'/'..dad.no
kid.bands={}
local mb=#mom.bands
local db=#dad.bands
if mb>db then mb,db=db,mb end --kid have bands count between mom and dad bands
local bn=math.random(mb,db)
for i=1,bn,2 do
table.insert(kid.bands, trand(mom.bands))
table.insert(kid.bands, trand(dad.bands))
end
p(false, i18n.recipe.critter, kid.name, #kid.bands)
return kid
end
function KeepGood() --copy best scoring critters form last gen if score above
local newHerd={}
for i=1,uo.herd.keepBest do
if critters[i].score==nil then critters[i].score=0 end -- bug nil BK 27/4/2013
if critters[i].score>uo.critter.keepScore and
(math.abs(critters[i].score)>0.1 or critters[i].score>0)
then
table.insert(newHerd, critters[i])
end
end
return newHerd
end
function BreedHerd()
p(false, i18n.recipe.bh)
table.sort(critters, SortC)
newHerd=KeepGood()
for i=1, uo.herd.breedBest do
local mom=critters[i]
if mom.score>uo.critter.breedScore
or i<2 then --breed only good ones, 1st is always bred anyway
for j=i+1, uo.herd.breedBest do
local dad=critters[j]
table.insert(newHerd, BreedCritters(mom,dad,"kid-"))
table.insert(newHerd, BreedCritters(dad,mom,"kid-"))
end
end
end
for i=1, uo.herd.breedBastards do --they will always appear ;]
local mom=critters[i]
local j=math.random(uo.herd.breedBastards+1,#critters)
local dad=critters[j]
table.insert(newHerd, BreedCritters(mom,dad,"bas-"))
table.insert(newHerd, BreedCritters(dad,mom,"bas-"))
end
critters=newHerd
FillHerd()
end
function GAB()
flag.gab=true
if uo.onlyMutable then
for i=1,segCnt do
if structure.IsMutable(i) then
table.insert(UseSegments, i)
end
end
end
if #AlwaysUse>0 then
for ss, se in tlist(AlwaysUse) do
--~ if ss>se then ss,se=se,ss end --automated, no check needed
if se==nil then table.insert(UseSegments, ss)
else for j=ss,se do table.insert(UseSegments, j) end
end
end
AlwaysUse={} --added to list, no need to check later
end
bestScore=Score()
critterID=0
gen=0
ss=Score()
save.Quicksave(gabSlot)
recentbest.Save()
p(true, i18n.recipe.g1)
critters={}
FillHerd()
badGen=0
while true do --this is (almost) endless script ;]
genScore=Score()
gen=gen+1
ShuffleHerd() -- changed BK 18/3/2013 -- if was redondant: if uo.herd.shuffle then ShuffleHerd() end
ScoreHerd()
save.Quickload(gabSlot)
if gen==uo.herd.maxGen then break end --end of script
local genScore2=Score()
if genScore>=genScore2 then
badGen=badGen+1
if badGen==uo.herd.maxBadGen then break end
else
badGen=0
end
p(true, i18n.recipe.g2, gen, genScore2, genScore2-genScore)
if badGen>=uo.herd.renew then
p(false, i18n.recipe.g3)
critters={}
FillHerd()
badGen=0
else
BreedHerd()
end
end
p(true, i18n.recipe.g4, Score(), Score()-ss)
flag.gab=false
end
-- fin GAB
-- dialogues, debug, lancement
function MakeFancyHeader(s)
return '----- '..s..' '..string.rep('-', 54-#s-7)
end
function SetAndFlag(dial, var, sub) -- fonction de sauvegarde
local val=dial[var].value
if not sub then uo[var]=val
else uo[sub][var]=val
end
end
function AskOptions()
local ask=dialog.CreateDialog(i18n.ask.options.mainTitle)
repeat
ask.l1=dialog.AddLabel(MakeFancyHeader(i18n.ask.options.l1))
ask.contSegsMin=dialog.AddSlider(i18n.ask.options.contSegsMin, uo.contSegsMin, 1, 20, 0)
ask.contSegsMax=dialog.AddSlider(i18n.ask.options.contSegsMax, uo.contSegsMax, 1, 20, 0)
ask.numSegs=dialog.AddSlider(i18n.ask.options.numSegs,uo.numSegs, 1, 50, 0)
ask.wholeProt=dialog.AddCheckbox(i18n.ask.options.wholeProt, uo.wholeProt)
ask.l2=dialog.AddLabel(MakeFancyHeader(i18n.ask.options.l2))
ask.rebuildNum=dialog.AddSlider(i18n.ask.options.rebuildNum, uo.rebuildNum, 1, 200, 0)
ask.solsPerScore=dialog.AddSlider(i18n.ask.options.solsPerScore, uo.solsPerScore, 1, 20, 0)
ask.l3=dialog.AddLabel(MakeFancyHeader(i18n.ask.options.l3))
ask.scoreFilter=dialog.AddSlider(i18n.ask.options.scoreFilter, uo.scoreFilter, 0, 50, 0)
ask.passGAB = dialog.AddCheckbox(i18n.ask.options.passGAB, uo.passGAB)
ask.l4=dialog.AddLabel(MakeFancyHeader(i18n.ask.options.l4))
ask.allowLoss=dialog.AddCheckbox(i18n.ask.options.allowLoss, uo.allowLoss)
ask.lossThresh=dialog.AddSlider(i18n.ask.options.lossThresh, uo.lossThresh, 1, 200, 0)
ask.l5=dialog.AddLabel(MakeFancyHeader(i18n.ask.options.l5))
ask.rebuildLoops = dialog.AddCheckbox(i18n.ask.options.rebuildLoops, uo.rebuildLoops)
ask.fastMode = dialog.AddCheckbox(i18n.ask.options.fastMode, uo.fastMode)
ask.fastFuse=dialog.AddCheckbox(i18n.ask.options.fastFuse, uo.fastFuse)
if flag.mutable then
ask.mutateOnce=dialog.AddCheckbox(i18n.ask.options.mutateOnce,uo.mutateOnce)
end
if flag.save then
ask.resumeScript=dialog.AddCheckbox(i18n.ask.options.resumeScript,uo.resumeScript)
end
ask.ok = dialog.AddButton(i18n.ask.ok, 1)
ask.cancel = dialog.AddButton(i18n.ask.cancel, 0)
ask.advanced=dialog.AddButton(i18n.ask.options.advanced, 2)
ask.GABOptions=dialog.AddButton(i18n.ask.options.GABOptions, 3)
askresult=dialog.Show(ask)
if askresult > 0 then
SetAndFlag(ask, 'contSegsMin')
SetAndFlag(ask, 'contSegsMax')
SetAndFlag(ask, 'numSegs')
SetAndFlag(ask, 'wholeProt')
SetAndFlag(ask, 'rebuildNum')
SetAndFlag(ask, 'solsPerScore')
SetAndFlag(ask, 'scoreFilter')
SetAndFlag(ask, 'passGAB')
SetAndFlag(ask, 'allowLoss')
SetAndFlag(ask, 'lossThresh')
SetAndFlag(ask, 'rebuildLoops')
SetAndFlag(ask, 'fastMode')
SetAndFlag(ask, 'fastFuse')
if flag.mutable then
SetAndFlag(ask, 'mutateOnce')
end
if flag.save then
SetAndFlag(ask, 'resumeScript')
end
if askresult==2 then AskAdvanced()
elseif askresult==3 then AskGABOptions() end
end
until askresult<2
return askresult > 0
end
function AskGABOptions()
local ask=dialog.CreateDialog(i18n.ask.gab.mainTitle)
ask.l1=dialog.AddLabel(MakeFancyHeader(i18n.ask.gab.l1))
ask.totalLoss=dialog.AddSlider(i18n.ask.gab.totalLoss,uo.critter.totalLoss,0,100,0)
ask.maxGen=dialog.AddSlider(i18n.ask.gab.maxGen,uo.herd.maxGen,1,50,0)
ask.l2=dialog.AddLabel(i18n.ask.gab.l2)
ask.renew=dialog.AddSlider(i18n.ask.gab.renew,uo.herd.renew,1,50,0)
ask.maxBadGen=dialog.AddSlider(i18n.ask.gab.maxBadGen,uo.herd.maxBadGen,1,50,0)
ask.l3=dialog.AddLabel(MakeFancyHeader(i18n.ask.gab.l3))
ask.firstGen=dialog.AddSlider(i18n.ask.gab.firstGen,uo.herd.firstGen,1,50,0)
ask.maxLoss=dialog.AddSlider(i18n.ask.gab.maxLoss,uo.critter.maxLoss,0,100,0)
ask.giveUp=dialog.AddSlider(i18n.ask.gab.giveUp,uo.critter.giveUp,0,500,0)
ask.keepConditions=dialog.AddCheckbox(i18n.ask.gab.keepConditions,uo.critter.keepConditions)
ask.fuzeThresh=dialog.AddSlider(i18n.ask.gab.fuzeThresh,uo.fuzeThresh,-.001,50,0)
if flag.ligand then
ask.l4=dialog.AddLabel(MakeFancyHeader(i18n.ask.gab.l4))
ask.l5=dialog.AddLabel(i18n.ask.gab.l5)
ask.useLigand=dialog.AddSlider(i18n.ask.gab.useLigand,uo.useLigand,0,2,0)
end
ask.ok = dialog.AddButton(i18n.ask.ok,1)
dialog.Show(ask)
SetAndFlag(ask, 'maxGen', 'herd')
SetAndFlag(ask, 'firstGen', 'herd')
SetAndFlag(ask, 'renew', 'herd')
SetAndFlag(ask, 'maxBadGen', 'herd')
SetAndFlag(ask, 'maxLoss', 'critter')
SetAndFlag(ask, 'totalLoss', 'critter')
SetAndFlag(ask, 'giveUp', 'critter')
SetAndFlag(ask, 'keepConditions', 'critter')
SetAndFlag(ask, 'fuzeThresh')
if flag.ligand then
SetAndFlag(ask, 'useLigand')
end
end
function AskAdvanced()
local ask=dialog.CreateDialog(i18n.ask.advanced.mainTitle)
ask.l1=dialog.AddLabel(MakeFancyHeader(i18n.ask.advanced.l1))
ask.minRebuild=dialog.AddSlider(i18n.ask.advanced.minRebuild,uo.minRebuild,0,5000,0)
ask.maxRebuild=dialog.AddSlider(i18n.ask.advanced.maxRebuild,uo.maxRebuild,0,1,3)
ask.l2=dialog.AddLabel(MakeFancyHeader(i18n.ask.advanced.l2))
ask.l3=dialog.AddLabel(i18n.ask.advanced.l3)
ask.stIndex=dialog.AddSlider(i18n.ask.advanced.stIndex,uo.stIndex,1,4,0)
ask.l4=dialog.AddLabel(MakeFancyHeader(i18n.ask.advanced.l4))
ask.l5=dialog.AddLabel(i18n.ask.advanced.l5)
ask.forceZoneStr=dialog.AddTextbox(i18n.ask.advanced.forceZoneStr, uo.forceZoneStr)
ask.zoneWalk = dialog.AddCheckbox(i18n.ask.advanced.zoneWalk, uo.zoneWalk)
ask.l6=dialog.AddLabel(MakeFancyHeader(i18n.ask.advanced.l6))
ask.autoGab=dialog.AddCheckbox(i18n.ask.advanced.autoGab,uo.autoGab)
ask.gabThresh=dialog.AddSlider(i18n.ask.advanced.gabThresh,uo.gabThresh,0,50,0)
ask.l7=dialog.AddLabel(MakeFancyHeader(i18n.ask.advanced.l7))
ask.rebuildCI=dialog.AddSlider(i18n.ask.advanced.rebuildCI,uo.rebuildCI,0,1,2)
ask.preciseBands=dialog.AddCheckbox(i18n.ask.advanced.preciseBands,uo.preciseBands)
ask.rebuildBest=dialog.AddCheckbox(i18n.ask.advanced.rebuildBest,uo.rebuildBest)
ask.longfirst=dialog.AddCheckbox(i18n.ask.advanced.longfirst,uo.longfirst)
ask.verbose=dialog.AddCheckbox(i18n.ask.advanced.verbose,uo.verbose) -- desactive (bug) BK 22/3/13
ask.ok = dialog.AddButton(i18n.ask.ok,1)
dialog.Show(ask)
SetAndFlag(ask, 'minRebuild')
SetAndFlag(ask, 'maxRebuild')
SetAndFlag(ask, 'stIndex')
index.scoreTypes=subscores[ask.stIndex.value]
uo.scoringMode=subscores.mode[uo.stIndex]
if ask.forceZoneStr.value~='' then
for a,b in ask.forceZoneStr.value:gmatch('(%d+),(%d+)') do
table.insert(uo.forceZone,{a,b})
end
else
uo.forceZone={}
end
SetAndFlag(ask, 'forceZoneStr')
SetAndFlag(ask, 'zoneWalk')
SetAndFlag(ask, 'autoGab')
SetAndFlag(ask, 'gabThresh')
SetAndFlag(ask, 'rebuildCI')
SetAndFlag(ask, 'preciseBands')
SetAndFlag(ask, 'rebuildBest')
SetAndFlag(ask, 'longfirst')
SetAndFlag(ask, 'verbose')
end
function DumpErr(err)
start,stop,line,msg=err:find(":(%d+):%s()")
err=err:sub(msg,#err)
p(true, '---')
if err:find('Cancelled')~=nil then
p(true, i18n.recipe.de1)
else
p(true, i18n.recipe.de2)
p(true, i18n.recipe.de3, line)
p(true, i18n.recipe.de4, err)
end
LastWish()
end
function LastWish()
p(true, i18n.recipe.lw1)
recentbest.Save()
for i=1, fuseSlot do
save.Quickload(i)
end
save.Quickload(100)
if uo.rebuildLoops then
p(true, i18n.recipe.lw2)
save.LoadSecondaryStructure()
end
if #index.bands>0 then
p(true, i18n.recipe.lw3)
RestoreBands()
end
p(true, i18n.recipe.lw4)
WhriteNote() -- New 8/11/2014
structure.SetNote(1,ConcatArray(uo))
CI(1)
end
xpcall(main, DumpErr)
--~ main()