Advertisement
Crashguard303

CG303 GAB V4.70+EO

Jun 5th, 2012
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 62.24 KB | None | 0 0
  1. --[[
  2. Genetic Bands III by Crashguard303
  3.  
  4. Inspired by cartoon Villain's Script, I created this one, including freezing.
  5. This script also works on not-very-best puzzle-states.
  6.  
  7. Random Creating:
  8.  It creates a set of clusters (herd). Each cluster has a random set of bands,freezes and a drift value.
  9.  There is a random list, which segments have already been banded or frozen, so it is guaranteed that all are tried.
  10.  If all have been tried, this list is shuffled, all segments are tried again.
  11.  The drift shows, in which directions banding or freezing segments can move.
  12.  (-1 will increase current segment number by, +1 will increase segment number by 1, 0 won't exist)
  13.  
  14. Then, for this puzzle state, all clusters are tried.
  15. This means:
  16.  
  17. Pulling:
  18.  Bands and freezes are applied (plus constant bands, if you want), the puzzle is wiggled for one iteration.
  19.  
  20. Releasing:
  21.  Bands and freezes are removed.
  22.  4 different subroutines similar to blue fuse run.
  23.  They test different clashing-importance shake/wiggle combinations.
  24. The best result of the fuse is stored to the cluster score.
  25.  
  26. Sorting:
  27.  If all clusters were tried, they are sorted by the scores they created, double score results are moved to the end of the list.
  28.  The best cluster is on top, the worst or and equal cluster is on bottom at the list.
  29.  
  30. Breeding:
  31.  All clusters from BreedFirst to BreedLast are breeded, first best  with other random clusters, preferring good ones
  32.  The cluster with the most bands is mom, cluster with fewer bands is dad.
  33.  Bands of mom and drift value are copied at first,
  34.  then a random crossover point is generated within the length of dad's bands.
  35.  Bands from 1 to inclusive crossover point from the new cluster are replaced by bands of dad, rest of mom
  36.  The same happens to freezes.
  37.  
  38. Mutating:
  39.  For each band or freeze:
  40.   A random flag (Drift flag or multiplicator) (either 0 or 1)  is created, depending on mutation probability.
  41.   If this flag is 1, drift value (-1 or +1) is added to the segment index, in other case, the segment index stays the same.
  42.   Band length and strength are randomly changed between an amount of -0.1 to 0.1
  43.   When mutating, all values are checked after they are changed, to guarantee that they don't leave a legal value range.
  44.  
  45. Inverting:
  46.  For each band or freeze:
  47.   A random flag (inversion flag) (either o or 1) is created, depending on inverting probability.
  48.   If this flag is 1, segment values are inverted, which means multiplying them by -1
  49.   Negative segment values results banding or freezing skip, they are deactivated.
  50.   If a segment has a negative value and is inverted, the value is positive and activated again
  51.  
  52. Filling:
  53.  The rest of the herd (BreedLast+1 to HerdSize) is replaced by new random clusters, as described in Random Creating.
  54.  
  55. Restart:
  56.   When new clusters have been breeded or replaced, the recent best puzzle state is loaded.
  57.   and pulling is performed again.
  58.  
  59. END OF MAIN DESCRIPTION
  60. P.S.: If you find typos, you can keep them ;)
  61. ]]--
  62.  
  63.  
  64. function math.frandom(m,n,e)
  65.  -- float random, e is number of remaining decimal digits
  66.  local e2=10^e
  67.  return math.random(m*e2,n*e2)/e2
  68. end -- function
  69.  
  70. function math.sgn(x)
  71.  -- Signum function
  72.  
  73.  if x==nil then
  74.    return nil
  75.   elseif x>0 then
  76.    return 1
  77.   elseif x<-0 then
  78.    return -1
  79.   else
  80.    return x
  81.  end -- if
  82. end -- function
  83.  
  84. function CutOff(x,y)
  85.  -- Keep only y digits after decimal point from x
  86.  return math.floor(x*10^y)/10^y
  87. end -- function
  88.  
  89. BoolString={}
  90. BoolString[true]="In"
  91. BoolString[false]="Ex"
  92.  
  93. function UseSegIRange(UseList,A,B,StepSize,bool)
  94.  -- In table "UseList", append or remove segment range A to B
  95.  local UseList=UseList
  96.  local A=A -- range start
  97.  local B=B -- range end
  98.  if A>B then A,B=B,A end -- Swap range start and end, if values are not okay
  99.  local StepSize=StepSize
  100.  local bool=bool -- True=append, false=remove
  101.  
  102.  local k=A
  103.  repeat
  104.   UseList=UseList_AR(UseList,k,bool)
  105.   k=k+StepSize -- increase k by StepSize
  106.  until k>B -- until k exceeds B
  107.  return UseList
  108. end -- function
  109.  
  110. function UseSegIValues(UseList,field,bool)
  111.  -- In table "UseList", append or remove segments listed in table "field"
  112.  local UseList=UseList
  113.  local field=field  -- table to add
  114.  local bool=bool -- True=append, false=remove
  115.  
  116.  local k
  117.  if #field>0 then -- If table to add is not empty
  118.    for k=1,#field do -- cycle through all elements from table
  119.     UseList=UseList_AR(UseList,field[k],bool)
  120.    end -- k loop
  121.  end -- if #field
  122.  return UseList
  123. end -- function
  124.  
  125. function Use_ss(UseList,SSLetter,bool)
  126.  -- In table "UseList", append or remove segments with secondary structure "SSLetter"
  127.  local UseList=UseList
  128.  local SSLetter=SSLetter
  129.  local bool=bool -- True=append, false=remove
  130.  
  131.  local k
  132.  for k=1,NumSegs do -- Cycle through all segment indices
  133.   if structure.GetSecondaryStructure(k)==SSLetter then -- If current segment index has same ss as given
  134.     UseList=UseList_AR(UseList,k,bool)
  135.   end -- if get_ss
  136.  end -- k loop
  137.  return UseList
  138. end -- function
  139.  
  140. function Use_aa(UseList,AALetters,bool)
  141.  -- In table "UseList", append or remove segments with amino-acid in table "AALetters"
  142.  local UseList=UseList
  143.  local AALetters=AALetters
  144.  local bool=bool -- add or  remove
  145.  
  146.  if #AALetters>0 then -- Is there minimum one aa letter given?
  147.  
  148.   local k
  149.   for k=1,NumSegs do -- Cycle through all segments
  150.    local aa=get_aa(k) -- get current aa of segment index k
  151.  
  152.    local exit_condition=false
  153.    local l=0
  154.    repeat
  155.     l=l+1 -- Cycle through all given aa letters
  156.     if aa==AALetters[l] then -- If current segment k's aa is equal to AALetters[l]
  157.      UseList=UseList_AR(UseList,k,bool)
  158.      exit_condition=true -- l loop can end here
  159.     end -- if aa
  160.     if l==#AALetters then exit_condition=true end
  161.    until exit_condition==true
  162.   end -- k loop
  163.  end -- if AALetters
  164.  return UseList
  165. end -- function
  166.  
  167. function Use_distance(UseList,MinDist,MaxDist,MinQuantity,MaxQuantity,bool)
  168.  -- In table "UseList", append or remove segments which have
  169.  -- MinQuantity to MaxQuantity neighbours within distance MinDist to MaxDist
  170.  local MinDist=MinDist
  171.  local MaxDist=MaxDist
  172.  local MinQuantity=MinQuantity
  173.  local MaxQuantity=MaxQuantity
  174.  local bool=bool -- True=append, false=remove
  175.  
  176.  for k=1, NumSegs do -- Cycle through all segments
  177.   local QCount=0
  178.   for l=1,NumSegs do -- compare index k with all around
  179.    if l~=k then -- Don't count segment itself, only neighbours
  180.     local Distance=structure.GetDistance(k,l) -- Measure distance from segment k to segment l
  181.     if Distance>=MinDist then -- If equal or above min distance
  182.      if Distance<=MaxDist then -- If equal or below max distance
  183.       QCount=QCount+1 -- count this segment
  184.      end -- if Distance
  185.     end -- if Distance
  186.    end -- if l
  187.   end -- l loop
  188.   if QCount<=MaxQuantity then -- If count is equal or below max quantity
  189.    if QCount>=MinQuantity then -- If count is equal or above min quantity
  190.     UseList=UseList_AR(UseList,k,bool) -- add or remove from list
  191.    end -- if QCount
  192.   end -- if QCount
  193.  end -- k loop
  194.  return UseList
  195. end -- function
  196.  
  197. function Use_close_ligand(UseList,MaxDist,bool)
  198.  -- In table "UseList", append or remove segments which have
  199.  -- a spatial distance of MaxDist or closer to ligand.
  200.  local UseList=UseList
  201.  local MaxDist=MaxDist
  202.  local bool=bool -- True=append, false=remove
  203.  local LigandIdx=NumSegs+1 -- Ligand Index
  204.  
  205.  local k
  206.  for k=1,NumSegs do -- Cycle with k through all segments but not ligand
  207.   local Distance=structure.GetDistance(k,LigandIdx) -- Check spatial distance of segment k to ligand
  208.   if Distance<=MaxDist then -- If equal or below MaxDist
  209.    UseList=UseList_AR(UseList,k,bool) -- add or remove from list
  210.   end -- if
  211.  end -- k loop
  212.  return UseList
  213. end -- function
  214.  
  215. function UseList_AR(UseList,value,bool)
  216.  -- Append value "value" to UseList
  217.  -- or remove all value's out of UseList, depending on bool
  218.  local UseList=UseList
  219.  local value=value
  220.  local bool=bool -- True=append, false=remove
  221.  -- print(BoolString[bool],"cluding segment index ",value)
  222.    if bool==true then
  223.       UseList=UseList_Append(UseList,value)
  224.     else
  225.       UseList=UseList_Remove(UseList,value)
  226.     end -- if bool
  227.  return UseList
  228. end -- function
  229.  
  230. function UseList_Append(UseList,value)
  231.  -- Adds content of "value" at end of UseList
  232.  local UseList=UseList
  233.  local value=value
  234.  UseList[#UseList+1]=value
  235.  return UseList
  236. end -- function
  237.  
  238. function UseList_Remove(UseList,value)
  239.  -- Creates new use list "UseList2" out of "UseList", but without all content of "value"
  240.  local UseList=UseList
  241.  local value=value
  242.  local UseList2={} -- Initialize new uselist
  243.  if #UseList>0 then -- if old
  244.   for k=1,#UseList do -- Scan UseList
  245.    if UseList[k]~=value then -- If "value" is not found
  246.     UseList2[#UseList2+1]=UseList[k] -- append this content to new use list
  247.    end -- if UseList
  248.   end -- k loop
  249.  end -- if UseList
  250.  return UseList2
  251. end -- function
  252.  
  253. function CompactContent(OS,E,AS)
  254.  --[[
  255.  Adds string AS to temporary output string OS and counts number of added AS in E.
  256.  If OS contents 10 elements, line is printed out
  257.  
  258.  I only had to write this sub because there Lua standard library is not included.
  259.  We neither can do some string manipulation nor use a print command without linebreaks at the moment :/
  260.  ]]--
  261.  
  262.  local OS=OS -- Temporary string for output
  263.  local AS=AS  -- String to add
  264.  local E=E -- Element counter, how often AS was added
  265.  
  266.  E=E+1
  267.  if AS<10 then -- Sorry for this, but there are no string operations possible at the moment
  268.    OS=OS.."00"..AS
  269.   elseif AS<100 then
  270.    OS=OS.."0"..AS
  271.   else
  272.    OS=OS..AS
  273.  end -- if AS
  274.  
  275.  if E<10 then -- If there are not 10 elements per line
  276.    OS=OS.."   " -- add space
  277.   else -- If there are 10 elements per line
  278.    print(OS) -- print line out
  279.    OS="" -- clear output string
  280.    E=0 -- reset element counter
  281.  end -- if E
  282.  return OS,E
  283. end -- function
  284.  
  285. function CheckUselist(UseList)
  286.  -- If there are fewer than 3 specific segments to work on given, take all
  287.  local UseList=UseList
  288.  if #UseList<=3 then
  289.   print("No or too few specific segments to work on given.")
  290.   print("Banding and freezing will now manipulate all puzzle segments.")
  291.   UseList={}
  292.   local k
  293.   for k=1,NumSegs do -- Cycle through all segments
  294.    UseList[#UseList+1]=k -- extend UseList by 1 and add segment index
  295.   end -- k loop
  296.  end -- if UseList
  297.  print("Segment list is now:")
  298.  local OS="" -- Initialize output string
  299.  local E=0 -- Initialize element counter
  300.  local k
  301.  for k=1,#UseList do
  302.    OS,E=CompactContent(OS,E,UseList[k])
  303.  end -- k
  304.  if E>0 then
  305.   print(OS)
  306.  end
  307.  return UseList
  308. end -- function
  309.  
  310. function shuffle2(ShuffleProb)
  311.  -- Scrambles segment use list depending on ShuffleProb
  312.  print("Shuffling segment list")
  313.  
  314.  local kend=#UseList-1
  315.  local k
  316.  for k=1,kend do -- Cycle through all UseList entries
  317.   if math.random()<ShuffleProb then -- If random value<probability
  318.   -- same as: if random_flag(ShuffleProb) then
  319.    local l=math.random(k+1,#UseList) -- pick random list entry behind k
  320.    UseList[k],UseList[l]=UseList[l],UseList[k] -- swap values of UseList index k with UseList index l
  321.   end -- if random
  322.  end -- k loop
  323.  UsedSegments=0 -- After Shuffling, set list pointer to 0
  324. end
  325.  
  326. function random_segment()
  327.  -- Gets a random segment index out of UseList which has not been used so far
  328.  
  329.  UsedSegments=UsedSegments+1 -- Increase UseList pointer
  330.  local Seg_result=UseList[UsedSegments] -- fetch segment index
  331.  if UsedSegments==#UseList then shuffle2(ShuffleProb) end
  332.  -- If this was the last value of UseList, shuffle list and reset pointer
  333.  
  334.  return Seg_result -- return random segment number
  335. end -- function
  336.  
  337. function FillHerd(StartAt,EndAt,TimeStamp)
  338.  local StartAt=StartAt -- First cluster index to generate (not cluster slot)
  339.  if StartAt<=HerdSize then
  340.   local EndAt=EndAt -- Last cluster index to generate (not cluster slot)
  341.   local TimeStamp=TimeStamp -- "birth date"
  342.   print("Generating Herd from ",StartAt," to ",EndAt)
  343.  
  344.   local k2
  345.   for k2=StartAt,EndAt do
  346.    -- print("Cluster: ",k2)
  347.    local k=ClusterPointer[k2] -- Fetch cluster slot by cluster index
  348.    ClusterScore[k]=0
  349.    ClusterDrift[k]=random_direction() -- Create value -1 or 1
  350.  
  351.    if (Mimic and k2==1) then -- If this is a Mimic band
  352.      ClusterType[k]="mimic" -- set cluster information for Mimic
  353.     else -- If this is not a Mimic band
  354.      ClusterType[k]="random" -- set cluster information for random
  355.    end -- if k2
  356.    ClusterType[k]=ClusterType[k].."-"..TimeStamp -- Show "birth date"
  357.  
  358.    if ClusterBands>0 then
  359.    ClusterSegA[k]={}
  360.    ClusterSegB[k]={}
  361.    ClusterLength[k]={}
  362.    ClusterStrength[k]={}
  363.  
  364.     local l
  365.     for l=1,ClusterBands do
  366.      if puzzle_is_ligand==false then -- If this is no ligand puzzle
  367.        ClusterSegA[k][l]=random_segment() -- get random segment number
  368.       else -- If this is a ligand puzzle
  369.        ClusterSegA[k][l]=NumSegs+1 -- Segment A is always ligand
  370.      end -- if puzzle_is_ligand
  371.  
  372.      if (Mimic==false or k2~=1) then -- If this is not a Mimic band
  373.       if random_flag(InvBProb) then -- and random flag for inverting is given
  374.        ClusterSegA[k][l]=-ClusterSegA[k][l] -- toggle cluster on/off by changing signum (+/-)
  375.       end -- if random_flag
  376.      end -- if k2
  377.  
  378.      repeat
  379.       ClusterSegB[k][l]=random_segment()
  380.       local IDistance=index_distance(ClusterSegA[k][l],ClusterSegB[k][l]) -- fetch index distance
  381.       local SDistance=structure.GetDistance(math.abs(ClusterSegA[k][l]),ClusterSegB[k][l]) -- fetch spatial distance
  382.      until IDistance>=MID_Game and SDistance<=MaxBL_Game
  383.      -- Segments must have a minimum index distance
  384.      -- and maximum spatial distance
  385.  
  386.      if (Mimic and k2==1) then -- If this is a Mimic band
  387.        ClusterLength[k][l]=FactorByLength(ClusterSegA[k][l],ClusterSegB[k][l])
  388.        ClusterStrength[k][l]=MaxBS
  389.       else -- if k2
  390.        ClusterLength[k][l]=math.frandom(0,1,6)
  391.        ClusterStrength[k][l]=math.frandom(MinBS,MaxBS,3)
  392.      end -- if k2
  393.  
  394.     end  -- l loop
  395.    end -- if ClusterBands
  396.  
  397.    if ClusterFreezes>0 then
  398.     ClusterFreeze[k]={}
  399.     local l
  400.     for l=1,ClusterFreezes do
  401.      ClusterFreeze[k][l]=random_segment()
  402.      if (Mimic and k2==1) or random_flag(InvFProb) then -- If this is a Mimic band or random flag for inverting freeze information is given
  403.       ClusterFreeze[k][l]=-ClusterFreeze[k][l] -- toggle freeze on/off by changing signum (+/-)
  404.      end -- if random_flag
  405.     end -- l loop
  406.    end -- if
  407.   end -- k loop
  408.  end -- if StartAt
  409. end -- function
  410.  
  411. function ShowHerd()
  412.  local k2
  413.  local l
  414.  
  415.  print("Clusters are:")
  416.  for k2=1,HerdSize do
  417.   local k=ClusterPointer[k2]
  418.   print("Cluster:",k2," score:",ClusterScore[k]," drift:",ClusterDrift[k])
  419.   if ClusterBands>0 then
  420.    local l
  421.    for l=1,ClusterBands do
  422.     print("Band ",l,": ",ClusterSegA[k][l]," to ",ClusterSegB[k][l])
  423.    end
  424.   end -- if ClusterBands
  425.  
  426.   if ClusterFreezes>0 then
  427.    local l
  428.    for l=1,ClusterFreezes do
  429.    print("Freeze ",l,": ",ClusterFreeze[k][l])
  430.    end -- l
  431.   end -- if
  432.  end -- k loop
  433. end -- function
  434.  
  435. function ShowHerdShort()
  436.  print("Clusters are:")
  437.  
  438.  local k2
  439.  for k2=1,HerdSize do
  440.   local k=ClusterPointer[k2]
  441.   print("Cluster:",k2,"(",k,") score:",ClusterScore[k])
  442.   print("Drift:",ClusterDrift[k])
  443.  end -- k loop
  444. end -- function
  445.  
  446. function ShowScoreList()
  447.  local k2
  448.  for k2=1,HerdSize do
  449.   local k=ClusterPointer[k2]
  450.   print("Cluster:",k2,"(",k,") delta:",ClusterScore[k])
  451.  end -- k
  452. end -- function
  453.  
  454. function SortHerd()
  455.  -- As we use pointers, we only have to swap the cluster "adresses" instead of copying all band/freeze values
  456.  local Finish=HerdSize-1
  457.  local k
  458.  for k=1,Finish do
  459.   local start=k+1
  460.   local l
  461.   for l=start,HerdSize do
  462.    if ClusterScore[ClusterPointer[l]]>ClusterScore[ClusterPointer[k]] then
  463.     -- print("Swapping cluster ",k,"(",ClusterPointer[k],"):",l,"(",ClusterPointer[l],")")
  464.     ClusterPointer[l],ClusterPointer[k]=ClusterPointer[k],ClusterPointer[l]
  465.    end -- if
  466.   end -- l
  467.  end -- k
  468. end -- function
  469.  
  470. function CreateCrossoverPoint(x)
  471.  -- create random crossover point
  472.  
  473.   if x==0 then
  474.     return 0
  475.    else -- if x ~=0
  476.     -- return math.random(0,x) -- create random value between 0 and x
  477.     return math.random(1,x-1) -- create random value between 1 and x-1
  478.   end -- if x
  479. end -- function
  480.  
  481. function Breed(TimeStamp)
  482.   -- Copy all clusters to another bank, same name for all cluster tables but with 2 at end
  483.   -- Breed two clusters from bank 2 back to old bank to prevent breeding collision.
  484.   -- If this wouldn't be done, and (for example) cluster 1 and 2 would be breeded to cluster 3,
  485.   -- cluster 3 couldn't be used as breeding source again, as it would be overwritten already.
  486.  
  487.   local TimeStamp=TimeStamp -- "birth date"
  488.  
  489.   ClusterScore2={}
  490.   -- ClusterType2={}
  491.   ClusterDrift2={}
  492.  
  493.   ClusterSegA2={}
  494.   ClusterSegB2={}
  495.   ClusterLength2={}
  496.   ClusterStrength2={}
  497.  
  498.   ClusterFreeze2={}
  499.  
  500.    local k
  501.    for k=1,HerdSize do
  502.     ClusterScore2[k]=ClusterScore[k]
  503.     ClusterDrift2[k]=ClusterDrift[k]
  504.  
  505.     if ClusterBands>0 then
  506.      ClusterSegA2[k]={}
  507.      ClusterSegB2[k]={}
  508.      ClusterLength2[k]={}
  509.      ClusterStrength2[k]={}
  510.      local l
  511.      for l=1,ClusterBands do
  512.        ClusterSegA2[k][l]=ClusterSegA[k][l]
  513.        ClusterSegB2[k][l]=ClusterSegB[k][l]
  514.        ClusterLength2[k][l]=ClusterLength[k][l]
  515.        ClusterStrength2[k][l]=ClusterStrength[k][l]
  516.      end -- l loop
  517.     end -- if ClusterBands
  518.  
  519.      if ClusterFreezes>0 then
  520.      ClusterFreeze2[k]={}
  521.      local l
  522.      for l=1,ClusterFreezes do
  523.        ClusterFreeze2[k][l]=ClusterFreeze[k][l]
  524.      end -- l loop
  525.     end -- if ClusterFreezes
  526.    end -- k loop
  527.  
  528.    FitnessOffset=ClusterScore[ClusterPointer[HerdSize]]
  529.    -- Take worst cluster score as fitness offset reference
  530.    -- By subtracting this score offset from each cluster score and adding 1,
  531.    -- it is guaranteed that worst cluster score is always 1, all other scores are better.
  532.    -- This will shift all cluster scores up, if worst cluster score is below 1, so there will be no values<1 for fitness calculation.
  533.    -- It will pull all scores down, if worst cluster score is above 1, to guarantee maximum privilege by fitness.
  534.    -- If all clusters would have similar big score values, they would be choosen equally.
  535.    -- By shifting the scores making the last score be 1, other scores are always x-times higher than 1.
  536.  
  537.    Fitness=0
  538.    local k
  539.    for k=1,HerdSize do
  540.     ClusterScore2[k]=ClusterScore2[k]-FitnessOffset+1 -- Shift cluster score copy by offset to met condition
  541.    -- We can overwrite this table, because it is only needed for breeding, and it won't affect the original table.
  542.    -- Original score will remain untouched.
  543.     Fitness=Fitness+ClusterScore2[k] -- Calculate fitness by adding all scores (offset included)
  544.  
  545.    end -- k loop
  546.  
  547.    local k
  548.    for k=BreedFirst,BreedLast do
  549.     ClusterBreed(k,TimeStamp)
  550.    end -- k loop
  551. end -- function
  552.  
  553. function Roulette()
  554.  -- Returns a random cluster index (not slot), the better their score, the more often they will appear
  555.  local TValue=math.random()*(Fitness+1) -- Target fitness value, which will stop the wheel
  556.  local CValue=0 -- Current value, where single cluster points will be added
  557.  local Wheel=math.random(1,HerdSize) -- Random initial wheel position
  558.  repeat
  559.   Wheel=Wheel+1 -- Spin Wheel
  560.   if Wheel>HerdSize then Wheel=1 end -- If Wheel made a full turn, it starts at 1 again
  561.   CValue=CValue+ClusterScore2[ClusterPointer[Wheel]]
  562.   -- Increase current value by score of cluster at wheel position
  563.  until CValue>TValue
  564.  return Wheel
  565. end -- function
  566.  
  567. function ClusterBreed(indexClusterB,TimeStamp)
  568.  local indexClusterB=indexClusterB -- Target cluster
  569.  local TimeStamp=TimeStamp -- "birth date"
  570.  
  571.  local indexClusterA1 -- Source cluster 1
  572.  if Parent1isRoulette==false then
  573.    indexClusterA1=indexClusterB-BreedFirst+1 -- Choose best, starting with 1
  574.   else
  575.    indexClusterA1=Roulette() -- Choose one by fitness roulette, the better the score, the more often it can be chosen
  576.  end -- if Parent1isRoulette
  577.  
  578.  local indexClusterA2 -- Source cluster 2
  579.  if Parent2isRoulette==true then
  580.    repeat
  581.     indexClusterA2=Roulette() -- Choose one by fitness roulette, the better the score, the more often it can be chosen
  582.    until indexClusterA2~=indexClusterA1 -- clusters must be different
  583.   else
  584.    indexClusterA2=indexClusterA1+1 -- Take next to Parent 1
  585.    if indexClusterA2>HerdSize then indexClusterA2=1 end
  586.  end -- if Parent2isRoulette
  587.  
  588.  local ClusterB=ClusterPointer[indexClusterB] -- Fetch save slot for target cluster
  589.  local ClusterA1=ClusterPointer[indexClusterA1] -- Fetch load slot for source cluster 1 (dad)
  590.  local ClusterA2=ClusterPointer[indexClusterA2] -- Fetch load slot for source cluster 2 (mom)
  591.  
  592.  local OS="Breeding "..indexClusterA1.."("..ClusterA1..") and "..indexClusterA2.."("..ClusterA2..") to "..indexClusterB.."("..ClusterB..")"
  593.  print(OS)
  594.  
  595.  ClusterType[ClusterB]="breeded".."-"..TimeStamp
  596.  
  597.  ClusterDrift[ClusterB]=ClusterDrift2[ClusterA1] -- Take drift information always from dad, preventing change in drift when breeding
  598.  
  599.   if ClusterBands>0 then -- We only need to copy if there are any bands
  600.    local CrossoverEnd
  601.    if MultiCrossOver== false then
  602.     CrossoverEnd=CreateCrossoverPoint(ClusterBands) -- Create
  603.     print("Band crossover point: ",CrossoverEnd) -- and show crossover point
  604.    end -- if MultiCrossOver
  605.  
  606.    ClusterSegA[ClusterB]={}
  607.    ClusterSegB[ClusterB]={}
  608.    ClusterLength[ClusterB]={}
  609.    ClusterStrength[ClusterB]={}
  610.  
  611.    local BandsChild
  612.    local l
  613.    for l=1,ClusterBands do -- Is crossover point reached?
  614.     if CrossOverCheck(CrossoverEnd,l) then
  615.       BandsChild=ClusterA2 -- Take mom after crossover point
  616.      else
  617.       BandsChild=ClusterA1 -- Take dad until crossover point
  618.     end -- if CrossoverEnd
  619.     ClusterSegA[ClusterB][l]=ClusterSegA2[BandsChild][l]
  620.     ClusterSegB[ClusterB][l]=ClusterSegB2[BandsChild][l]
  621.     ClusterLength[ClusterB][l]=ClusterLength2[BandsChild][l]
  622.     ClusterStrength[ClusterB][l]=ClusterStrength2[BandsChild][l]
  623.    end -- l loop
  624.   end -- if ClusterBands
  625.  
  626.   if ClusterFreezes>0 then -- We only need to copy if there are any freezes
  627.   local CrossoverEnd
  628.    if MultiCrossOver== false then
  629.     CrossoverEnd=CreateCrossoverPoint(ClusterFreezes) -- Create
  630.     print("Freeze crossover point: ",CrossoverEnd) -- and show crossover point
  631.    end -- if MultiCrossOver
  632.  
  633.    ClusterFreeze[ClusterB]={}
  634.  
  635.    local FreezesChild
  636.    local l
  637.    for l=1,ClusterFreezes do -- For all freezes
  638.     if CrossOverCheck(CrossoverEnd,l) then -- Is crossover point reached?
  639.       FreezesChild=ClusterA2 -- Take mom after crossover point
  640.      else
  641.       FreezesChild=ClusterA1 -- Take dad until crossover point
  642.     end -- if CrossoverEnd
  643.     ClusterFreeze[ClusterB][l]=ClusterFreeze2[FreezesChild][l]
  644.    end -- l loop
  645.   end -- if ClusterFreezes
  646.  
  647.   -- Cluster mutating starts here
  648.   -- Secondary cluster set not needed anymore
  649.   -- Mutation is directly performed on target cluster
  650.  
  651.   if ClusterBands>0 then
  652.   local l
  653.    for l=1,ClusterBands do
  654.     if puzzle_is_ligand==false then -- only on non-ligand-puzzles mutate segment A
  655.      if random_flag(DriftProb) then
  656.       ClusterSegA[ClusterB][l]=drift_segment(ClusterSegA[ClusterB][l],ClusterDrift[ClusterB])
  657.      end -- if random_flag
  658.     end -- if puzzle_is_ligand
  659.  
  660.     if random_flag(InvBProb) then
  661.      ClusterSegA[ClusterB][l]=-ClusterSegA[ClusterB][l] -- invert
  662.     end -- if random_flag
  663.  
  664.     repeat
  665.      if random_flag(DriftProb) then
  666.       ClusterSegB[ClusterB][l]=drift_segment(ClusterSegB[ClusterB][l],ClusterDrift[ClusterB])
  667.      end -- if random_flag
  668.      local Distance=index_distance(ClusterSegA[ClusterB][l],ClusterSegB[ClusterB][l])
  669.     until Distance>=MID_Game -- Segments must have a minimum index distance
  670.  
  671.     if random_flag(DriftProb) then -- mutation allowed
  672.      ClusterLength[ClusterB][l]=drift_band_attribute(ClusterLength[ClusterB][l],1,3,0,1,6)
  673.      -- change bandlength by value + or - randomly 10e-[1 to 3 randomly]
  674.      -- keep bandlength between 0 and 1
  675.      -- if error occurs, generate new bandstrength value with 6 decimal digits
  676.     end -- if random_flag
  677.  
  678.     if random_flag(DriftProb) then -- mutation allowed
  679.      ClusterStrength[ClusterB][l]=drift_band_attribute(ClusterStrength[ClusterB][l],1,3,MinBS,MaxBS,3)
  680.      -- change bandstrength by value + or - randomly 10e-[1 to 3 randomly]
  681.      -- keep bandstrength between MinBS and MaxBS
  682.      -- if error occurs, generate new bandlength value with 3 decimal digits
  683.     end -- if random_flag
  684.    end  -- l loop
  685.   end -- if ClusterBands
  686.  
  687.   if ClusterFreezes>0 then
  688.    local l
  689.    for l=1,ClusterFreezes do
  690.     if random_flag(DriftProb) then
  691.     ClusterFreeze[ClusterB][l]=drift_segment(ClusterFreeze[ClusterB][l],ClusterDrift[ClusterB])
  692.     end -- if random_flag
  693.  
  694.     if random_flag(InvFProb) then
  695.      ClusterFreeze[ClusterB][l]=-ClusterFreeze[ClusterB][l] -- invert
  696.     end -- if random_flag
  697.    end -- l loop
  698.   end -- if
  699. end -- function
  700.  
  701. function drift_segment(Segment,Drift)
  702.  local Drift=Drift
  703.  local Seg2=Segment
  704.  
  705.  local Seg2sgn=math.sgn(Seg2)
  706.  Seg2=math.abs(Seg2)+Drift
  707.  
  708.  if Seg2<1 then
  709.    Seg2=NumSegs
  710.   elseif Seg2>NumSegs then
  711.    Seg2=1
  712.  end -- if Seg2
  713.  
  714.  Seg2=Seg2*Seg2sgn
  715.  
  716.  return Seg2
  717. end -- function
  718.  
  719. function drift_band_attribute(Target,RndE1,RndE2,Min,Max,RndE3)
  720.  -- apply random drift on variable Target resulting Target2 (Target2=Target+random value)
  721.  -- drift value can be positive or negative
  722.  -- and is 10^-[RndE1 to RndE2 randomly]
  723.  -- for example if RndE1 is 1 and RndE2 is 3, resulting value can be 10^-1,10-2 or 10^-3
  724.  
  725.  -- If Min or Max is exceeded, value of Target2 is ring-wrapped (moebius transformation, no clamping):
  726.  -- If maximum is exceeded, the amount of exceedment (Target2-Value) is applied to minimum
  727.  -- If minimum is exceeded, the amount of exceedment (Target2-Value) is applied to maximum
  728.  
  729.  local Target2=Target
  730.  
  731.  local Target2=Target2+random_direction()*10^-math.random(RndE1,RndE2)
  732.  
  733.  if Target2>Max then
  734.    Target2=Min+(Target2-Max)
  735.   elseif Target2<Min then
  736.    Target2=Max+(Target2-Min)
  737.  end -- if Target2
  738.  
  739.  if Target2>Max or Target2<Min then
  740.   Target2=math.frandom(Min,Max,RndE3)
  741.  end -- if Target2
  742.  
  743.  return Target2
  744. end -- function
  745.  
  746. function CrossOverCheck(CrossoverEnd,Pos)
  747.  
  748.  if MultiCrossOver then
  749.    if random_flag(0.5) then
  750.      return true
  751.     else
  752.      return false
  753.    end -- if random_flag
  754.   else -- if MultiCrossOver is false
  755.    if Pos>CrossoverEnd then
  756.      return true
  757.     else
  758.      return false
  759.    end -- if Pos
  760.  end -- if
  761. end -- function
  762.  
  763. function random_flag(Prob)
  764.  -- Returns false or true randomly
  765.  -- how often true appears depends on probability Prob
  766.  local Prob=Prob
  767.  
  768.  if math.random()<Prob then
  769.    return true
  770.   else
  771.    return false
  772.  end -- if random
  773. end -- function
  774.  
  775. function random_direction()
  776.  -- returns either -1 or 1
  777.  return math.random(0,1)*2-1
  778. end -- function
  779.  
  780. function structure.WiggleBackbone(iter)
  781.  structure.WiggleAll(iter,true,false)
  782. end -- function
  783.  
  784. function structure.WiggleSidechains(iter)
  785.  structure.WiggleAll(iter,false,true)
  786. end -- function
  787.  
  788. function xtool(method,iter,tL2)
  789.   -- unifies score-conditional shake and wiggle into one function
  790.   local OS=""
  791.   local iter=iter
  792.   local tL2=tL2
  793.   if iter>0 then
  794.     OS="max iter:"..iter
  795.   end -- if
  796.   -- print("Method:",method," ",OS," threshold:",tL2)
  797.   local curr_iter=0
  798.   local exit_condition=false
  799.   repeat
  800.    curr_iter=curr_iter+1
  801.    -- print(" Testing with iterations: ",curr_iter)
  802.    local tempScore=current.GetEnergyScore()
  803.    if method=="s" then
  804.      structure.ShakeSidechainsAll(curr_iter)
  805.     elseif method=="wb" then
  806.      structure.WiggleBackbone(curr_iter)
  807.     elseif method=="ws" then
  808.      structure.WiggleSidechains(curr_iter)
  809.     else
  810.      structure.WiggleAll(curr_iter)
  811.    end -- if method
  812.    local tempScore2=current.GetEnergyScore()
  813.    local rDelta=(tempScore2-tempScore)/curr_iter
  814.    -- print(" Rel. change: ",rDelta," pts/iteration")
  815.    if curr_iter==iter then exit_condition=true end
  816.    if math.abs(rDelta)<tL2 then exit_condition=true end
  817.   until exit_condition==true
  818. end -- function
  819.  
  820. -- Inspired by vertex's blue fuse script
  821. -- You may want to tweak this function
  822.  
  823. function PinkFuse()
  824.     save.Quicksave(3) -- store state before fuse
  825.      print("Release 1")
  826.  
  827.      behavior.SetClashImportance(0.1)
  828.      xtool("s",Shakes,ScoreThreshold)
  829.      BestScoreCheck()
  830.      behavior.SetClashImportance(0.7)
  831.      xtool("wa",Wiggles,ScoreThreshold)
  832.      BestScoreCheck()
  833.     FuseEnd()
  834.  
  835.     save.Quickload(3) -- load state before fuse
  836.      print("Release 2")
  837.  
  838.      behavior.SetClashImportance(0.3)
  839.      xtool("s",Shakes,ScoreThreshold)
  840.      BestScoreCheck()
  841.      behavior.SetClashImportance(0.6)
  842.      xtool("wa",Wiggles,ScoreThreshold)
  843.      BestScoreCheck()
  844.     FuseEnd()
  845.  
  846.     save.Quickload(3) -- load state before fuse
  847.      print("Release 3")
  848.  
  849.      behavior.SetClashImportance(0.2)
  850.      xtool("s",Shakes,ScoreThreshold)
  851.      BestScoreCheck()
  852.      behavior.SetClashImportance(0.5)
  853.      xtool("wa",Wiggles,ScoreThreshold)
  854.      BestScoreCheck()
  855.     FuseEnd()
  856.  
  857.     save.Quickload(3) -- load state before fuse
  858.      print("Release 4")
  859.  
  860.      behavior.SetClashImportance(0.4)
  861.      xtool("s",Shakes,ScoreThreshold)
  862.      BestScoreCheck()
  863.      behavior.SetClashImportance(0.3)
  864.      xtool("wa",Wiggles,ScoreThreshold)
  865.      BestScoreCheck()
  866.     FuseEnd()
  867. end
  868.  
  869. function FuseEnd()
  870.     -- Fuse try finishing with CI=1
  871.     behavior.SetClashImportance(1)
  872.     xtool("wa",Wiggles,ScoreThreshold)
  873.     xtool("s",Shakes,ScoreThreshold)
  874.     xtool("wa",Wiggles,ScoreThreshold)
  875.     BestScoreCheck()
  876. end -- function
  877.  
  878. function BestScoreCheck()
  879.    local TempScore=current.GetEnergyScore()
  880.  
  881.    if LastBest then
  882.     if TempScore>ACS5 then
  883.      save.Quicksave(5) -- Set best cluster result for this generation
  884.      ACS5=TempScore
  885.      -- print("ACS5 is ",ACS5)
  886.     end -- if TempScore
  887.    end -- if LastBest
  888.  
  889.     if TempScore>ACS4 then
  890.      save.Quicksave(4) -- Set best cluster result for current cluster
  891.      ACS4=TempScore
  892.     end -- if TempScore
  893.  
  894.    if TempScore>BestScore then
  895.     -- recentbest.Save()
  896.     BestScore=TempScore
  897.     print("New best total score: ",BestScore)
  898.     BSChange=true
  899.    end -- if
  900. end -- function
  901.  
  902. function PullDownEqualResults()
  903.  print("Checking for double results")
  904.  -- Compare all cluster points with next in list
  905.  -- If next has the same score, move this cluster to end.
  906.  
  907.  local kEnd=HerdSize-1
  908.  local k
  909.  for k=1,kEnd do
  910.   while ClusterScore[ClusterPointer[k]]==ClusterScore[ClusterPointer[k+1]] do
  911.   -- If next has the same score
  912.    ClusterScore[ClusterPointer[k+1]]=ClusterScore[ClusterPointer[HerdSize]]-1
  913.    -- make its score more worse then the baddest cluster
  914.    SortHerd() -- so it is placed at the end when sorting by score
  915.   end -- while ClusterScore
  916.  end -- k
  917. end -- function
  918.  
  919. function InitializeClusterData()
  920.  ClusterScore={}
  921.  ClusterType={}
  922.  ClusterDrift={}
  923.  
  924.   ClusterSegA={}
  925.   ClusterSegB={}
  926.   ClusterLength={}
  927.   ClusterStrength={}
  928.  
  929.   ClusterFreeze={}
  930.  
  931.  ClusterPointer={}
  932.  local k
  933.  for k=1,HerdSize do
  934.   ClusterPointer[k]=k
  935.  end -- k
  936. end -- function
  937.  
  938. function PrintStartingTests()
  939.  print()
  940.  local OS=" "
  941.  if Runs==1 then
  942.    OS=OS.."1 run"
  943.   else
  944.    if Runs>1 then
  945.      OS=OS..Runs
  946.     else
  947.      OS=OS.."infinite"
  948.    end -- if
  949.    OS=OS.." runs"
  950.  end -- if
  951.  OS="Starting cluster tests for "..OS.."."
  952.  print(OS)
  953. end -- function
  954.  
  955. function select_close_ligand()
  956.  local LigandSegment=NumSegs+1
  957.  local k
  958.  for k=1,NumSegs do
  959.   if structure.GetDistance(k,LigandSegment)<=MutateLigandDistance then
  960.    selection.Select(k)
  961.    -- print(k," is close enough to ligand for mutating.")
  962.   end -- if get_segment_distance
  963.  end -- k loop
  964. end -- function
  965.  
  966. function SetRebuildWorst()
  967.  -- Acitvate rebuild worst if forced or condidtions are met
  968.  if RebuildForce==nil then
  969.    --[[
  970.    if BSChange then
  971.      RebuildWorst=false
  972.     else
  973.      RebuildWorst=true
  974.    end -- if BSChange
  975.    ]]--
  976.    RebuildWorst=BSValueCheck()
  977.   else
  978.    RebuildWorst=RebuildForce
  979.  end -- if RebuildForce
  980. end -- function
  981.  
  982. function BSValueCheck()
  983.  -- Returns true if current generation's best cluster didn't do much
  984.  local ChangeTooSmall=false
  985.  if BSValue>=0 then -- If last generation's best cluster score is better than at generation start
  986.    if BSValue<SCPT then -- but below limit
  987.     ChangeTooSmall=true
  988.    end -- if BSValue
  989.   else -- if BSValue<0  -- If last generation's best cluster score is not better than at generation start
  990.    if BSValue>SCNT then  -- but above limit
  991.     ChangeTooSmall=true
  992.    end -- if BSValue
  993.  end -- if BSValue
  994.  return ChangeTooSmall
  995. end -- function
  996.  
  997. function SetBreedFirstCurrent(BreedFirstCurrent)
  998.  -- Changes first cluster to test if forced or conditions are met
  999.  local BreedFirstCurrent=BreedFirstCurrent
  1000.  if BreedFirstCurrentForce==nil then -- If we don't force BreedFirstCurrent do a special value
  1001.    if (LastBest==false) and (RecentUse==false) then -- if we load initial state
  1002.      BreedFirstCurrent=BreedFirst
  1003.     else -- If we don't load initial state
  1004.      if BSChange or BSValueCheck()==false then -- If there was a considerable change
  1005.        BreedFirstCurrent=1 -- check all clusters again in next generation
  1006.       else -- If there was no considerable change
  1007.        BreedFirstCurrent=BreedFirstCurrent+1 -- increase start cluster for this generation (don't test best again)
  1008.        if BreedFirstCurrent>BreedFirst then BreedFirstCurrent=BreedFirst end -- but not further than BreedFirst
  1009.      end -- if BSChange
  1010.    end -- if LastBest==false and RecentUse=false then
  1011.   else -- if BreedFirstCurrentForce not nil
  1012.    BreedFirstCurrent=BreedFirstCurrentForce
  1013.  end -- if BreedFirstCurrentForce
  1014.  return BreedFirstCurrent
  1015. end -- function
  1016.  
  1017. function GAB()
  1018.  -- save.Quickload(1): Puzzle state at GAB Start
  1019.  -- save.Quickload(2): Puzzle state at generation start
  1020.  -- save.Quickload(3): Puzzle state at fuse start
  1021.  -- save.Quickload(4): Best result for current cluster
  1022.  -- save.Quickload(5): Best result for current generation
  1023.  
  1024.  print("Starting GAB-III.")
  1025.  print ("Minimum allowed bandlength: ",MinBL_Game)
  1026.  print ("Maximum allowed bandlength: ",MaxBL_Game)
  1027.  
  1028.  print ("Random seed is: ",RNDseed)
  1029.  math.randomseed(RNDseed) -- initialize random seed
  1030.  
  1031.  UseList=CheckUselist(UseList)
  1032.  shuffle2(ShuffleProb) -- Shuffle UseList and reset pointer
  1033.  
  1034.  InitializeClusterData()
  1035.  
  1036.  FillHerd(1,HerdSize,1) -- From 1 to HerdSize
  1037.  
  1038.  -- ShowHerd()
  1039.  
  1040.  band.DeleteAll() -- clean bands
  1041.  freeze.UnfreezeAll() -- and freezes
  1042.  behavior.SetClashImportance(1)
  1043.  selection.DeselectAll()
  1044.  recentbest.Save()
  1045.  
  1046.  save.Quicksave(1) -- Save initial puzzle state
  1047.  BestScore=current.GetEnergyScore() -- initialize best score (ACS1)
  1048.  
  1049.  PrintStartingTests(Runs)
  1050.  
  1051.  local BreedFirstCurrent=1
  1052.  CRun=0 -- set CRun to 0, counting up after each cluster generation
  1053.  repeat
  1054.   CRun=CRun+1 -- Increase current run value
  1055.   if CRun>1 then -- If this is not the first run
  1056.    if RecentHybrid>0 then -- If RecentHybrid>0, tweak RecentUse
  1057.      if (CRun-1)%RecentHybrid==0 then -- Each RecentHybrid runs
  1058.        RecentUse=true -- use recent best
  1059.       else -- If not
  1060.        RecentUse=false -- don't use recent best
  1061.      end -- if CRun
  1062.    end -- if RecentHybrid
  1063.    if LastBest then
  1064.      print("Loaded last generation's best.")
  1065.      save.Quickload(5) -- Load best cluster result of last generation
  1066.     else -- If Lastbest is false
  1067.      if RecentUse then
  1068.        print("Loaded recent best.")
  1069.        recentbest.Restore() -- Load best result so far
  1070.       else
  1071.        print("Loaded initial state.")
  1072.        save.Quickload(1) -- Load initial state
  1073.      end -- if RecentUse
  1074.    end -- if LastBest
  1075.    SetRebuildWorst()
  1076.    BreedFirstCurrent=SetBreedFirstCurrent(BreedFirstCurrent)
  1077.   end -- if CRun
  1078.  
  1079.   if RebuildWorstGen then -- If rebuild is requestet at geneartion start
  1080.    rebuild_worst() -- do it
  1081.   end
  1082.  
  1083.   BSChange=false -- Reset improvement information
  1084.  
  1085.   save.Quicksave(2) -- Set this state as start state for current generation
  1086.   ACS2=current.GetEnergyScore() -- Get score at start for this generation
  1087.   print()
  1088.   print("Score now: ",ACS2)
  1089.  
  1090.   local k2 -- Cluster counter (cluster number not in braces)
  1091.   for k2=BreedFirstCurrent,HerdSize do
  1092.    local k=ClusterPointer[k2] -- fetch slot number(adress) resulting from k2 (cluster number in braces)
  1093.    print()
  1094.    local OS="Gen.:"..CRun.." cluster:"..k2.."("..k..")/"..HerdSize.." drift:"..ClusterDrift[k].." type:"..ClusterType[k]
  1095.    print(OS)
  1096.  
  1097.    if k2>BreedFirstCurrent then
  1098.       -- print("Loaded Quicksave 1.")
  1099.       save.Quickload(2)
  1100.    end -- if k2
  1101.  
  1102.    band.DeleteAll() -- remove all bands, because recent best can contain some
  1103.    freeze.UnfreezeAll() -- and freezing to apply others
  1104.  
  1105.    if ClusterBands>0 then
  1106.     local l -- Band counter
  1107.     for l=1,ClusterBands do
  1108.      if ClusterSegA[k][l]>0 then
  1109.        band.AddBetweenSegments(ClusterSegA[k][l],ClusterSegB[k][l])
  1110.        local TempBandCount=band.GetCount()
  1111.        -- fetch current band number index to make setting its length and strength possible
  1112.  
  1113.        local Length=LengthWithFactor(ClusterSegA[k][l],ClusterSegB[k][l],ClusterLength[k][l])
  1114.        
  1115.        if (Mimic==false or l~=1) then -- If this is not a Mimic band
  1116.         if Length>structure.GetDistance(ClusterSegA[k][l],ClusterSegB[k][l]) then -- and random generated target length is bigger than actual distance
  1117.           Length=Length+BLchangeUpPush -- add push up value
  1118.           -- print("Pushed up.")
  1119.           if Length>MaxBL_Game then
  1120.            Length=MaxBL_Game
  1121.           end -- if Length>MaxBL_Game
  1122.          else -- if random generated target length is smaller or equal than actual distance
  1123.           Length=Length+BLchangeDownPush -- add push down value
  1124.           -- print("Pushed down.")
  1125.           if Length<MinBL_Game then
  1126.            Length=MinBL_Game
  1127.           end -- if Length<MinBL_Game
  1128.         end -- if Length>structure.GetDistance
  1129.        end -- if (Mimic==false or l~=1)
  1130.        
  1131.        local Length1R=CutOff(ClusterLength[k][l],3) -- Cut after 3 decimal digits before displaying
  1132.        local Length2R=CutOff(Length,3) -- Cut after 3 decimal digits before displaying
  1133.  
  1134.        local OS="Band "..l..": "..ClusterSegA[k][l]..":"..ClusterSegB[k][l]
  1135.        OS=OS.." L:"..Length1R.."="..Length2R
  1136.        if ShowBF then
  1137.         OS=OS.." S:"..ClusterStrength[k][l]
  1138.        end -- if
  1139.        print(OS)
  1140.  
  1141.        band.SetGoalLength(TempBandCount,Length) -- Set current band length
  1142.        band.SetStrength(TempBandCount,ClusterStrength[k][l]) -- Set current band strength
  1143.  
  1144.       else -- if ClusterSegA[k][l] is <0, which means band is deactivated
  1145.       if ShowBF then
  1146.        local OS="Band "..l..": off"
  1147.        print(OS)
  1148.       end -- if
  1149.      end -- if ClusterSegA
  1150.     end -- l loop
  1151.    end -- if ClusterBands
  1152.  
  1153.    if RebuildWorstGen==false then rebuild_worst() end
  1154.  
  1155.    selection.DeselectAll() -- Before freezing, so we can select segments to freeze
  1156.  
  1157.    if ClusterFreezes>0 then -- if there are segments to freeze
  1158.     local l -- Freeze counter
  1159.     for l=1,ClusterFreezes do  -- select all segments to freeze
  1160.      if ClusterFreeze[k][l]>0 then
  1161.        if ShowBF then
  1162.         local OS="Freeze "..l..": "..ClusterFreeze[k][l]
  1163.         print(OS)
  1164.        end -- if
  1165.        selection.Select(ClusterFreeze[k][l])
  1166.       else
  1167.       if ShowBF then
  1168.        local OS="Freeze "..l..": off"
  1169.        print(OS)
  1170.       end -- if
  1171.      end -- if ClusterFreez
  1172.     end -- l loop
  1173.    end -- if ClusterFreezes
  1174.  
  1175.    if puzzle_is_ligand then -- if this is a ligand puzzle
  1176.      selection.Select(NumSegs+1) --  select ligand for freezing
  1177.      freeze.FreezeSelected(true,true) -- freeze backbone and sidechains
  1178.     else -- if this is not a ligand puzzle
  1179.       if ClusterFreezes>0 then -- but there are segments to freeze
  1180.        freeze.FreezeSelected(true,false) -- freeze backbone only
  1181.       end -- if ClusterFreezes
  1182.    end -- if puzzle_is_ligand
  1183.  
  1184.    if ConstantBands==true then
  1185.     add_constant_bands() -- You can add some bands or freezes in this routine, which should appear each try
  1186.    end -- if
  1187.  
  1188.    print("Pulling...")
  1189.    behavior.SetClashImportance(CI_pull)
  1190.    selection.SelectAll () -- Select all segments to wiggle
  1191.    structure.WiggleAll(PWiggles) -- Just a small pull
  1192.  
  1193.    band.DeleteAll() -- clean up bands before saving
  1194.    freeze.UnfreezeAll() -- clean up freezes before saving
  1195.  
  1196.    if LastBest then -- If LastBest Mode
  1197.     if k2==BreedFirstCurrent then -- and this is the first try of current generation
  1198.      ACS5=current.GetEnergyScore()
  1199.      -- initialize current generation best score
  1200.     end -- if k2
  1201.    end -- if LastBest
  1202.  
  1203.    save.Quicksave(4) -- Initialize this state as reference for current cluster best score
  1204.    ACS4=current.GetEnergyScore() -- and initialize current cluster best score
  1205.    BestScoreCheck() -- raise BestScore ACS4, if result is better
  1206.  
  1207.    xMutate(Mutating1) -- including BestScoreCheck
  1208.  
  1209.    Release() -- including Fuse and BestScoreCheck
  1210.  
  1211.    xMutate(Mutating2) -- including BestScoreCheck
  1212.  
  1213.    ClusterScore[k]=ACS4-ACS2 -- Store best score minus start score for this try as cluster score
  1214.    print("Difference to start: ",ClusterScore[k])
  1215.   end -- k loop, take next cluster
  1216.  
  1217.   print()
  1218.   print("Sorting Cluster list by score")
  1219.   SortHerd() -- Sort herd by score difference
  1220.   ShowScoreList()
  1221.  
  1222.   BSValue=ClusterScore[ClusterPointer[1]] -- Fetch best score difference
  1223.  
  1224.   PullDownEqualResults() -- Move duplicate results to end of herd
  1225.  
  1226.   if ExtremalOptimization==false then -- if we do genetic and not extremal optimization
  1227.    Breed(CRun+1) -- Range: BreedFirst to BreedLast
  1228.   end -- if ExtremalOptimization
  1229.  
  1230.   if BSValueCheck() or BSValue<=0 then -- If generation's best cluster has low or negative score difference
  1231.    print("No or few improvement for this generation.")
  1232.    if HerdSize<IncHerdSize then -- and herd size increasing is allowed
  1233.     print("Increasing herd size.")
  1234.     local k
  1235.     for k=1,2 do -- Increase herd size by 2 individuums
  1236.      HerdSize=HerdSize+1 -- Increase herd size
  1237.      ClusterPointer[HerdSize]=HerdSize -- and number of cluster save slots; set them to its own value
  1238.     end -- k loop
  1239.     BreedLast=BreedLast+1 -- Increase breed slots by 1
  1240.    end -- if incHerdSize
  1241.   end -- if BSChange
  1242.  
  1243.   FillHerd(BreedLast+1,HerdSize,CRun+1)
  1244.   -- generate random clustes behind breeded ones
  1245.   -- ShowHerdShort()
  1246.  
  1247.  until CRun==Runs
  1248. end -- function GAB
  1249.  
  1250. function FactorByLength(SegA,SegB)
  1251.  -- As mimic doesn't use random band lengths (with random factor) but tries to imitate current puzzle state,
  1252.  -- we have not to generate but to calculate the factor value
  1253.  -- This is the opposite of function LengthWithFactor
  1254.  
  1255.  local Min=SpatLimit(SegA,SegB,BLchangeDown)
  1256.  local Max=SpatLimit(SegA,SegB,BLchangeUp)
  1257.  
  1258.  return (structure.GetDistance(SegA,SegB)-Min)/(Max-Min)
  1259. end -- function
  1260.  
  1261. function LengthWithFactor(SegA,SegB,Factor)
  1262.  -- Apply length factor to range between minimum allowed band length and maximum allowed band length
  1263.  -- Factor=0 results minimum allowed band length
  1264.  -- Factor=1 results maximum allowed band length
  1265.  
  1266.  local Min=SpatLimit(SegA,SegB,BLchangeDown)
  1267.  local Max=SpatLimit(SegA,SegB,BLchangeUp)
  1268.  
  1269.  -- local OS="Length range without push: "..CutOff(Min,3)..":"..CutOff(Max,3)
  1270.  -- print(OS)
  1271.  
  1272.  return Factor*(Max-Min)+Min
  1273. end -- function
  1274.  
  1275. function SpatLimit(SegA,SegB,Distance)
  1276.  
  1277.  local Distance2=structure.GetDistance(SegA,SegB)+Distance
  1278.  
  1279.  if Distance2<MinBL_Game then
  1280.    Distance2=MinBL_Game
  1281.   elseif Distance2>MaxBL_Game then
  1282.    Distance2=MaxBL_Game
  1283.  end -- if Distance2
  1284.  
  1285.  return Distance2
  1286. end -- funtction
  1287.  
  1288. function index_distance(SegA,SegB)
  1289.  -- Fetch segment index distance
  1290.  
  1291.  return math.abs(math.abs(SegA)-SegB)
  1292. end -- function
  1293.  
  1294. function Release()
  1295.   if Releasing then
  1296.     -- print("Score after pulling: ",ACS4)
  1297.     print("Releasing...")
  1298.     save.Quickload(4) -- load best cluster result so far
  1299.     selection.SelectAll ()
  1300.     if Fuse then
  1301.       PinkFuse() -- save.Quicksave(4), raise BestScore and ACS4, if result is better
  1302.      else
  1303.       behavior.SetClashImportance(1)
  1304.       structure.ShakeSidechainsAll(1)
  1305.       structure.WiggleAll(12)
  1306.       BestScoreCheck() -- save.Quicksave(4), raise BestScore and ACS4, if result is better
  1307.     end -- if fuse
  1308.    end -- if Releasing
  1309. end -- function
  1310.  
  1311. function rebuild_worst()
  1312.  if RebuildWorst then
  1313.   print("Rebuilding worst...")
  1314.   selection.DeselectAll()
  1315.  
  1316.   local WorstScore=current.GetSegmentEnergyScore(1)
  1317.   local WorstIndex=1
  1318.  
  1319.   local k
  1320.   for k=2,NumSegs do
  1321.    local SegmentScore=current.GetSegmentEnergyScore(k)
  1322.    if SegmentScore<WorstScore then
  1323.     WorstScore=SegmentScore
  1324.     WorstIndex=k
  1325.    end -- if SegmentScore
  1326.   end -- k
  1327.  
  1328.   if (WorstIndex-RebuildRange)<1 then
  1329.     WorstIndex=1+RebuildRange
  1330.    elseif (WorstIndex+RebuildRange)>NumSegs then
  1331.     WorstIndex=NumSegs-RebuildRange
  1332.   end -- if
  1333.  
  1334.   local SegA=WorstIndex-RebuildRange
  1335.   local SegB=WorstIndex+RebuildRange
  1336.  
  1337.   for k=SegA,SegB do
  1338.    selection.Select(k)
  1339.   end -- k loop
  1340.   structure.RebuildSelected(RebuildIter)
  1341.   selection.DeselectAll()
  1342.  end -- if RebuildWorst
  1343. end -- function
  1344.  
  1345. function xMutate(Mutating)
  1346.    if Mutating then
  1347.     save.Quickload(4) -- load best result for this cluster so far
  1348.     print("Mutating...")
  1349.     if puzzle_is_ligand then
  1350.       selection.DeselectAll() -- clear selection
  1351.       select_close_ligand() -- select all segments close as MutateLigandDistance or less to ligand
  1352.      else
  1353.       selection.SelectAll ()
  1354.     end -- if puzzle_is_ligand
  1355.     do_mutate(1)
  1356.     BestScoreCheck() -- Check if it made an improvement
  1357.    end -- if Mutating
  1358. end -- function
  1359.  
  1360. function detect_ligand(flag)
  1361.  --[[
  1362.  ligand puzzle detection
  1363.  normally, segments have a secondary structure of "E", "H" or "L"
  1364.  and they always have a spatial distance of about 3.75 to 3.85 to their next index neighbour.
  1365.  a ligand is more far away.
  1366.  
  1367.  this function should respond true if this is a ligand puzzle, and false if it is not.
  1368.  if flag is nil, ligand auto-detection is enabled, distance of last two segments is checked
  1369.  if flag is not nil, ligand auto-detection is disabled, result is flag
  1370.  
  1371.  It also returns the last segment index which is no ligand
  1372.  ]]--
  1373.  
  1374.  local flag=flag
  1375.  
  1376.  local LastPos=structure.GetCount() -- fetch very last segment index number
  1377.  
  1378.  if flag==nil then -- Only if flag is nil, detect if there is a ligand and change flag
  1379.    print("Detecting if there is a ligand.")
  1380.    local ss=structure.GetSecondaryStructure(LastPos)
  1381.    flag=not(ss=="L" or ss=="H" or ss=="E" )
  1382.    -- if last segment's ss is neither "l" nor "h" nor "e"
  1383.    flag=flag or (structure.GetDistance(LastPos-1,LastPos)>=3.9)
  1384.    -- or distance to second last segment is bigger or equal than 3.9
  1385.  end -- if
  1386.  
  1387.  local OS="This should be "
  1388.  if flag then
  1389.    OS=OS.."a"
  1390.    LastPos=LastPos-1
  1391.   else
  1392.    OS=OS.."no"
  1393.  end -- if flag
  1394.  OS=OS.." ligand puzzle."
  1395.  print(OS)
  1396.  
  1397.  return flag,LastPos
  1398. end -- function
  1399.  
  1400. function create_UseList(flag)
  1401.  -- Creates segment use list depending on which puzzle-type is there
  1402.  
  1403.  local flag=flag
  1404.  
  1405.  UseList={}
  1406.                       -- Initialize list of segments to use
  1407.                       -- UseList extensions (true) are applied to list, so multiple selected segments will appear more often
  1408.  if flag==false then -- If this is no ligand puzzle
  1409.    UseList=UseSegIRange(UseList,1,NumSegs,1,true)
  1410.                       -- Set every segment index from 1 to puzzle size as bandable
  1411.    UseList=Use_distance(UseList,0,8,10,1200,false)
  1412.                       -- Consider all segments which have min 10 to max 1200 neighbours
  1413.                       -- over a distance of 0 to 8 as non-solitary and remove them from list
  1414.    UseList=UseSegIRange(UseList,1,NumSegs,1,true)
  1415.                       -- Add a complete segment set again to make sure that distance check didn't erase all
  1416.    UseList=Use_ss(UseList,"L",true)
  1417.                       -- Add segments with this secondary structure
  1418.                         -- "L"=loop
  1419.                         -- "H"=helix
  1420.                         -- "E"=sheet
  1421.    -- UseList=UseSegIRange(UseList,1,NumSegs,2,false)
  1422.                       -- Set every 2nd segment index between 1 to puzzle size as not bandable, example
  1423.    -- UseList=UseSegIValues(UseList,{1;3;9},true)
  1424.                       -- Include these single segments as bandable, example
  1425.    -- UseList=UseSegIValues(UseList,{2;5;10},false)
  1426.                       -- Exclude these single segments as bandable, example
  1427.    -- UseList=Use_aa(UseList,{"g";"a"},true)
  1428.                       -- Set this amino acid as bandable, example
  1429.   else -- If this is a ligand puzzle
  1430.    UseList=Use_close_ligand(UseList,20,true)
  1431.                       -- Set segments which have a maximum spatial distance of 20 to ligand as bandable
  1432.  end -- if flag
  1433. end -- function
  1434.  
  1435. function LastBandLengthStrength(Length,Strength)
  1436.  -- sets length and strength of the very last band to default values
  1437.  local TempBandCount=band.GetCount()
  1438.  band.SetGoalLength(TempBandCount,Length)
  1439.  band.SetStrength(TempBandCount,Strength)
  1440. end -- function
  1441.  
  1442. function add_constant_bands()
  1443.  -- Add some constant bands to fix parts of the puzzle here
  1444.  -- and/or freeze some parts
  1445.  
  1446.  band.AddBetweenSegments(40,15)
  1447.  LastBandLengthStrength(5,0.1)
  1448.  
  1449.  --[[
  1450.  selection.DeselectAll()
  1451.  for k=10,11 do
  1452.   selection.Select(k)
  1453.  end -- k
  1454.  freeze.FreezeSelected(true,false)
  1455.  ]]--
  1456. end -- function
  1457.  
  1458.  Runs=0
  1459.                      -- Number of runs (generations), integer value
  1460.                        -- Set to <1 to run infinitely
  1461.  puzzle_is_ligand,NumSegs=detect_ligand()
  1462.                      -- puzzle_is_ligand: Ligand flag, boolean value
  1463.                        -- true for ligand puzzle
  1464.                        -- false for non-ligand-puzzle
  1465.                      -- NumSegs: Last segment index which is no ligand, integer value
  1466.                      -- detect_ligand(): Ligand auto detection.
  1467.                        -- If it fails, use detect_ligand(true) to declare that this is a ligand puzzle
  1468.                        -- and detect_ligand(false) to declare that this is a no ligand puzzle
  1469.  create_UseList(puzzle_is_ligand)
  1470.                       -- Initialize segment working list
  1471.                       -- Depending on puzzle type
  1472.                       -- Advanced Users: see function create_UseList for description of uselist creating features
  1473.  MID_Game=3
  1474.                        -- Minimum index distance of segment indices, integer value >=2
  1475.                        -- As the game doesn't allow banding the segments with themselves or the nearest neighbour,
  1476.                        -- This value is needed to prevent game errors,
  1477.                        -- but you can also use it to prevent sharp backbone turns.
  1478.  MinBL_Game=3.8
  1479.                        -- Minimum band length limiter, float value >=0 and <=MaxBL_Game
  1480.                        -- Opposite of MaxBL_Game
  1481.                        -- Prevents bands getting too short
  1482.  MaxBL_Game=10000
  1483.                        -- Maximum band length limiter, float value <=10000 and >=MinBL_Game
  1484.                        -- In rough, values about 20 or lower tend to compress the puzzle, values above 20 allow decompressing (stretching)
  1485.                        -- Maximum expedient value for a puzzle is about (number of segments-1)*3.8,
  1486.                         -- which would stretch the region between connected segments completely out.
  1487.  BLchangeDown=-3.8*2
  1488.                        -- Maximum band change down, float value <=0
  1489.                        -- Generated bands have a minimum length of [current segment distance]+BLchangeDown+BLchangeDownPush
  1490.  BLchangeDownPush=-3.8/2
  1491.                        -- Value added to BLchangeDown, float value <=0
  1492.                        -- This value is added to non-mimic bands if they are shorter or equal current segment distance to guarantee a certain change in length  
  1493.  BLchangeUp=3.8*1.5
  1494.                        -- Maximum band change up, float value >=0
  1495.                        -- Generated bands have a maximum length of [current segment distance]+BLchangeUp+BLchangeUpPush
  1496.  BLchangeUpPush=3.8/2
  1497.                        -- Value added to BLchangeUp, float value >=0
  1498.                        -- This value is added to non-mimic bands if they are longer than current segment distance to guarantee a certain change in length
  1499.  BreedFirst=3
  1500.                       -- First cluster to change by breeding, integer value
  1501.                       -- All clusters before this index will be kept as good solution and as potential parents for breeding new solutions
  1502.                         -- Setting this to 1 is not a good idea, because you will loose good clusters as breeding parents (some kind of incest), but should work, too
  1503.  BreedLast=5
  1504.                       -- Last cluster to change by breeding, integer value >=BreedFirst and <=HerdSize
  1505.                       -- All clusters after this index to HerdSize will be generated randomly
  1506.                       -- This value will be increased if no better solution was found
  1507.  HerdSize=8
  1508.                       -- Number of clusters, integer value >=BreedLast
  1509.                       -- This value will be increased if no better solution was found
  1510.  IncHerdSize=16
  1511.                       -- Increase herdsize, integer value
  1512.                         -- Allows increasing the herdsize if no better solution was found (will generate more clusters)
  1513.                         -- if >HerdSize, allow increasing herdsize until this amount
  1514.                         -- if <=HerdSize, no increasing
  1515.  ExtremalOptimization=false
  1516.                       -- ExtremalOptimization flag, boolean value
  1517.                         -- false (default) = script uses genetic algorithm with breeding
  1518.                         -- true = breeding is skipped, cluster are left as they are,
  1519.                           -- only those clusters with index behind BreedLast to BreedLast will be replaced by random ones
  1520.  ShowBF=true
  1521.                       -- Shows band and freeze details, boolean value
  1522.                         -- true (default) = segments which are banded or frozen are shown by text
  1523.                         -- false = no text for these actions
  1524.  ClusterBands=4
  1525.                       -- Maximum Bands to create per cluster, integer value >=0
  1526.  ClusterFreezes=3
  1527.                       -- Maximum segments to freeze by random, integer value >=0
  1528.  MinBS=0.8
  1529.                       -- Minimum strength per (random chosen) band, float value
  1530.                         -- Use decimal number between .1 and 10
  1531.  MaxBS=1.2
  1532.                       -- Minimum strength per (random chosen) band, float value
  1533.                         -- Use decimal number between .1 and 10 and >=MinBS
  1534.  Shakes=1
  1535.                       -- Number of iterations for fuse-shake, integer value
  1536.  Wiggles=4
  1537.                       -- Number of iterations for fuse-wiggle, integer value
  1538.  PWiggles=1
  1539.                       -- Number of iterations for pulling, integer value
  1540.  CI_pull=1
  1541.                       -- Clashing importance for pulling, float value >=0 and <=1
  1542.                         -- Default is 1
  1543.                         -- Reduce this to make pulling more drastic
  1544.  Releasing=true
  1545.                       -- Release flag, boolean value
  1546.                         -- true (default) = After pulling, releasing is performed.
  1547.                         -- false = releasing is skipped (and Fuse, too)
  1548.  Fuse=true
  1549.                       -- Fuse flag, boolean value
  1550.                         -- true (default) = After pulling, Fuse (requires Releasing=true) is performed.
  1551.                         -- false = after pulling, just a shake(1) and wiggle_all(12) with CI=1 is performed
  1552.  MutateLigandDistance=15
  1553.                       -- Radius length for selection sphere around ligand, where mutating is performed.
  1554.                         -- Selects only segments which are this or more close to the ligand for mutating.
  1555.  ScoreThreshold=0.5
  1556.                       -- Threshold value for shake and wiggles, float value >=0
  1557.                         -- This won't repeat some w/s, if absolute score change per itertation is below this
  1558.  MultiCrossOver=true
  1559.                       -- Multi crossover flag, boolean value
  1560.                         -- false (default) = One crossover point for each breeding is generated.
  1561.                         -- true = Each gene can be from mom or dad
  1562.  Parent1isRoulette=false
  1563.                       -- Roulette flag for breeding parent 1, boolean value
  1564.                         -- false (default) = parent is cluster with best score and downwards
  1565.                           -- use this to force good clusters for breeding
  1566.                         -- true = parent is chosen by fitness roulette
  1567.  Parent2isRoulette=true
  1568.                       -- Roulette flag for breeding parent 2, boolean value
  1569.                       -- true (default) = parent is chosen by fitness roulette
  1570.                       -- false = parent is next to parent 1
  1571.                         -- use this to force good clusters for breeding
  1572.  DriftProb=0.3
  1573.                       -- band drift (cluster mutation) probability, float value >=0 and <1
  1574.                         -- Probability, if drift is added or not
  1575.  InvBProb=0.2
  1576.                       -- Inverting (deactivating/reactivating) probability for bands, float value >=0 and <1
  1577.                         -- Makes inversion happen depending on this probability value
  1578.  InvFProb=0.3
  1579.                       -- Inverting (deactivating/reactivating) probability for freezes, float value >=0 and <1
  1580.                         -- Makes inversion happen depending on this probability value
  1581.  ShuffleProb=0.9
  1582.                       -- Shuffle rate, float value >=0 and <=1
  1583.                         -- Used to scramble random segment list, where bands are applied
  1584.                         -- 0 lets the list be as it is
  1585.                         -- 1 swaps all list entries with a random one behind them in list
  1586.  RecentUse=true
  1587.                         -- recent best flag, boolean value
  1588.                           -- true = recent best puzzle state is used for each generation
  1589.                           -- false = initial puzzle state is used for each generation
  1590.                             -- prevents getting stuck on local maximum (recommended for endgame)
  1591.                           -- If using RecentHybrid or LastBest, this value will be set automatically
  1592.  RecentHybrid=0
  1593.                         -- Hybrid behaviour between RecentUse=false/true, integer value >=0
  1594.                           -- ==0 = regular behaviour as set in RecentUse
  1595.                           -- >0 = use intial puzzle state but recent best state each RecentHybrid's generations
  1596.                            -- (counting from generation 2)
  1597.                           -- 1 would have the same effect as RecentUse=true
  1598.                           -- I recommend values>=2 when using it
  1599.  LastBest=false
  1600.                         -- Flag for using best cluster of current generation, boolean value
  1601.                         -- false (default) = use recent best or initial puzzle state (as set in RecentUse/RecentHybrid)
  1602.                         -- true = neither recent best nor initial puzzle state are loaded, but best result of current generation,
  1603.                         -- allowing unimproving the puzzle to get out of local maximum
  1604.                         -- Try this, you are really stuck on a puzzle.
  1605.  BreedFirstCurrentForce=nil
  1606.                        -- Loop start cluster force flag, integer value
  1607.                          -- nil (default) = best clusters will only be tested again
  1608.                            -- if there was an improvement in last generation
  1609.                          -- >0 = start at this cluster after first generation
  1610.                            -- 1 = test all clusters again (also good ones)
  1611.                            -- If BreedFirst, test only new generated clusters
  1612.  SCPT=1
  1613.                         -- Score change positive tolerance, float value >=0
  1614.                           -- Activates rebuild (if allowed)
  1615.                           -- if current generation start score and best cluster score difference
  1616.                           -- is below this positive value (not good enough)
  1617.  SCNT=-10
  1618.                         -- Score change negative tolerance, float value <=0
  1619.                           -- Activates rebuild (if allowed)
  1620.                           -- if current generation start score and best cluster score difference
  1621.                           -- is above this negative value (not bad enough)
  1622.  RebuildWorstGen=true
  1623.                         -- Rebuild worst at generation start flag, boolean value
  1624.                           -- true = rebuild worst is executed once for current generation
  1625.                           -- false = rebuild worst is executed for each cluster (not recommended)
  1626.                           -- nil = rebuild is never executed.
  1627.  RebuildWorst=false
  1628.                         -- Rebuild flag at script start, boolean value
  1629.                           -- true = rebuild is executed in first generation
  1630.  RebuildForce=nil
  1631.                         -- Force RebuildWorst, boolean value
  1632.                         -- Sets how RebuildWorst is changed.
  1633.                           -- nil (default) = worst segment is only rebuilt
  1634.                             -- if there was no improvement in last generation
  1635.                           -- true = worst segment is always rebuilt before pulling
  1636.                           -- false = worst segment is never rebuilt before pulling
  1637.  RebuildRange=2
  1638.                         -- Rebuild range, integer value>=1
  1639.                           -- For example, if 1 and worst segment is 3, segments from 2 to 4 are rebuilt.
  1640.                           -- if 2 and worst segment is 3, segments from 1 to 5 are rebuilt.
  1641.  RebuildIter=1
  1642.                       -- Iterations for rebuild worst, integer value>0
  1643.  Mutating1=puzzle_is_ligand
  1644.                       -- if true, puzzle segment mutating after pulling is performed
  1645.  Mutating2=false
  1646.                       -- if true, puzzle segment mutating after releasing is performed
  1647.  ConstantBands=false
  1648.                       -- Add constant bands flag, boolean value
  1649.                         -- if true, adds user-defined bands and freezes of add_constant_bands function above
  1650.                         -- before regular test-cluster is applied
  1651.  Mimic=false
  1652.                         -- Mimic flag, boolean value
  1653.                           -- if true, first cluster tries to imitate initial puzzle state
  1654.  RNDseed=os.time()+recipe.GetRandomSeed()
  1655.                       -- Random Seed
  1656.                         -- Here, the initial value is set to system time plus the game's random seed, so we get different random numbers
  1657.                         -- for each PC and each time the script is started.
  1658.                         -- If you want the same numbers (for testing purposes/results), take an arbitrary constant value.
  1659. GAB()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement