-- QuickMutate by Crashguard303
-- Improvements by rav3n_pl
-- Mutating takes a long time, if you have selected all segments, because it checks the new positions of all segments at once and does a shake.
-- This function tries to do it not better, but faster, by testing all amino-acids through all (selected) segments.
function CompactContent() -- Show
print("Mutating will work on these segments:")
local OS=""
local E=0
local k
for k=SegA,SegB,StepSz do
if is_mutable[k] then
OS=OS..k.." "
E=E+1
if E==10 then
E=0
OS=OS.."\n"
end -- if E
end -- if is_mutable
end -- k
print(OS)
end --function
function SetMutableRange(A,B,bool)
--- Applies all segments of "is_mutable" which are ibetween A and B to value of "bool"
local A=A
local B=B
local bool=bool
local k
for k=A,B do -- cycle from segment A to B
is_mutable[k]=bool -- set is_mutable at this position to bool
end -- k loop
end -- function
function SetMutableValues(field,bool)
-- Applies all segments of "is_mutable" which are in "field" to value of "bool"
-- If field is empty, all "is_mutable" values are changed to "bool"
local field=field -- target table
local Length=get_field_length(field) -- fetch its length
local bool=bool
local k
if Length>0 then -- if table to add is not empty
for k=1,Length do -- cycle through all elements from table
is_mutable[field[k]]=bool -- set is_mutable at this position to bool
end -- k loop
else -- if table is empty, regard all segments as mutable
for k=SegA,SegB,StepSz do
is_mutable[k]=bool
end -- l loop
end -- if Length
end -- function
function get_field_length(field)
-- checks how many entries are in a list (table)
local field=field
local k=1
while field[k]~=nil do
k=k+1
end
return k-1
end -- function
function MutableCheck()
-- Store in checklist table is_mutable, if a segment is mutable or not
if ListCheck then -- Check is_mutable list only if ListCheck is true
print("Checking for mutable segments")
print("between ",SegA," and ",SegB," Stepsize:",StepSz)
quicksave(1) -- Store puzzle before test
local k
for k=SegA,SegB,StepSz do -- Cycle through segments
if is_mutable[k] then -- If current segment is marked as mutable, check this
-- print(k)
deselect_all()
select_index(k)
replace_aa("g")
local aa1=get_aa(k) -- Store result, to check that mutate was successful
replace_aa("a")
local aa2=get_aa(k) -- Store result, to check that mutate was successful
if aa1~=aa2 then
-- Compare both results, to guarantee that the sidechain wasn't like this already (before mutating)
is_mutable[k]=true
print(k," is mutable.")
else
is_mutable[k]=false
end -- if aa1~=aa2
end -- if is_mutable
end -- k loop
quickload(1) -- restore puzzle after test, as the test did some changes
end -- if ListChek
CompactContent()
end -- function
function RandomOrder(SideChLetter)
used={}
for k=1,20 do
used[k]=0
end -- k
SideChLetter2={}
Score=get_score(true)
Offset=integervalue(Score)
Amount=(Score-Offset)*20
PsRandom=Offset-Amount
for k=1,20 do
PsRandom=PsRandom+Amount
while PsRandom>=21 do
PsRandom=PsRandom-20
end
while PsRandom<=0 do
PsRandom=PsRandom+20
end
PsRandom2=integervalue(PsRandom)
while used[PsRandom2]==1 do
PsRandom2=PsRandom2+1
if PsRandom2>20 then PsRandom2=1 end
end
SideChLetter2[k]=SideChLetter[PsRandom2]
used[PsRandom2]=1
print("Random transformed Letter# ",k," to letter# ",PsRandom2," which is ",SideChLetter2[k])
end -- k
return SideChLetter2
end -- function
function SpecialShake(iter)
ScoreBefore=get_score(true)
do_shake(1)
Delta=get_score(true)-ScoreBefore
if Delta>0 then do_shake(iter) end
end
function ReverseOrder(x)
x2={}
for k=1,20 do
x2[k]=x[21-k]
end -- k
return x2
end -- function
function absolutevalue(x)
local y=x
if y<0 then y=y*-1 end
return y
end
function integervalue(x) -- integer function
if (x==0 or x==nil) then int=0
else
if x>0 then sign=1
else sign=-1
end
x2=x*sign
rest=x2-x2%1
int=rest*sign
end
return int
end
function change_all_segments(OrderStyle ,Acid,SegN,ShakeIter)
if is_mutable[SegN] then -- replace segment only if it is mutable
deselect_all()
select_index(SegN)
local ScoreAfter=get_score(true)
print("Score: ",ScoreAfter)
local Delta=ScoreAfter-ScoreBefore
if Delta<0 then
restore_recent_best() -- If this try made worse result, restore puzzle
elseif Delta==0 then
reset_recent_best() -- an equal result counts as "better result", because of its properties
-- elseif Delta>0
-- reset_recent best does the game automatically
end --if Delta
end -- if is_mutable
end
function QuickMutate()
local SideChSet={}
SideChSet[1]={"G";"A";"V";"C";"P";"T";"S";"I";"L";"N";"D";"M";"H";"Q";"E";"F";"K";"Y";"R";"W"}
SideChSet[2]={"G";"A";"V";"C";"P";"I";"L";"M";"F";"Y";"W";"T";"S";"N";"D";"H";"Q";"E";"K";"R"}
SideChSet[3]={"G";"A";"V";"C";"T";"S";"P";"I";"L";"N";"D";"M";"H";"Q";"E";"F";"K";"Y";"R";"W"}
SideChSet[4]={"I";"V";"L";"F";"C";"M";"A";"G";"W";"Y";"P";"T";"S";"H";"N";"D";"Q";"E";"K";"R"}
SideChSet[5]={"I";"V";"L";"F";"C";"M";"A";"G";"T";"S";"W";"Y";"P";"H";"N";"D";"Q";"E";"K";"R"}
if (OrderStyle ==0 or absolutevalue(OrderStyle )>5) then OrderStyle =1 end
-- Check if OrderStyle has a valid value
SideChLetter=SideChSet[absolutevalue(OrderStyle )]
-- Select Sidechain order out of Sidechain sets
if OrderStyle <0 then SideChLetter=ReverseOrder(SideChLetter) end
-- if OrderStyle is negative, revert sidechain order
if Random==true then SideChLetter=RandomOrder(SideChLetter) end
-- if Random flag is true, scramble orde list
if GStart==true then select_all() replace_aa("G") end
-- if GStart is true, set all acids to Glycine before testing
ShakeIter=integervalue(ShakeIter)
reset_recent_best() -- store puzzle state before changes are done
local ScoreAtStart=get_score(true) -- get score at script start
if InsideOut==false then
for l=1,20 do -- cycle through all 20 acids
for k=SegA,SegB,StepSz do -- and try them on each segment
if GStart==false or SideChLetter[l]~="G" then change_all_segments(OrderStyle ,l,k,ShakeIter) end
end -- k
end -- l
else -- if InsideOut is true
for k=SegA,SegB,StepSz do -- cycle through all segments
for l=1,20 do -- and try all 20 acids
if GStart==false or SideChLetter[l]~="G" then change_all_segments(OrderStyle ,l,k,ShakeIter) end
end -- l
end -- k
end -- if InsideOut
if ShakeIter>0 then SpecialShake(ShakeIter) end
local ScoreAtEnd=get_score(true) -- get score at script end
print("Score at mutate start: ",ScoreAtStart)
print("Score at mutate end: ",ScoreAtEnd)
print("Score difference: ",ScoreAtEnd-ScoreAtStart)
end -- function
-- DESCRIPTION / HOW TO USE:
-- Variables:
is_mutable={}
-- Initialize flag table which shows with boolean values (true,false), which segments are mutable and which are not
SegA=1
-- The first segment you want to Quick-Mutate, integer value
-- Must be 1 or bigger
SegB=get_segment_count()
-- The last segment you want to Quick-Mutate, integer value
-- Must be bigger or equal than SegA and lower or equal Puzzle size
StepSz=1 -- the stepsize, so you can skip some segments if you want
SetMutableRange(SegA,SegB,true) -- Set all segments as mutable
-- SetMutableValues({},true) -- Example. Alternative method to set all segments as mutable.
-- SetMutableValues({},false) -- Example. Alternative method to set all segments as not mutable.
-- SetMutableRange(1,5,true) -- Example. Use this to set segments 1 to 5 as mutable.
-- SetMutableRange(1,5,false) -- Example. Use this to set segments 1 to 5 as not mutable.
-- SetMutableValues({10;12;15},true) -- Example. Use this to set segment 10,12,15 as mutable.
-- SetMutableValues({10;12;15},false) -- Example. Use this to set segment 10,12,15 as not mutable.
ListCheck=true -- If true, test segments
-- Set this to false if you are sure your segment lists are right and don't need to be tested.
GStart=false -- If true, all possible sidechains (SC) are set to Glycine before performing the whole task, so that you have a reference.
-- default is false
OrderStyle=1 -- Selects the order, of how the SC are tried. See following tab.
-- Co means color,Le length, HI hydorpathy index. Leftmost position means maximum priority.
-- If you use negative values, the tried ss order is backwards.
-- So, valid styles are 1 to 5 and -1 to -5
-- Every other value uses style 1, which lets the Sidechains "grow out" of the backbone ;)
Random=false -- true=your chosen list will be used but scrambled dependent on the score as seeding value.
-- false=No scrambling
ShakeIter=0 -- =0 no shake
-- >0 A shake is performed at the very end with the batch,
-- within the selected number of iterations.
-- <0 A shake is performed after every change of sidechain.
InsideOut=false -- false=regular behaviour. Acid is chosen, tested through all segments, then next acid is tested.
-- true=alternate behaviour. Segment is chosen, all acids are tried, then next segment is tested.
-- END OF DESCRIPTION
MutableCheck() -- Before start, check is_mutable entries (if ListCheck is true) and show them
QuickMutate() -- Execute QuickMutate
-- QuickMutate by Crashguard303
-- Improvements by rav3n_pl
-- Mutating takes a long time, if you have selected all segments, because it checks the new positions of all segments at once and does a shake.
-- This function tries to do it not better, but faster, by testing all amino-acids through all (selected) segments.
function CompactContent() -- Show
print("Mutating will work on these segments:")
local OS=""
local E=0
local k
for k=SegA,SegB,StepSz do
if is_mutable[k] then
OS=OS..k.." "
E=E+1
if E==10 then
E=0
OS=OS.."\n"
end -- if E
end -- if is_mutable
end -- k
print(OS)
end --function
function SetMutableRange(A,B,bool)
--- Applies all segments of "is_mutable" which are ibetween A and B to value of "bool"
local A=A
local B=B
local bool=bool
local k
for k=A,B do -- cycle from segment A to B
is_mutable[k]=bool -- set is_mutable at this position to bool
end -- k loop
end -- function
function SetMutableValues(field,bool)
-- Applies all segments of "is_mutable" which are in "field" to value of "bool"
-- If field is empty, all "is_mutable" values are changed to "bool"
local field=field -- target table
local Length=get_field_length(field) -- fetch its length
local bool=bool
local k
if Length>0 then -- if table to add is not empty
for k=1,Length do -- cycle through all elements from table
is_mutable[field[k]]=bool -- set is_mutable at this position to bool
end -- k loop
else -- if table is empty, regard all segments as mutable
for k=SegA,SegB,StepSz do
is_mutable[k]=bool
end -- l loop
end -- if Length
end -- function
function get_field_length(field)
-- checks how many entries are in a list (table)
local field=field
local k=1
while field[k]~=nil do
k=k+1
end
return k-1
end -- function
function MutableCheck()
-- Store in checklist table is_mutable, if a segment is mutable or not
if ListCheck then -- Check is_mutable list only if ListCheck is true
print("Checking for mutable segments")
print("between ",SegA," and ",SegB," Stepsize:",StepSz)
quicksave(1) -- Store puzzle before test
local k
for k=SegA,SegB,StepSz do -- Cycle through segments
if is_mutable[k] then -- If current segment is marked as mutable, check this
-- print(k)
deselect_all()
select_index(k)
replace_aa("g")
local aa1=get_aa(k) -- Store result, to check that mutate was successful
replace_aa("a")
local aa2=get_aa(k) -- Store result, to check that mutate was successful
if aa1~=aa2 then
-- Compare both results, to guarantee that the sidechain wasn't like this already (before mutating)
is_mutable[k]=true
print(k," is mutable.")
else
is_mutable[k]=false
end -- if aa1~=aa2
end -- if is_mutable
end -- k loop
quickload(1) -- restore puzzle after test, as the test did some changes
end -- if ListChek
CompactContent()
end -- function
function RandomOrder(SideChLetter)
used={}
for k=1,20 do
used[k]=0
end -- k
SideChLetter2={}
Score=get_score(true)
Offset=integervalue(Score)
Amount=(Score-Offset)*20
PsRandom=Offset-Amount
for k=1,20 do
PsRandom=PsRandom+Amount
while PsRandom>=21 do
PsRandom=PsRandom-20
end
while PsRandom<=0 do
PsRandom=PsRandom+20
end
PsRandom2=integervalue(PsRandom)
while used[PsRandom2]==1 do
PsRandom2=PsRandom2+1
if PsRandom2>20 then PsRandom2=1 end
end
SideChLetter2[k]=SideChLetter[PsRandom2]
used[PsRandom2]=1
print("Random transformed Letter# ",k," to letter# ",PsRandom2," which is ",SideChLetter2[k])
end -- k
return SideChLetter2
end -- function
function SpecialShake(iter)
ScoreBefore=get_score(true)
do_shake(1)
Delta=get_score(true)-ScoreBefore
if Delta>0 then do_shake(iter) end
end
function ReverseOrder(x)
x2={}
for k=1,20 do
x2[k]=x[21-k]
end -- k
return x2
end -- function
function absolutevalue(x)
local y=x
if y<0 then y=y*-1 end
return y
end
function integervalue(x) -- integer function
if (x==0 or x==nil) then int=0
else
if x>0 then sign=1
else sign=-1
end
x2=x*sign
rest=x2-x2%1
int=rest*sign
end
return int
end
function change_all_segments(OrderStyle ,Acid,SegN,ShakeIter)
if is_mutable[SegN] then -- replace segment only if it is mutable
deselect_all()
select_index(SegN)
local ScoreBefore=get_score(true)
print("OrderStyle #",OrderStyle ," Segment#",SegN," Acid#",Acid," Letter:",SideChLetter[Acid])
replace_aa(SideChLetter[Acid]) -- try Amino Acid
if ShakeIter<0 then SpecialShake(-ShakeIter) end
local ScoreAfter=get_score(true)
print("Score: ",ScoreAfter)
local Delta=ScoreAfter-ScoreBefore
if Delta<0 then
restore_recent_best() -- If this try made worse result, restore puzzle
elseif Delta==0 then
reset_recent_best() -- an equal result counts as "better result", because of its properties
-- elseif Delta>0
-- reset_recent best does the game automatically
end --if Delta
end -- if is_mutable
end
function QuickMutate()
local SideChSet={}
SideChSet[1]={"G";"A";"V";"C";"P";"T";"S";"I";"L";"N";"D";"M";"H";"Q";"E";"F";"K";"Y";"R";"W"}
SideChSet[2]={"G";"A";"V";"C";"P";"I";"L";"M";"F";"Y";"W";"T";"S";"N";"D";"H";"Q";"E";"K";"R"}
SideChSet[3]={"G";"A";"V";"C";"T";"S";"P";"I";"L";"N";"D";"M";"H";"Q";"E";"F";"K";"Y";"R";"W"}
SideChSet[4]={"I";"V";"L";"F";"C";"M";"A";"G";"W";"Y";"P";"T";"S";"H";"N";"D";"Q";"E";"K";"R"}
SideChSet[5]={"I";"V";"L";"F";"C";"M";"A";"G";"T";"S";"W";"Y";"P";"H";"N";"D";"Q";"E";"K";"R"}
if (OrderStyle ==0 or absolutevalue(OrderStyle )>5) then OrderStyle =1 end
-- Check if OrderStyle has a valid value
SideChLetter=SideChSet[absolutevalue(OrderStyle )]
-- Select Sidechain order out of Sidechain sets
if OrderStyle <0 then SideChLetter=ReverseOrder(SideChLetter) end
-- if OrderStyle is negative, revert sidechain order
if Random==true then SideChLetter=RandomOrder(SideChLetter) end
-- if Random flag is true, scramble orde list
if GStart==true then select_all() replace_aa("G") end
-- if GStart is true, set all acids to Glycine before testing
ShakeIter=integervalue(ShakeIter)
reset_recent_best() -- store puzzle state before changes are done
local ScoreAtStart=get_score(true) -- get score at script start
if InsideOut==false then
for l=1,20 do -- cycle through all 20 acids
for k=SegA,SegB,StepSz do -- and try them on each segment
if GStart==false or SideChLetter[l]~="G" then change_all_segments(OrderStyle ,l,k,ShakeIter) end
end -- k
end -- l
else -- if InsideOut is true
for k=SegA,SegB,StepSz do -- cycle through all segments
for l=1,20 do -- and try all 20 acids
if GStart==false or SideChLetter[l]~="G" then change_all_segments(OrderStyle ,l,k,ShakeIter) end
end -- l
end -- k
end -- if InsideOut
if ShakeIter>0 then SpecialShake(ShakeIter) end
local ScoreAtEnd=get_score(true) -- get score at script end
print("Score at mutate start: ",ScoreAtStart)
print("Score at mutate end: ",ScoreAtEnd)
print("Score difference: ",ScoreAtEnd-ScoreAtStart)
end -- function
-- DESCRIPTION / HOW TO USE:
-- Variables:
is_mutable={}
-- Initialize flag table which shows with boolean values (true,false), which segments are mutable and which are not
SegA=1
-- The first segment you want to Quick-Mutate, integer value
-- Must be 1 or bigger
SegB=get_segment_count()
-- The last segment you want to Quick-Mutate, integer value
-- Must be bigger or equal than SegA and lower or equal Puzzle size
StepSz=1 -- the stepsize, so you can skip some segments if you want
SetMutableRange(SegA,SegB,true) -- Set all segments as mutable
-- SetMutableValues({},true) -- Example. Alternative method to set all segments as mutable.
-- SetMutableValues({},false) -- Example. Alternative method to set all segments as not mutable.
-- SetMutableRange(1,5,true) -- Example. Use this to set segments 1 to 5 as mutable.
-- SetMutableRange(1,5,false) -- Example. Use this to set segments 1 to 5 as not mutable.
-- SetMutableValues({10;12;15},true) -- Example. Use this to set segment 10,12,15 as mutable.
-- SetMutableValues({10;12;15},false) -- Example. Use this to set segment 10,12,15 as not mutable.
ListCheck=true -- If true, test segments
-- Set this to false if you are sure your segment lists are right and don't need to be tested.
GStart=false -- If true, all possible sidechains (SC) are set to Glycine before performing the whole task, so that you have a reference.
-- default is false
OrderStyle=1 -- Selects the order, of how the SC are tried. See following tab.
-- Co means color,Le length, HI hydorpathy index. Leftmost position means maximum priority.
-- 1=Le,Co,HI
-- 2=Co,Le,HI
-- 3=Le,HI,Co
-- 4=Co,HI,Le
-- 5=Co,Le
-- If you use negative values, the tried ss order is backwards.
-- So, valid styles are 1 to 5 and -1 to -5
-- Every other value uses style 1, which lets the Sidechains "grow out" of the backbone ;)
Random=false -- true=your chosen list will be used but scrambled dependent on the score as seeding value.
-- false=No scrambling
ShakeIter=0 -- =0 no shake
-- >0 A shake is performed at the very end with the batch,
-- within the selected number of iterations.
-- <0 A shake is performed after every change of sidechain.
InsideOut=false -- false=regular behaviour. Acid is chosen, tested through all segments, then next acid is tested.
-- true=alternate behaviour. Segment is chosen, all acids are tried, then next segment is tested.
-- END OF DESCRIPTION
MutableCheck() -- Before start, check is_mutable entries (if ListCheck is true) and show them
QuickMutate() -- Execute QuickMutate