Crashguard303

CG303 GAB+EO Remix V7.923

May 21st, 2013
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 109.53 KB | None | 0 0
  1. --[[
  2. 0. general:
  3.    GAB+EO Remix V7.923 by Crashguard303
  4.    Copyright (C) 2013 Crashguard303 <http://fold.it/portal/user/119022>
  5.  
  6.    This program is free software: you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation, either version 3 of the License, or
  9.    (at your option) any later version.
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16.  
  17. 1. introduction:
  18.    1.1 inspired by:
  19.        Cartoon Villain (GA idea & first random band script of this kind)
  20.        Rav3n_pl        (OO parameter/variable handling)
  21.        jeff101         (EO & input-boxes idea)
  22.        Batz            (     input-boxes layout)
  23.  
  24.    1.2 idea:
  25.        -- further development of my last GAB+EO
  26.           i wrote this version from scratch to improve table handling & modularity
  27.           (coding did take 1 month,
  28.            testing, documenting & frontend did take another month!)
  29.  
  30.        -- this script doesn't simply band to random segs,
  31.            it will create:
  32.               a list of "cardinal" origin segs (see 3.3.2.3)
  33.               & connect them to target segs
  34.  
  35.           -- origin segs:
  36.              -- are detected and/or set by user via selection interface (blue) before.
  37.              -- don't change (they are just turned off or on)
  38.  
  39.           -- target segs:
  40.              -- do vary (see 3.3.2.2)
  41.              -- they can be
  42.                 -- each of uselist (see 3.3.2.2: all except "random 2")
  43.                 -- complete random (see 3.3.2.2:            "random 2")
  44.           -> this will avoid double banding
  45.  
  46.        -- new idea is to keep the number of random band parameters as small as they can be:
  47.           the script works with 2 fixed band strengths (as the length is already random)
  48.           -- primary bands:   do seg movement in space or relative to any other seg (depending on band mode)
  49.           -- secondary bands: do seg movement between proximate segs.
  50.                               they can be used to stabilize or move internal puzzle structure,
  51.                               so their job is supporting the primary bands with their major task
  52.  
  53.        -- as i didn't want to overload the starting sequence
  54.           with too many input boxes & selectable vals (more than 7 boxes at the moment!).
  55.           -> you can set all vals (even the other) in the declaration section.
  56.  
  57.    1.3 features:
  58.        -- cardinal seg auto-detection: (see 3.3.2.3)
  59.           -- secondary-structure changes, amino-acids, etc will create a uselist
  60.           -- locked (grey) segs will be detected
  61.              -- and won't be used as origin segs
  62.              -- but          used as target segs
  63.           ++ selected (blue) segs via game interface can be used as origin segs, too
  64.  
  65.        -- 3 breeding modes: (see 3.2)
  66.                             GA
  67.                             EO1
  68.                             EO2
  69.  
  70.        -- 2 gene     modes: (see 3.2.2.2)
  71.                             "dual"
  72.                             "poly"
  73.  
  74.        -- 6 banding  modes (see 3.3)
  75.                            "space"
  76.                            "center"
  77.                            "user"
  78.                            "furthest"
  79.                            "random1"
  80.                            "random2"
  81.  
  82.        ++ further settings for each
  83.  
  84.    1.4 known bugs/problems:
  85.        1.4.1 ligand puzzles:
  86.              -- are supported by script, but i couldn't test if it works properly!
  87.              -> to band ligand:
  88.                 use band to "user", then slide to last segment!
  89.  
  90.        1.4.2 locked (grey) puzzle segs:
  91.              -- will be detected & used as target segs only (see 1.3)
  92.              -- you have to select them, if they should be used as origin segs
  93.  
  94.    1.5 more:
  95.        1.5.1 Further support:
  96.              In future, I will have some examinations (and to learn other programming languages),
  97.              so I won't have the time do care much about:
  98.              -- script extensions,
  99.              -- feature requests &
  100.              -- spelling mistakes (or other lingual issues, as I'm not a native English speaker)
  101.              I hope, the manual is complete in this way that it answers most questions.
  102.              Maybe some other scripters can help you if there is a minor problem
  103.             (setting default values etc).
  104.  
  105.        1.5.2 "Frontend":
  106.              There are already many input-boxes for the most important values included in this script.
  107.              I neither wanted to write a full-automatic banding-robot (so I offered "a couple" of parameters)
  108.              nor to annoy anybody with tons of inputboxes.
  109.              But as long as we can't store files, we can change settings only:
  110.              -- via input dialog boxes or
  111.              -- by  writing them directly into script code.
  112.              
  113.              So it's up to you to choose, which parameters you change and in which way.
  114.              The strategy we choose is our human part in this game, the rest can ROSETTA do.
  115.              The script should be stable if you don't mess up vital things.
  116.              I tested it as good as I could with my limited internet-connection.
  117.  
  118.        1.5.3 (default) Parameter customizing and uploading:
  119.              If you find useful puzzle-adapted settings or script changes, you are free to post them
  120.              (and your version of the script, too).
  121.              Maybe you can recommend some settings (useful banding modes, thresholds... well, some puzzle-related things).
  122.              
  123.              Advice for coders/users with few experience:
  124.              -please- don't just unlock some "hidden" features
  125.              (e.g. by uncommenting some debugging functions or
  126.              just adding some "prints", making the script more verbose but nothing more)
  127.              and upload you personal customization as "reinvention of the wheel".
  128.              A car doesn't go faster if you put some racing-stickers on it ;)
  129.              For scripts, let's concentrate on functionality, the beauty will be found in good puzzle solutions.
  130.              If everybody would change the script's appearance, we won't be able to fish out functional code anymore.
  131.              
  132.              I want the script to be kept modular and relatively universal
  133.              + genetic, there are enough pure-random-band scripts already existing.
  134.              This means removing some of "vital" code is a bad idea, too
  135.              (apart from bug & performance fixes, of course).
  136.              So, if you do some changes and upload your script, please tell us what you did change  ;)
  137.              (by posting the complete function section you did change, from "function" to "end")
  138.              
  139.              If you want your own (personal) default values instead of using dialog-boxes,
  140.              use the declaration section to initialize them.
  141.              Most people who are able to fill out their annual tax declaration (especially those with business education),
  142.              should be able to modify some existing values in a complete script.
  143.              It's just putting "the right" numbers to "the right" position.
  144.              
  145.              As changing the "fuse" batches (order & number of CIs, wiggles, shakes & mutates) is a more complex thing,
  146.              I will help you with this... but please help other users, too ;)
  147.  
  148. 2. abbreviations/terms you might find:
  149.    2.1 structure:
  150.    gen: gen
  151.    clu: cluster
  152.    seg: segment
  153.    dst: distance
  154.    len: length
  155.    str: strength
  156.    itr: iterations
  157.  
  158.    2.2 addressing:
  159.    list: table
  160.    idx:  index     (numerical)
  161.    key:  key       (alphanumerical)
  162.    val:  value
  163.  
  164.    2.3 vals:
  165.    prm: parameter  (argument)
  166.    cur: current    (measured)
  167.    max: maximum
  168.    min: minimum
  169.    cng: change     (to add)
  170.    res: result     (calculated)
  171.    rnd: random     (generated)
  172.  
  173.    2.4 other:
  174.    gui: frontend (dialog input box)
  175.  
  176. 3. features:
  177.    3.1 terms & herd generating:
  178.        This script (as GAB before) applies & tests combinations of random bands.
  179.        one band combination set is named cluster (clu) here
  180.        (GA-term: individuum).
  181.        a testing row of different clus is a generation (gen)
  182.        (by default, 1 generation consists of 8 clus = herd.size)
  183.        when one gen has tested, it is evaluated.
  184.        each clu is measured by it's score gain,
  185.        gen will be sorted by clu's score gain, best on top.
  186.  
  187.    3.2 analyzing & breeding:
  188.        selection of of partners &
  189.        breeding them (mutating, too)
  190.        is the heart of a genetic algorithm !!!
  191.  
  192.        3.2.1 analyzing:
  193.              after  testing each gen,
  194.              clus are sorted by the score gain they made
  195.              -> first clu is this with best  gain,
  196.              -> last  clu is this with worst gain,
  197.  
  198.        3.2.2 breeding:
  199.              3.2.2.1 selection via EO:
  200.                      EO mode decides what happens with mediocre clus:
  201.  
  202.                      -- EO_mode.cur=0: mediocre clus are breeded             (only this is GA)
  203.                      -- EO_mode.cur=1: mediocre clus are considered as best  (soft         EO)
  204.                      -- EO_mode.cur=2: mediocre clus are considered as worst (hard/real    EO)
  205.  
  206.                      best clus (always):
  207.                      -- are kept (default: cluster 1 & 2 = 1...herd.breed.first)
  208.                         and "breeded" = mixed to new ones.
  209.  
  210.                      mediocre clus (EO_mode.cur=0):
  211.                      -- are overwritten by breeded ones
  212.                         (default: clu 3...5 = herd.breed.first to herd.breed.last)
  213.  
  214.                      worst clus (always):
  215.                      -- are replaced by new random ones
  216.                        (default: clu 6...8 = herd.breed.last...herd.size)
  217.  
  218.              3.2.2.2 sex (breed mode):
  219.                      -- imagine the clus as snails with both genders
  220.                      -- "poly": each single gene can be from any clu by roulette!
  221.  
  222.                      -- "dual": 1 kid has only 2 parents (classic):
  223.                         -> dad is 1st breeding partner
  224.                         -> mom is 2nd breeding partner
  225.  
  226.                         -- breeding partners can be chosen by:
  227.                            -> their rank: 1st has best score gain
  228.                            -> roulette:   1st appears most time, but all possible
  229.  
  230.                               -> if you breed 3 kids,
  231.                                  roulette combinations are:
  232.  
  233.                                  -- by default:
  234.                                     herd.breed.roulette.dad==false
  235.                                     herd.breed.roulette.mom==true
  236.  
  237.                                     -> kid#1: dad=clu#1 & mom#1=roulette
  238.                                     -> kid#2: dad=clu#2 & mom#2=roulette
  239.                                     -> kid#3: dad=clu#3 & mom#3=roulette
  240.  
  241.                                  -- other setting:
  242.                                     herd.breed.roulette.dad==false
  243.                                     herd.breed.roulette.mom==false
  244.  
  245.                                     -> kid#1: dad=clu#1 & mom#1=dad#1+1=clu#2
  246.                                     -> kid#2: dad=clu#2 & mom#2=dad#2+1=clu#3
  247.                                     -> kid#3: dad=clu#3 & mom#3=dad#3+1=clu#4
  248.  
  249.                                  -- other setting:
  250.                                     herd.breed.roulette.dad==true
  251.                                     herd.breed.roulette.mom==false
  252.  
  253.                                     -> kid#1: dad#1=roulette & mom#1=dad#1+1
  254.                                     -> kid#2: dad#2=roulette & mom#2=dad#2+1
  255.                                     -> kid#3: dad#3=roulette & mom#3=dad#3+1
  256.  
  257.                                  -- other setting:
  258.                                     herd.breed.roulette.dad==true
  259.                                     herd.breed.roulette.mom==true
  260.  
  261.                                     -> kid#1: dad#1=roulette & mom#1=roulette
  262.                                     -> kid#2: dad#2=roulette & mom#2=roulette
  263.                                     -> kid#3: dad#3=roulette & mom#3=roulette
  264.  
  265.    3.3 applying bands to segments:
  266.        3.3.1 types of connections:
  267.              The clus which are tested will be not only from seg to seg anymore (like in old GAB)
  268.              but also from seg to free space (if using clu.band_to.val="space"),
  269.              allowing more freedom of direction.
  270.  
  271.        3.3.2 origin segs & target segs:
  272.              3.3.2.1 origin segs:
  273.                      -- are always the same
  274.                         -- i did this to prevent double banding, simplifiy breeding
  275.                            & keeping the clu's gene-length homogenous
  276.                         -> you can't crossbreed a horse with a zebra because their DNAs have different lengths
  277.                         -> in real life, DNA also doesn't change length.
  278.                            genes remain, they are just active or inactive !
  279.  
  280.                      -- segs which can be banded & their banding order
  281.                         are stored in a uselist (selection)
  282.                      -> but you can turn some off & change their activity by mutation
  283.                      -> you can set them in the seg_use table declaration
  284.  
  285.              3.3.2.2 target segs:
  286.                       -- can be different, depending on mode clu.band_to.val:
  287.                       -- origin segs can be banded to
  288.  
  289.                       -> "space":    no   seg, but to "air"      (more freedom of movement,
  290.                                                                   but no reference to other segs anymore)
  291.                       -> "center":   calculated  seg             (real center  seg)
  292.                       -> "user":     selected    seg             (pseudo "center" seg internally)
  293.                       -> "furthest": calculated  seg             (furthest to origin seg)
  294.                       -> "random1":  another seg in seg_use list (given in table)
  295.                       -> "random2":      rnd seg in puzzle       (all  available)
  296.  
  297.              3.3.2.3 if no list is given (in declaration section):
  298.                      -- if you
  299.                         -- neither change the seg_use list to your needs
  300.                         -- nor     select any seg by game interface:
  301.                            -> by default, only these segs are banded,
  302.                               where changes in secondary structures do occur
  303.                             & which do have special residues (default: Glycine)
  304.                               -> key idea of this new script !!!
  305.  
  306.        3.3.3 band strength:
  307.              -- is constant for all bands now (unlike to old GAB),
  308.                 as the length is already set by random.
  309.              -> but you can set the global band strength
  310.                 for primary & secondary bands (not always used)
  311. --]]
  312.  
  313. function random_seed_set_val(random_seed)
  314.  local random_seed= random_seed
  315.  if (random_seed==nil) or (random_seed=="") then
  316.     random_seed=os.time()+recipe.GetRandomSeed()
  317.  else
  318.     random_seed= tonumber(random_seed)
  319.  end -- if random_seed
  320.  
  321.  print('Random Seed: '..random_seed)
  322.  math.randomseed(random_seed) -- initialize random seed
  323.  return random_seed
  324. end -- function randomseed
  325.  
  326. function above0(x)
  327.  if x>0 then
  328.     return 1
  329.  else -- if x<=0
  330.     return -1
  331.  end -- if x
  332. end -- function above0
  333.  
  334. function crop_digits(x,n)
  335.  local y=x
  336.  
  337.  y=y*10^n
  338.  y=math.floor(y)
  339.  y=y*10^(-n)
  340.  
  341.  return y
  342. end -- function crop_digits
  343.  
  344. function range_wrap(x,min,max,offset)
  345.  --[[
  346. prevent x getting higher than max
  347.                or lower  than min
  348. if x gets out of range, it is set to the other boundary+it's exceeding amount
  349.  
  350. if x>max, val will be >min, if offset is 0 & float   vals are used
  351.                    or =min, if offset is 1 & integer vals are used
  352. if x<min, val will be <max, if offset is 0 & float   vals are used
  353.                    or =min, if offset is 1 & integer vals are used
  354.  
  355. example:
  356. range_wrap(1.1,0,1,0) will return 0.1 (x is by .1 >1, so it is set next to 0+.1)
  357. range_wrap(-.1,0,1,0) will return 0.9 (x is by .1 <0, so it is set next to 1-.1)
  358.  
  359. range_wrap(11,0,10,0) will return 1 (x is by 1 >10, so it is set to  0+1)
  360. range_wrap(-1,0,10,0) will return 9 (x is by 1 <10, so it is set to 10-1)
  361.  
  362. range_wrap(11,0,10,1) will return 0  (x is by 1 >10, so it is set to  0+1-1)
  363. range_wrap(-1,0,10,1) will return 10 (x is by 1 < 0, so it is set to 10-1+1)
  364. --]]
  365.  
  366.   local y=x+0
  367.      if y>max then
  368.         y=min+(y-max)-offset
  369.  elseif y<min then
  370.         y=max+(y-min)+offset
  371.  end -- if y
  372.  return y
  373. end -- function range_wrap
  374.  
  375. function range_clamp(x,min,max)
  376.  --[[
  377. prevent x getting higher than max by setting it to max
  378.                or lower  than min by setting it to min
  379. --]]
  380.  
  381.   local y=x+0
  382.      if y>max then
  383.         y=max
  384.  elseif y<min then
  385.         y=min
  386.  end -- if y
  387.  return y
  388. end -- range_clamp()
  389.  
  390. function random_flag1(prob)
  391.  --[[
  392.  return true or false randomly, depending on prob(ability)
  393.  probability should be a float val between 0...1 as
  394.  vals <0 have the same effect as =0 &
  395.  vals >1 have the same effect as =1
  396.  
  397.  returns true, if
  398.  prob=0:   never
  399.  prob=0.1: sometimes
  400.  prob=0.5: quite as often as false
  401.  prob=0.9: most times
  402.  prob=1:   always
  403.  
  404.  calculation example:
  405.  -- if you want it to respond true
  406.  -- in 1 of 10 cases
  407.  -- use 1/10= 0.1
  408. --]]
  409.  
  410.  return (math.random()<prob)
  411. end -- function random_flag1
  412.  
  413. function random_flag2(prob,invert,bool)
  414. -- return val like random_flag1(), but
  415. -- invert=true inverts val
  416. -- bool=false  converts boolean vals
  417.    -- true ->  1
  418.    -- false -> 0
  419.  
  420.  local val=random_flag1(prob)
  421.  
  422.  if invert then
  423.     val= not(val)
  424.  end -- if invert
  425.  
  426.  if bool==false then
  427.     if val then
  428.        val= 1
  429.     else
  430.        val= 0
  431.     end -- if val
  432.  end -- if bool
  433.  
  434.  return val
  435. end -- function random_flag2
  436.  
  437. function list_show_deep(list,text)
  438. -- full key & val as string - advanced
  439. -- indexing: pairs
  440.  if text==nil then
  441.     text=tostring(list)
  442.  end -- if text
  443.  local k,v
  444.  for k,v in pairs(list) do
  445.      local ktext
  446.      if type(k)=="number" then
  447.         ktext= text..'['..tostring(k)..']'
  448.      else
  449.         ktext= text..'.'..tostring(k)
  450.      end -- if type(k)
  451.      if type(v)=="table" then
  452.         list_show_deep(v,ktext)
  453.      else
  454.         local vtext
  455.         if (type(v)=="number") or (type(v)=="boolean") then
  456.            vtext= tostring(v)
  457.         else
  458.            vtext= '\"'..tostring(v)..'\"'
  459.         end -- if type(v)
  460.         print(ktext..'='..vtext)
  461.      end -- if type(v)
  462.  end -- for k
  463. end -- function list_show_deep
  464.  
  465. function puzzle_ismutable()
  466.  local ismutable= false
  467.  
  468.  for i=1,puzzle.seg_count do
  469.      if structure.IsMutable(i) then
  470.         ismutable= true
  471.         break -- for i
  472.      end -- if structure.IsMutable
  473.  end -- for i
  474.  
  475.  return ismutable
  476. end -- function puzzle_ismutable
  477.  
  478. function puzzle_isligand()
  479.   local isligand
  480.   if structure.GetSecondaryStructure(puzzle.seg_count)==not(ss=="L" or ss=="H" or ss=="E" ) then
  481.      isligand= true
  482.   else
  483.      isligand= false
  484.   end -- if structure.GetSecondaryStructure
  485.   print('Ligand detected: '..tostring(isligand))
  486.   return isligand
  487. end -- function puzzle_isligand
  488.  
  489. function seg_blocks(blocks)
  490. -- create a list of mutlitple segment sections
  491. -- example:
  492.    --       blocks={{1;3};{7;10}}
  493.    -- results list={1;2;3;7;8;9;10}
  494.  local list={}
  495.  local i
  496.  for i=1,#blocks do
  497.      local j
  498.      for j=blocks[i][1],blocks[i][2] do
  499.          print('Appending Idx:'..(#list+1)..'=Seg:'..j)
  500.          table.insert(list,j)
  501.      end -- for j
  502.  end -- for i
  503.  return list
  504. end -- function seg_blocks
  505.  
  506. function seg_use_list_create(seg_use)
  507. -- table seg_use contains
  508.    -- associative keys - their vals are information for creating the:
  509.    -- numerical keys -   their vals are a list, which puzzle segment indices can be used
  510.  local seg_use=seg_use
  511.  
  512.  print('Appending segs with idx given in table...')
  513.  seg_use=seg_use_list_append(seg_use,seg_use.include.idx)
  514.  
  515.  if seg_use.include.selected.act then
  516.     print('Appending segs depending on selection: '..tostring(seg_use.include.selected.val)..'...')
  517.     seg_use=seg_use_list_append(seg_use,seg_list_selected_get(seg_use.include.selected.val))
  518.  end -- seg_use.include.selected.act
  519.  selection.DeselectAll()
  520.  
  521.  if seg_use.include.frozen.act then
  522.     print('Appending segs depending on freeze: backbone: '..tostring(seg_use.include.frozen.backbone)..' sidechain:'..tostring(seg_use.include.frozen.sidechain))
  523.     seg_use=seg_use_list_append(seg_use,seg_list_frozen_get(seg_use.include.frozen.backbone,seg_use.include.frozen.sidechain))
  524.  end -- seg_use.include.frozen.act
  525.  
  526.  if seg_use.include.ss_cngs then
  527.     print('Appending segs, where structure changes do occur...')
  528.     seg_use=seg_use_list_append(seg_use,ss_cngs_get_seg_list())
  529.  end -- if seg_use.include.ss_cngs
  530.  
  531.  print('Appending segs with ss given in table...')
  532.  seg_use=seg_use_list_append(seg_use,seg_list_ss_get(seg_use.include.ss))
  533.  
  534.  print('Appending segs with aa given in table...')
  535.  seg_use=seg_use_list_append(seg_use,seg_list_aa_get(seg_use.include.aa))
  536.  
  537.  seg_use=seg_use_filter(seg_use)
  538.  -- sort   seg list &
  539.  -- remove duplicate entries
  540.  
  541.  print('Removing segs which are locked...')
  542.  seg_use=seg_use_list_remove(seg_use,seg_list_locked_get())
  543.  
  544.  print('Removing segs with idx given in table...')
  545.  seg_use=seg_use_list_remove(seg_use,seg_use.exclude.idx)
  546.  
  547. if seg_use.exclude.selected.act then
  548.     print('Removing segs depending on selection: '..tostring(seg_use.exclude.selected.val)..'...')
  549.     seg_use=seg_use_list_remove(seg_use,seg_list_selected_get(seg_use.exclude.selected.val))
  550.  end -- seg_use.exclude.selected.act
  551.  
  552.  if seg_use.exclude.frozen.act then
  553.     print('Remove segs depending on freeze: backbone: '..tostring(seg_use.exclude.frozen.backbone)..' sidechain:'..tostring(seg_use.exclude.frozen.sidechain))
  554.     seg_use=seg_use_list_remove(seg_use,seg_list_frozen_get(seg_use.exclude.frozen.backbone,seg_use.exclude.frozen.sidechain))
  555.  end -- seg_use.exclude.frozen
  556.  
  557.  print('Removing segs with ss given in table...')
  558.  seg_use=seg_use_list_remove(seg_use,seg_list_ss_get(seg_use.exclude.ss))
  559.  
  560.  print('Removing segs with aa given in table...')
  561.  seg_use=seg_use_list_remove(seg_use,seg_list_aa_get(seg_use.exclude.aa))
  562.  
  563.  print('\nScript will use these segs:')
  564.  for i=1,#seg_use do
  565.   print(i..': '..seg_use[i])
  566.  end -- for i
  567.  
  568.  return seg_use
  569. end -- function seg_use_list_create
  570.  
  571. function seg_use_list_append(use_idx,append_idx)
  572.  local use_idx=use_idx
  573.  
  574.  if seg_use.append_all~=false then
  575.     seg_use.append_all=true
  576.  end -- if seg_use.append_all
  577.  -- if seg_use.append_all is not false
  578.  -- force it to be true
  579.  -- as no other vals are allowed
  580.  
  581.  if seg_use.append_all then
  582.     use_idx=seg_use_list_append_all(use_idx,append_idx)
  583.  else -- if seg_use.append_all~=true
  584.     use_idx=seg_use_list_append_missing(use_idx,append_idx)
  585.  end -- if seg_use.append_all
  586.  
  587.  return use_idx
  588. end -- function seg_use_list_append
  589.  
  590. function seg_use_list_append_all(use_idx,append_idx)
  591.  local use_idx=use_idx
  592.  local i
  593.  for i=1,#append_idx do
  594.      -- print('Appending Idx:'..(#use_idx+1)..'=Seg:'..append_idx[i])
  595.      table.insert(use_idx,append_idx[i])
  596.  end -- for i
  597.  return use_idx
  598. end -- function seg_use_list_append_all
  599.  
  600. function seg_use_list_append_missing(use_idx,append_idx)
  601.  local use_idx=use_idx
  602.  local i
  603.  for i=1,#append_idx do
  604.      if val_isintable(use_idx,append_idx[i])==false then
  605.         print('Appending Idx:'..(#use_idx+1)..'=Seg:'..append_idx[i])
  606.         table.insert(use_idx,append_idx[i])
  607.      end -- if val_isintable
  608.  end -- for i
  609.  return use_idx
  610. end -- function seg_use_list_append_missing
  611.  
  612. function val_isintable(list,valsearch)
  613. -- return:
  614.    -- true:  if list does    contain valsearch
  615.    -- false: if list doesn't contain valsearch
  616.  if #list==0 then
  617.    return false
  618.  else
  619.    return key_getbyval(list,valsearch)~=nil
  620.  end -- if #list
  621. end -- function val_isintable
  622.  
  623. function key_getbyval(list,valsearch)
  624. -- check all keys in table list
  625. -- return first found key which has valsearch
  626.  local keyres=nil
  627.  local key,val
  628.  
  629.  for key,val in pairs(list) do
  630.  -- with key loop, cycle through all keys
  631.  -- for each key, get its val
  632.     if val==valsearch then
  633.     -- if val found
  634.        keyres= key
  635.        -- return it's key
  636.        break -- key,val
  637.        -- break key loop
  638.     end -- if val
  639.  end -- key loop
  640.  
  641.  return keyres
  642. end -- function key_getbyval
  643.  
  644. function seg_use_list_remove(use_idx,remove_idx)
  645.  local use_idx=use_idx
  646.  
  647.  local i=1
  648.  for i=1,#remove_idx do
  649.      local j=1
  650.      while j<=#use_idx do
  651.            if use_idx[j]==remove_idx[i] then
  652.               print('Removing Idx:'..j..'=Seg:'..use_idx[j])
  653.               table.remove(use_idx,j)
  654.               j=j-1
  655.            end -- if use_idx
  656.            j=j+1
  657.      end -- while j
  658.  end -- for i
  659.  
  660.  return use_idx
  661. end -- function seg_use_list_remove
  662.  
  663. function seg_use_filter(seg_use)
  664. -- sort   list by seg idx numbers &
  665. -- remove duplicate entries
  666.  local seg_use=seg_use
  667.  
  668.  -- leave seg_use.sort_ascending as it is, as it is allowed to be nil
  669.  print('Sorting segs ascending: '..tostring(seg_use.sort_ascending))
  670.  
  671.  if seg_use.remove_double~=false then
  672.     seg_use.remove_double=true
  673.  end -- if seg_use.remove_double
  674.  -- if seg_use.remove_double is not false
  675.  -- force it to be true
  676.  -- as no other vals are allowed
  677.  print('Checking & removing double segs:'..tostring(seg_use.remove_double))
  678.  
  679.  local i=1
  680.  while i<=(#seg_use-1) do
  681.        local j=i+1
  682.        while j<=#seg_use do
  683.              if     seg_use[i]==seg_use[j] then
  684.              -- if two elements in list are equal
  685.                     if seg_use.remove_double then
  686.                        -- print('Removing idx:'..j..' = Seg:'..seg_use[j])
  687.                        table.remove(seg_use,j)
  688.                        j=j-1
  689.                        -- as element at position j was removed,
  690.                        -- another one might have moved up to position j
  691.                     end -- if seg_use.remove_double
  692.              elseif ((seg_use[i]>seg_use[j])==seg_use.sort_ascending) then
  693.              -- if they are not equal
  694.              --  & they don't have the order as given in seg_use.sort_ascending
  695.                     -- print('Swapping idx:'..i..'=Seg:'..seg_use[i]..' with idx:'..j..'=Seg:'..seg_use[j])
  696.                     seg_use[i],seg_use[j]=seg_use[j],seg_use[i]
  697.              end -- if seg_use
  698.              j=j+1
  699.        end -- for j
  700.        i=i+1
  701.  end -- while i<=(#seg_use-1)
  702.  
  703.  return seg_use
  704. end -- function seg_use_filter
  705.  
  706. function seg_list_locked_get()
  707.  local seg_found={}
  708.  local i
  709.  for i=1,puzzle.seg_count do
  710.      if structure.IsLocked(i) then
  711.         table.insert(seg_found,i)
  712.      end -- if structure.IsLocked
  713.  end -- for i
  714.  return seg_found
  715. end -- function seg_list_locked_get
  716.  
  717. function ss_cngs_get_seg_list()
  718.  -- check  all secondary strucutres of puzzle &
  719.  -- return a list, whre structure changes do occur
  720.  local seg_found={}
  721.  
  722.  local seg_count2= puzzle.seg_count-1
  723.  
  724.  local i=1
  725.  while i<seg_count2 do
  726.        local ss1=structure.GetSecondaryStructure(i)
  727.        local ss2=structure.GetSecondaryStructure(i+1)
  728.        -- check ss of seg with idx i & i+1
  729.        if ss1~=ss2 then
  730.        -- are ss different?
  731.        -- primary, we want to find segs with loop-ss at the end of helix or sheet sections
  732.        -- but sometimes helices are directly near sheets
  733.           if     ss1=="L" then
  734.                  -- loop found at i? (then other ss is behind i) then
  735.                  table.insert(seg_found,i)
  736.           elseif ss2=="L" then
  737.                  -- loop found near i? (then other ss is at i)
  738.                  table.insert(seg_found,(i+1))
  739.                  i=i+1
  740.           elseif ss1=="H" then
  741.                  -- helix found at i? (then other ss (but no loop) is behind i)
  742.                  table.insert(seg_found,i)
  743.           elseif ss2=="H" then
  744.                  -- helix found near i? (then other ss (but no loop) is at i)
  745.                  table.insert(seg_found,(i+1))
  746.                  i=i+1
  747.           end -- if ssx==ss
  748.        end -- if ss1~=ss2
  749.        i=i+1
  750.  end -- while i<seg_count2
  751.  
  752.  return seg_found
  753. end -- function ss_cngs_get_seg_list
  754.  
  755. function seg_list_selected_get(selected_flag)
  756.  local seg_found={}
  757.  local i
  758.  for i=1,puzzle.seg_count do
  759.      if selection.IsSelected(i)==selected_flag then
  760.         table.insert(seg_found,i)
  761.      end -- if selection.IsSelected
  762.  end -- for i
  763.  return seg_found
  764. end -- seg_list_selected_get
  765.  
  766. function seg_list_frozen_get(backbone_flag,sidechain_flag)
  767.  local seg_found={}
  768.  local i
  769.  for i=1,puzzle.seg_count do
  770.      local backbone,sidechain=freeze.IsFrozen(i)
  771.      if (backbone==backbone_flag) and (sidechain==sidechain_flag) then
  772.         table.insert(seg_found,i)
  773.      end -- if backbone,sidechain
  774.  end -- for i
  775.  return seg_found
  776. end -- function seg_list_frozen_get
  777.  
  778. function ss_cngs_show(structure_cngs_get,freeze_flag1,freeze_flag2)
  779.  selection.DeselectAll()
  780.  freeze.UnfreezeAll()
  781.  
  782.  print("Found changes:")
  783.  local i
  784.  for i=1,#seg_use do
  785.      -- by variable i, cycle through all segs in list which have been found
  786.      print(i..': '..seg_use[i])
  787.      -- show seg number
  788.      selection.Select(seg_use[i])
  789.      -- select seg number
  790.  end -- for i
  791.  
  792.  freeze.FreezeSelected(freeze_flag1,freeze_flag2)
  793.  -- if flags are set, freeze selected segs, backbone and/or sidechains
  794.  selection.DeselectAll()
  795. end -- function ss_cngs_show
  796.  
  797. function seg_list_ss_get(use_ss)
  798.  local seg_found={}
  799.  
  800.  local i
  801.  for i=1,#use_ss do
  802.      local j
  803.      for j=1,puzzle.seg_count do
  804.          if structure.GetSecondaryStructure(j)==use_ss[i] then
  805.             -- print(j..': '..structure.GetSecondaryStructure(j))
  806.             table.insert(seg_found,j)
  807.          end -- if structure.GetSecondaryStructure
  808.      end -- for j
  809.  end -- for i
  810.  return seg_found
  811. end -- function seg_list_ss_get
  812.  
  813. function seg_list_aa_get(use_aa)
  814.  local seg_found={}
  815.  
  816.  local i
  817.  for i=1,#use_aa do
  818.      local j
  819.      for j=1,puzzle.seg_count do
  820.          if structure.GetAminoAcid(j)==use_aa[i] then
  821.             -- print(j..': '..structure.GetAminoAcid(j))
  822.             table.insert(seg_found,j)
  823.          end -- if structure.GetAminoAcid
  824.      end -- for j
  825.  end -- for i
  826.  return seg_found
  827. end -- function seg_list_aa_get
  828.  
  829. function seg_center_get()
  830.  if (puzzle.seg_center.get_mode=="start") and (puzzle.seg_center.val~=nil) then
  831.  -- start center seg is to get & center seg is set
  832.        print('Stored center seg: '..puzzle.seg_center.val)
  833.        return puzzle.seg_center.val
  834.        -- use stored center seg
  835.  else
  836.  -- start center seg is not to get or center seg is not set
  837.  -- current center seg is to get
  838.     puzzle.seg_center.val= seg_center_get2()
  839.     -- get current center seg
  840.     return puzzle.seg_center.val
  841.  end -- if puzzle.seg_center.get_mode,puzzle.seg_center.val
  842. end -- function seg_center_get
  843.  
  844. function seg_center_get2()
  845. --[[
  846. find center seg of puzzle:
  847. -- for each seg:
  848.    -- measure it's dst to all other segs &
  849.    -- sum these dsts up
  850. -> center seg has lowest sum of dsts
  851. --]]
  852.  
  853.  -- print ('Getting center segment.')
  854.  local dist_sum={min=math.huge;min_issegidx=0}
  855.  
  856.  local i
  857.  for i=1,puzzle.seg_count do
  858.      dist_sum.cur=0
  859.      local j
  860.      for j=1,puzzle.seg_count do
  861.          dist_sum.cur=dist_sum.cur+structure.GetDistance(i,j)
  862.      end -- for j
  863.      -- print('Distance sum for #'..i..' = '..dist_sum.cur)
  864.      if dist_sum.cur<dist_sum.min then
  865.         dist_sum.min=dist_sum.cur
  866.         dist_sum.min_issegidx=i
  867.         -- print('Distance sum min hit!')
  868.         -- print('Distance sum min: #'..dist_sum.min_issegidx..' = '..dist_sum.min)
  869.      end -- if dist_sum.cur
  870.  end -- for i
  871.  -- print('Distance sum min: #'..dist_sum.min_issegidx..' = '..dist_sum.min)
  872.  -- similar to:
  873.  print('Current center seg: '..dist_sum.min_issegidx)
  874.  return dist_sum.min_issegidx
  875. end -- function seg_center_get2
  876.  
  877. function seg_furthest_get(seg_target)
  878.  -- print ('Getting furthest segment to seg#'..seg_target)
  879.  local dist={max=0;max_issegidx=0}
  880.  local i
  881.  for i=1,puzzle.seg_count do
  882.      dist.cur= structure.GetDistance(seg_target,i)
  883.      if dist.cur>dist.max then
  884.         dist.max= dist.cur
  885.         dist.max_issegidx=i
  886.         -- print('Distance max hit!')
  887.         -- print('Distance max: #'..dist.max_issegidx..' = '..dist.max)
  888.      end -- if dist.cur
  889.  end -- i
  890.  -- print('Distance max: #'..dist.max_issegidx..' = '..dist.max)
  891.  
  892.  return dist.max_issegidx
  893. end -- seg_furthest_get
  894.  
  895. function herd_generate(clu,first,last)
  896.  print('Generating herd from '..first..' to '..last..'...')
  897.  local i
  898.  for i=first,last do
  899.      -- print('Generating clu: '..i)
  900.      clu[i]={}
  901.      local j
  902.      for j=1,#seg_use do
  903.      -- with j, cycle through all segment indices given in seg uselist
  904.      -- print('--seg:'..j..'use:'..seg_use[j])
  905.          clu[i][j]=band_generate(j)
  906.          -- create clu band
  907.      end -- for i
  908.      clu[i].name=clu_name_get(i,"r")
  909.  end -- for i
  910.  return clu
  911. end -- function herd_generate
  912.  
  913. function band_generate(seg_cur)
  914.  local band={act=random_flag2(herd.mutate.prob.off,true,true)}
  915.              -- depending on random flag (influenced by herd.mutate.prob.off),
  916.              -- turn off band when indicated
  917.  
  918.  if clu.band_to.val=="space" then
  919.     -- following vals are pure random float numbers between 0...<1
  920.         band.rho=    math.random()
  921.         band.theta=  math.random()
  922.      -- band.theta=  .5;
  923.         band.phi=    math.random()
  924.  
  925.  else
  926.         band.d_cng1= math.random()
  927.         if clu.band_to.val=="random" then
  928.         -- random segs?
  929.            if puzzle.seg_random.get_mode=="list" then
  930.            -- random seg in list ?
  931.               repeat
  932.                     band.seg_target= seg_use[math.random(1,#seg_use)]
  933.               until band.seg_target~=seg_use[seg_cur]
  934.               -- prevent banding seg to itself
  935.               -- print('Random seg target of list: '..band.seg_target..' (not '..seg_use[seg_cur]..')')
  936.            else -- puzzle.seg_random.get_mode=="all"
  937.            -- random seg in puzzle ?
  938.               repeat
  939.                     band.seg_target= math.random(1,puzzle.seg_count)
  940.               until band.seg_target~=seg_use[seg_cur]
  941.               -- prevent banding seg to itself
  942.               -- print('Random seg target of all: '..band.seg_target..' (not '..seg_use[seg_cur]..')')
  943.            end -- if puzzle.seg_random.get_mode
  944.         end -- if clu.band_to.val
  945.  end -- if clu.band_to.val
  946.  
  947.  if clu.d_cng2.act then
  948.  -- secondary bands are used
  949.     band.d_cng2= math.random()
  950.  end -- if clu.d_cng2.act
  951.  
  952.  return band
  953. end -- function band_generate
  954.  
  955. function herd_mutate(clu,first,last)
  956.  local clu= clu
  957.  print('Mutating herd from '..first..' to '..last..'...')
  958.  local i
  959.  for i=first,last do
  960.      if herd.mutate.genes_show.act then
  961.         print('Mutating clu#'..i)
  962.      end -- if if herd.mutate.genes_show.act
  963.      local j
  964.      for j=1,#clu[i] do
  965.      if herd.mutate.genes_show.act then
  966.         print('Mutating band#'..j)
  967.      end -- if herd.mutate.genes_show.act
  968.      clu[i][j]=band_mutate(clu[i][j])
  969.      end -- for j
  970.  end -- for i
  971.  return clu
  972. end -- function herd_mutate
  973.  
  974. function band_mutate(clu_band)
  975.  local band={act=mutate_bool_val(clu_band.act)}
  976.  
  977.  if clu.band_to.val=="space" then
  978.         band.rho=    mutate_float_val(clu_band.rho)
  979.         band.theta=  mutate_float_val(clu_band.theta)
  980.         band.phi=    mutate_float_val(clu_band.phi)
  981.  
  982.  else
  983.         band.d_cng1= mutate_float_val(clu_band.d_cng1)
  984.         if clu.band_to.val=="random" then
  985.            band.seg_target= mutate_int_seg(clu_band.seg_target)
  986.         end -- if clu.band_to.val
  987.  end -- if clu.band_to.val
  988.  
  989.  if clu.d_cng2.act then
  990.  -- secondary bands are used
  991.     band.d_cng2= mutate_float_val(clu_band.d_cng2)
  992.  end -- if clu.d_cng2.act
  993.  
  994.  return band
  995. end -- function band_mutate
  996.  
  997. function mutate_bool_val(val)
  998. -- depending on herd.mutate.prob.vals
  999. -- possibly toggle band activity:
  1000.    -- band on  -> band off
  1001.    -- band off -> band on
  1002.  
  1003.   local val= val or false
  1004.   -- break reference
  1005.   if random_flag1(herd.mutate.prob.vals) then
  1006.   -- has random hit possibility?
  1007.      mutate_val_show('Old',val)
  1008.      val= not(val)
  1009.      -- invert boolean
  1010.      mutate_val_show('New',val)
  1011.      return val
  1012.   else
  1013.      return val
  1014.   end -- if random_flag1
  1015. end -- function mutate_bool_val
  1016.  
  1017. function mutate_float_val(val)
  1018. -- depending on herd.mutate.prob.vals
  1019. -- possibly change normalized val 0...1
  1020. -- by a random amount between +/-10^(min...max)
  1021.  
  1022.   local val= val+0
  1023.   -- break reference
  1024.   if random_flag1(herd.mutate.prob.vals) then
  1025.   -- has random hit possibility?
  1026.     mutate_val_show('Old',val)
  1027.     val= val+(math.random(0,1)*2-1)*(10^(math.random(herd.mutate.rng10e.min,herd.mutate.rng10e.max)))
  1028.     val= range_wrap(val,0,1,0)
  1029.     mutate_val_show('New',val)
  1030.     return val
  1031.   else
  1032.     return val
  1033.   end -- if random_flag1
  1034. end -- function mutate_float_val
  1035.  
  1036. function mutate_int_seg(val)
  1037. -- depending on herd.mutate.prob.vals
  1038. -- possibly change segment idx
  1039. -- by a random amount between +/-1
  1040.  
  1041.   local val= val+0
  1042.   -- break reference
  1043.   if random_flag1(herd.mutate.prob.vals) then
  1044.   -- has random hit possibility?
  1045.      mutate_val_show('Old',val)
  1046.      val= val+(random_flag2(0.6,false,false)*2-1)
  1047.      -- 0.6 (0.5 would be 50:50) means appearing:
  1048.         -- +1: more often
  1049.         -- -1: less often
  1050.      val= range_wrap(val,1,puzzle.seg_count,1)
  1051.     mutate_val_show('New',val)
  1052.     return val
  1053.   else
  1054.     return val
  1055.   end -- if random_flag1
  1056. end -- function mutate_float_val
  1057.  
  1058. function mutate_val_show(text,val)
  1059.  if herd.mutate.genes_show.act then
  1060.     print(text..' val: '..tostring(val))
  1061.  end -- if herd.mutate.genes_show.act
  1062. end -- function mutate_val_show
  1063.  
  1064. function clu_name_get(idx,kind)
  1065. -- create a table with following name elements:
  1066.  
  1067. return {
  1068.         gen=gen.cur;
  1069.         clu=idx;
  1070.         knd=kind;
  1071.         dat=os.date()
  1072.        }
  1073. end -- function clu_name_get
  1074.  
  1075. function clu_name_get_string(clu_name,dat_flag)
  1076. local OS=""
  1077.     OS= OS..'G'..clu_name.gen
  1078.     OS= OS..'C'..clu_name.clu
  1079.     OS= OS..'K'..clu_name.knd
  1080.  
  1081.  if dat_flag then
  1082.     OS= OS..'D'..clu_name.dat
  1083.  end -- if dat_flag
  1084. return OS
  1085. end -- function clu_name_get
  1086.  
  1087. function clu_apply_bands(band_use)
  1088. -- apply all bands which are:
  1089.    -- fixed
  1090.    -- stored in current clu (passed by table band_use)
  1091.  
  1092. -- for each band pair, depending on mode clu.band_to.val
  1093. -- connect origin seg (given in uselist)
  1094. -- to another seg ("center", "furthest", "random") or
  1095. -- to "space"
  1096.  
  1097. -- apply fixed bands given in clu.fix:
  1098.  local i
  1099.  for i=1,#clu.fix do
  1100.      -- print(clu.fix[i][1],clu.fix[i][2])
  1101.      band.AddBetweenSegments(clu.fix[i][1],clu.fix[i][2])
  1102.  
  1103.      local len= structure.GetDistance(clu.fix[i][1],clu.fix[i][2])+clu.fix.lencng
  1104.      len= range_clamp(len,clu.band_sys_lim.min,clu.band_sys_lim.max)
  1105.      band.SetGoalLength(band.GetCount(),len)
  1106.  
  1107.      band.SetStrength(band.GetCount(),clu.fix.str)
  1108.  end -- for i
  1109.  
  1110.  local seg_center
  1111.  if clu.band_to.val=="center" then
  1112.  -- banding to "center" is used
  1113.  -- alternative:
  1114.  -- if (clu.band_to.val=="center") or (clu.band_to.val=="space") then
  1115.  -- banding to "center" or "space" is used
  1116.  
  1117.     seg_center= seg_center_get()
  1118.     -- get current center segment
  1119.     -- fetch it before cycling through all clu bands,
  1120.     -- as it is the same each time
  1121.  end -- if clu.band_to.val
  1122.  
  1123.  -- appply random bands given in clu:
  1124.  for i=1,#band_use do
  1125.  -- with i, cycle through all clu bands & their data
  1126.  
  1127.   if band_use[i].act then
  1128.   -- only if current band i is act (gene is not off)
  1129.  
  1130.      local seg_origin= seg_use[i]
  1131.      -- get origin seg to band from seg uselist
  1132.  
  1133.      if clu.band_to.val=="space" then
  1134.      -- if banding to space, but not to other segs
  1135.      -- get
  1136.         -- axis reference seg indices (seg_axis_x,seg_axis_y) &
  1137.            -- calculated here
  1138.         -- spatial vals (rho, theta,phi) from normalzed vals
  1139.            -- given by clu data
  1140.  
  1141.         local seg_axis_x= seg_get_idx("usepuzz",seg_origin,-1)
  1142.         -- band x-angle reference is previous seg in puzzle
  1143.  
  1144.         local seg_axis_y= seg_get_idx("usepuzz",seg_origin,1)
  1145.         -- band y-angle reference is next seg in puzzle
  1146.         -- alternative:
  1147.         -- local seg_axis_y= seg_center
  1148.         -- band y-angle reference is center seg in puzzle
  1149.  
  1150.         -- rho uses band str1
  1151.         band.Add2(i,
  1152.                   seg_origin,
  1153.                   seg_axis_x,
  1154.                   seg_axis_y,
  1155.                   band_use[i].rho,
  1156.                   band_use[i].theta,
  1157.                   band_use[i].phi,
  1158.                   clu.pull.str1)
  1159.  
  1160.      else -- (clu.band_to.val=="center") or (clu.band_to.val=="furthest") or (clu.band_to.val=="random") then
  1161.      -- not banding to space, but to other segs
  1162.         -- having a relative dst or are random
  1163.         -- calculated here
  1164.  
  1165.         local seg_target1
  1166.         if     clu.band_to.val=="center" then
  1167.                seg_target1= seg_center
  1168.                -- primary target seg is center seg in puzzle
  1169.         elseif clu.band_to.val=="furthest" then
  1170.                seg_target1= seg_furthest_get(seg_origin)
  1171.                -- primary target seg is furthest to origin seg
  1172.         elseif clu.band_to.val=="random" then
  1173.                seg_target1= band_use[i].seg_target
  1174.                -- primary target seg is random
  1175.         else-- clu.band_to.val has other val
  1176.               assert(false,'function clu_apply_bands: clu.band_to.val is invalid: '..tostring(clu.band_to.val))
  1177.         end -- if clu.band_to.val
  1178.         -- primary target seg uses band str1
  1179.         band.AddBetweenSegments2(i,
  1180.                                  seg_origin,
  1181.                                  seg_target1,
  1182.                                  band_use[i].d_cng1,
  1183.                                  clu.d_cng1.min,
  1184.                                  clu.d_cng1.max,
  1185.                                  clu.pull.str1)
  1186.  
  1187.      end -- if clu.band_to.val
  1188.  
  1189.      if clu.d_cng2.act then
  1190.      -- secondary bands are used
  1191.         local seg_target2= seg_get_idx("uselist",i,1)
  1192.         -- secondary target seg is next in seg uselist
  1193.         -- secondary target seg uses band str2
  1194.         band.AddBetweenSegments2(i,
  1195.                                  seg_origin,
  1196.                                  seg_target2,
  1197.                                  band_use[i].d_cng2,
  1198.                                  clu.d_cng2.min,
  1199.                                  clu.d_cng2.max,
  1200.                                  clu.pull.str2)
  1201.      end -- if clu.d_cng2.act
  1202.   else
  1203.      -- print('B#'..i..' off')
  1204.   end -- if band_use[i].act
  1205.  end -- for i
  1206. end -- function clu_apply_bands
  1207.  
  1208. function seg_get_idx(seg_option,val,offset)
  1209.  if     seg_option=="uselist" then
  1210.         return seg_use[range_wrap((val+offset),1,#seg_use,1)]
  1211.         -- offset=+1 : angle reference is next seg in uselist
  1212.         -- offset=-1 : angle reference is prev seg in uselist
  1213.  elseif seg_option=="usepuzz" then
  1214.         return range_wrap((val+offset),1,puzzle.seg_count,1)
  1215.         -- offset=+1 : angle reference is next seg in puzzle
  1216.         -- offset=-1 : angle reference is prev seg in puzzle
  1217.  else
  1218.         assert(false, 'function seg_get_idx: seg_option has invalid val: '..tostring(seg_get_idx))
  1219.  end -- if seg_option
  1220. end -- function seg_get_idx
  1221.  
  1222. function band.Add2(i,
  1223.                    seg_origin,
  1224.                    seg_axis_x,
  1225.                    seg_axis_y,
  1226.                    rho,
  1227.                    theta,
  1228.                    phi,
  1229.                    str)
  1230.  -- print(i,seg_origin,seg_axis_x,seg_axis_y,rho,theta,phi,str)
  1231.  
  1232.  local seg_axis_y,cng_flag= seg_axis_y_check_idx(seg_origin,seg_axis_x,seg_axis_y)
  1233.  -- avoid seg_axis_y having the same val as seg_axis_x
  1234.  
  1235.  if (cng_flag and clu.band_skip_wrong)==false then
  1236.  
  1237.     local    R= rho^(1/3) + 0.001
  1238.     -- bend val rho 0..1 towards 1 by cubic root giving val R
  1239.     local  rho= R*(clu.rho.max-clu.rho.min)+clu.rho.min
  1240.     -- stretch R 0...1 to min...max giving rho again
  1241.            rho= range_clamp(rho,0,clu.band_sys_lim.max)
  1242.            -- rho within limits?
  1243.  
  1244.     local theta= math.acos(2*theta-1)+0
  1245.     -- x-angle (azimut) range: 180 degrees (here: pi)
  1246.  
  1247.     local   phi= 2*math.pi*phi+0
  1248.     -- y-angle (elevation) range: 360 degrees (here: 2*pi)
  1249.  
  1250.     local band_count1= band.GetCount()
  1251.     -- check number of bands before applying another band
  1252.     band.Add(seg_origin,
  1253.              seg_axis_x,
  1254.              seg_axis_y,
  1255.              rho,
  1256.              theta,
  1257.              phi)
  1258.     local band_count2= band.GetCount()
  1259.     -- check number of bands after applying another band
  1260.  
  1261.     if band_count1~=band_count2 then
  1262.     -- only if band has been created
  1263.     -- show its attributes
  1264.        print(
  1265.              'B#'..i..
  1266.              ' Seg#'..seg_origin..
  1267.              ':('..seg_axis_x..
  1268.              '&'..seg_axis_y..
  1269.              ') Rho:'..crop_digits(rho,3)..
  1270.              ' Theta:'..crop_digits(math.deg(theta),3).."o"..
  1271.              -- ..string.char(39)..
  1272.              ' Phi:'..crop_digits(math.deg(phi),3).."o"..
  1273.              ' Str:'..crop_digits(str,3)
  1274.             )
  1275.  
  1276.        band.SetStrength(band_count2,str)
  1277.        -- change str
  1278.     else
  1279.        print('B#'..i..' skipped')
  1280.     end -- if band_count
  1281.  else
  1282.     print('B#'..i..' skipped')
  1283.  end -- if (cng_flag and clu.band_skip_wrong) == false
  1284. end -- function band.Add2
  1285.  
  1286. function seg_axis_y_check_idx(seg_origin,seg_axis_x,seg_axis_y)
  1287. -- avoid seg_axis_y having the same val as seg_axis_x or seg_origin
  1288.  local seg_axis_y= seg_axis_y
  1289.  -- print('seg_axis_y: '..seg_axis_y)
  1290.  local cng_flag= false
  1291.  
  1292.  if (seg_axis_y==seg_axis_x) or (seg_axis_y==seg_origin) then
  1293.     seg_axis_y= range_wrap((seg_origin+1),1,puzzle.seg_count,1)
  1294.     cng_flag= true
  1295.  end -- if seg_axis_y
  1296.  
  1297.  --[[
  1298.  if cng_flag then
  1299.     print('Value changed')
  1300.  end -- if cng_flag
  1301.  --]]
  1302.  
  1303.  return seg_axis_y,cng_flag
  1304. end -- function seg_axis_y_check_idx
  1305.  
  1306. function band.AddBetweenSegments2(i,
  1307.                                   seg_origin,
  1308.                                   seg_target,
  1309.                                   d_cng,
  1310.                                   d_cng_min,
  1311.                                   d_cng_max,
  1312.                                   str)
  1313.  -- print(i,seg_origin,seg_target,d_cng,d_cng_min,d_cng_max,str)
  1314.  
  1315.  seg_target,cng_flag= seg_target_check_spat(seg_origin,seg_target)
  1316.  -- avoid seg_target beeing too close to seg_origin
  1317.  
  1318.  if (cng_flag and clu.band_skip_wrong)==false then
  1319.     local dst= structure.GetDistance(seg_origin,seg_target)
  1320.  
  1321.     local cng= (d_cng-0.5)*2
  1322.     -- as d_cng is a normalized val 0...1 internally
  1323.     -- (i don't want to mess with band lens before)
  1324.     -- stretch it to -1...1
  1325.     -- print('D_cng:'..crop_digits(d_cng,3)..' Cng:'..crop_digits(cng,3))
  1326.     local sign=   above0(cng)
  1327.           -- -1: compression
  1328.           -- +1: expansion
  1329.           cng=    sign*(math.abs(cng)*(d_cng_max-d_cng_min)+d_cng_min)
  1330.           -- as sign is stored now, truncate it from cng,
  1331.           -- resulting an absoulte val 0...1
  1332.           -- do linear transformation like cng*factor+offset
  1333.           -- (factor: delta(extremae): (max-min), offset: min)
  1334.           -- this maps 0...1 to min...max
  1335.           -- finally, multiply by sign again to get direction back
  1336.     local len= dst+cng
  1337.     -- print('Cng:'..crop_digits(cng,3)..' len:'..crop_digits(len,3))
  1338.  
  1339.     len= range_clamp(len,clu.band_sys_lim.min,clu.band_sys_lim.max)
  1340.  
  1341.     local band_count1= band.GetCount()
  1342.     -- check number of bands before applying another band
  1343.     band.AddBetweenSegments(seg_origin,seg_target)
  1344.     local band_count2= band.GetCount()
  1345.     -- check number of bands after applying another band
  1346.  
  1347.     if band_count1~=band_count2 then
  1348.     -- only if band has been created
  1349.     -- show its attributes
  1350.        print(
  1351.              'B#'..i..
  1352.              ' Seg#'..seg_origin..
  1353.              ':'..seg_target..
  1354.              ' Len:'..crop_digits(len,3)..
  1355.              ' (Cng:'..crop_digits(cng,3)..')'..
  1356.              ' Str:'..crop_digits(str,3)
  1357.             )
  1358.        -- print('Distance:'..crop_digits(dst,3)..' Cng:'..crop_digits(cng,3))
  1359.  
  1360.        band.SetGoalLength(band_count2,len)
  1361.        -- change len
  1362.        band.SetStrength(band_count2,str)
  1363.        -- change str
  1364.     else
  1365.        print('B#'..i..' skipped')
  1366.     end -- if band_count
  1367.  else
  1368.     print('B#'..i..' skipped')
  1369.  end -- if (cng_flag and clu.band_skip_wrong)==false
  1370. end -- function band.AddBetweenSegments2
  1371.  
  1372. function seg_target_check_spat(seg_origin,seg_target)
  1373. -- avoid seg_target beeing too close to seg_origin
  1374. -- by measuring spatial dst
  1375.  local seg_target= seg_target
  1376.  local cng_flag= false
  1377.  
  1378.  while structure.GetDistance(seg_origin,seg_target)<clu.seg_min_dist do
  1379.        seg_target,cng_flag= seg_target_too_close_show(seg_origin,seg_target)
  1380.  end -- structure.GetDistance
  1381.  
  1382.  --[[
  1383.  if cng_flag then
  1384.     print('Value changed')
  1385.  end -- if cng_flag
  1386.  --]]
  1387.  
  1388.  return seg_target,cng_flag
  1389. end -- seg_target_check_spat
  1390.  
  1391. function seg_target_too_close_show(seg_origin,seg_target)
  1392.  -- print('seg_origin='..seg_origin..':'..'seg_target='..seg_target..' too close.')
  1393.  -- print('increasing seg_target idx.')
  1394.  local seg_target= range_wrap((seg_target+1),1,puzzle.seg_count,1)
  1395.  return seg_target,true
  1396. end -- function seg_too_close_show
  1397.  
  1398. function pull_do()
  1399.  if pull.act then
  1400.     print('Pulling...')
  1401.     CI_apply(pull.CI_default,'Default CI for pull:')
  1402.     -- if given, apply default CI
  1403.     local i
  1404.     for i=1,#pull do
  1405.         CI_method(pull[i])
  1406.     end -- for i
  1407.  end -- if pull.act
  1408. end -- function pull_do
  1409.  
  1410. function release_n_fuse()
  1411.  if release.act then
  1412.     print('Releasing...')
  1413.     CI_apply(release.CI_default,'Default CI for release: ')
  1414.     -- if given, apply default CI
  1415.     CI_method_batch(release)
  1416.  end -- if release.act
  1417.  
  1418.  if fuse.act then
  1419.     -- print('Fusing...')
  1420.     local i
  1421.     for i=1,#fuse do
  1422.         print('Fuse#'..i..'...')
  1423.         CI_apply(fuse.CI_default,'Default CI for fuse: ')
  1424.         -- if given, apply default CI
  1425.         CI_method_batch(fuse[i])
  1426.     end -- for i
  1427.  end -- if fuse.act
  1428. end -- function release_n_fuse
  1429.  
  1430. function CI_method_batch(CI_method_list)
  1431.  quicksave_do("load",3)
  1432.  local i
  1433.  for i=1,#CI_method_list do
  1434.      CI_method(CI_method_list[i])
  1435.      quicksave_do("save",4)
  1436.      if quicksave_score[4]>quicksave_score[5] then
  1437.         quicksave_do("save",5)
  1438.      end -- if quicksave_score
  1439.   end -- for i
  1440. end -- function CI_method_batch
  1441.  
  1442. function CI_method(prm)
  1443. -- depending on passed table prm:
  1444. -- 1. if given, set CI
  1445. -- 2. for a given number of itrs &
  1446. -- 3. use a foldit tool (backbone/sidechain move or mutate)
  1447.  
  1448. -- i intentionally use only shake/wiggle all
  1449. -- & didn't implement local wiggle,
  1450. -- as it can make the puzzle too stiff (local maximum)
  1451.  
  1452. --[[
  1453.  print('CI_method prms:')
  1454.  local k,v
  1455.  for k,v in pairs(prm) do
  1456.      print(k,v)
  1457.  end
  1458. --]]
  1459.  
  1460.  CI_apply(prm.CI,'Current CI: ')
  1461.  -- if given, apply CI
  1462.  
  1463.  if type(prm.itr)=="number" then
  1464.  -- number of itrs given?
  1465.     if prm.itr>0 then
  1466.        -- depending on prm.cmd, do one of these tools:
  1467.        if     prm.cmd=="m" then
  1468.               if puzzle.ismutable then
  1469.                  if puzzle.mutate.act then
  1470.                     -- print('Mutating for '..prm.itr..' iterations...')
  1471.                     structure.MutateSidechainsAll(prm.itr)
  1472.                  end -- if puzzle.mutate.act
  1473.               end -- if puzzle.ismutable
  1474.        elseif prm.cmd=="s" then
  1475.               -- print('Shaking for '..prm.itr..' iterations...')
  1476.               structure.ShakeSidechainsAll(prm.itr)
  1477.        elseif prm.cmd=="w" then
  1478.               -- print('wiggling for '..prm.itr..' iterations...')
  1479.               structure.WiggleAll(prm.itr,prm.backbone,prm.sidechains)
  1480.        end -- if prm.cmd
  1481.     end -- if prm.itr
  1482.  end -- if prm.itr
  1483. end -- function CI_method
  1484.  
  1485. function CI_apply(CI,text)
  1486.  if type(CI)=="number" then
  1487.  -- CI given?
  1488.     -- print(text..CI)
  1489.     behavior.SetClashImportance(CI)
  1490.     -- set it
  1491.  end -- if type(CI)
  1492. end -- function CI_apply
  1493.  
  1494. function quicksave_do(mode,slot)
  1495.      if mode=="save" then
  1496.         save.Quicksave(slot)
  1497.         quicksave_score[slot]=current.GetEnergyScore()
  1498.         -- print('Quicksaved to slot:'..slot..' - Score:'..crop_digits(quicksave_score[slot],3))
  1499.  elseif mode=="load" then
  1500.         save.Quickload(slot)
  1501.         -- print('Quickloaded from slot:'..slot..' - Score:'..crop_digits(quicksave_score[slot],3))
  1502.     end -- if mode
  1503. end -- function quicksave_do
  1504.  
  1505. function quicksave_do_batch(mode,first,last)
  1506.  local i
  1507.  for i=first,last do
  1508.      quicksave_do(mode,i)
  1509.  end -- for i
  1510. end -- function quicksave_do
  1511.  
  1512. function herd_fitnessandsort(clu)
  1513.  local clu= clu
  1514.  -- print("Getting herd's scoregain minimum...")
  1515.  clu.scoregain_min= clu[1].scoregain
  1516.  -- to have a minimum gain val (gain_min) to compare
  1517.  -- get first clu's scoregain val
  1518.  local i
  1519.  for i=2,#clu do
  1520.  -- cycle through all other scoregain vals
  1521.      if clu[i].scoregain<clu.scoregain_min then
  1522.         -- new gain_min found
  1523.         clu.scoregain_min= clu[i].scoregain
  1524.         -- set it as new gain_min (worst)
  1525.      end -- if clu[i].scoregain
  1526.  end -- for i
  1527.  -- print('Old minimum clu scoregain: '..clu.scoregain_min)
  1528.  if clu.scoregain_min>0 then
  1529.  -- gain_min >0?
  1530.     clu.scoregain_min= 1
  1531.     -- we don't need to push fitness vals
  1532.     -- so resulting fitness vals will be equal to scoregain vals
  1533.  end -- if clu.scoregain_min
  1534.  -- if gain_min were <=0, we would have to push fitness vals
  1535.  -- print('New minimum clu scoregain: '..clu.scoregain_min)
  1536.  
  1537.  -- print("Putting clu's fitness vals...")
  1538.  -- fitness= gain-gain_min+1
  1539.  -- smallest fitness val  must be >0 (prevent fitnesses <=0)
  1540.  --   if all fitness vals were    =0, roulette would run infinitely
  1541.  -- (plus, we even want to give worst clus a small chance)
  1542.  local i
  1543.  for i=1,#clu do
  1544.      clu[i].fitness= clu[i].scoregain-clu.scoregain_min+1
  1545.      --[[
  1546.      a gain_min of 1 doesn't do a change:
  1547.         fitness= gain-gain_min+1
  1548.      is fitness= gain-1       +1
  1549.      is fitness= gain-0
  1550.      -> so we've set a good gain_min (>0) to 1 before
  1551.  
  1552.      -- now subtract gain_min
  1553.         (can be negative, then it will be added to push value)
  1554.         -> from clu's scoregain
  1555.            -> giving fitness==0 for worst clu
  1556.      -- then add 1, as 0 isn't allowed, too
  1557.         -> giving fitness==1 for worst clu
  1558.      --]]
  1559.  end -- for i
  1560.  
  1561.  clu= herd_normalize(clu)
  1562.  -- sum of all fitness vals==1
  1563.  
  1564.  if (herd.fitness_e~=nil) and (herd.fitness_e~=1) then
  1565.  -- bending exponent given?
  1566.     -- print("Bending clu's fitnesses...")
  1567.     local i
  1568.     for i=1,#clu do
  1569.         clu[i].fitness= clu[i].fitness^(herd.fitness_e)
  1570.         -- bend fitness val -> 1 (if 0<exponent<1)
  1571.     end -- for i
  1572.  
  1573.     clu= herd_normalize(clu)
  1574.     -- sum of all fitness vals==1
  1575.  end -- if herd.fitness_e
  1576.  
  1577.  -- print("Sorting herd by clu's fitnesses...")
  1578.  local i
  1579.  for i=1,(#clu-1) do
  1580.      local j
  1581.      for j=(i+1),#clu do
  1582.          if clu[i].fitness<clu[j].fitness then
  1583.             clu[i],clu[j]=clu[j],clu[i]
  1584.          end -- if clu[i].fitness
  1585.      end -- for j
  1586.  end -- for i
  1587.  print('\nHerd after sorting is:')
  1588.  herd_show(clu)
  1589.  -- for debugging:
  1590.  -- list_show_deep(clu,"clu")
  1591.  print()
  1592.  return clu
  1593. end -- function herd_fitnessandsort
  1594.  
  1595. function herd_normalize(clu)
  1596.  local clu= clu
  1597.  clu.fitness_sum= clu_fitness_sum_get(clu)
  1598.  
  1599.  -- print("Normalizing clu's fitnesses...")
  1600.  local i
  1601.  for i=1,#clu do
  1602.      clu[i].fitness= clu[i].fitness/clu.fitness_sum
  1603.  end -- for i
  1604.  -- print('Herd with normalized fitness is:')
  1605.  -- herd_show(clu)
  1606.  return clu
  1607. end -- function herd_normalize
  1608.  
  1609. function clu_fitness_sum_get(clu)
  1610.  -- print("Getting herd's fitness sum...")
  1611.  local fitness_sum= 0
  1612.  local i
  1613.  for i=1,#clu do
  1614.      fitness_sum= fitness_sum+clu[i].fitness
  1615.  end -- for i
  1616.  -- print('Clus have fitness sum: '..fitness_sum)
  1617.  return fitness_sum
  1618. end -- function
  1619.  
  1620. function herd_show(clu)
  1621.  print('Gen#'..gen.cur..' had start score: '..quicksave_score[2])
  1622.  local i
  1623.  for i=1,#clu do
  1624.      print(
  1625.            'Clu#'..i..
  1626.            ' Name:'..clu_name_get_string(clu[i].name,false)..
  1627.            ' Score:'..crop_digits(clu[i].score,3)..
  1628.            ' Gain:'..crop_digits(clu[i].scoregain,3)..
  1629.            ' Fitness:'..crop_digits(clu[i].fitness,6)
  1630.           )
  1631.  end -- for i
  1632.  clu.fitness_sum= clu_fitness_sum_get(clu)
  1633.  -- print('Fitness checksum: '..clu.fitness_sum)
  1634. end -- function herd_show
  1635.  
  1636. function breed_n_generate(clu)
  1637.     if     herd.EO_mode.cur==2 then
  1638.            clu= herd_generate(
  1639.                               clu,
  1640.                               herd.breed.first,
  1641.                               herd.size
  1642.                              )
  1643.     elseif herd.EO_mode.cur==1 then
  1644.            clu= herd_generate(
  1645.                               clu,
  1646.                               (herd.breed.last+1),
  1647.                               herd.size
  1648.                              )
  1649.     else
  1650.            clu= herd_breed(
  1651.                            clu,
  1652.                            herd.breed.first,
  1653.                            herd.breed.last
  1654.                           )
  1655.            if herd.mutate.act then
  1656.               clu= herd_mutate(
  1657.                                clu,
  1658.                                herd.breed.first,
  1659.                                herd.breed.last
  1660.                               )
  1661.            end -- if herd.mutate.act then
  1662.            clu= herd_generate(
  1663.                               clu,
  1664.                               (herd.breed.last+1),
  1665.                               herd.size
  1666.                              )
  1667.     end -- if herd.EO_mode.cur
  1668.  
  1669.  return clu
  1670. end -- function breed_n_generate
  1671.  
  1672. function herd_breed(clu,first,last)
  1673.  local kid={}
  1674.  -- intialize kid clus breeding section
  1675.  
  1676.  if     herd.breed.mode.val=="dual" then
  1677.         kid= herd_breed_dual(first,last)
  1678.         -- get kid by mom & dad breeding
  1679.  elseif herd.breed.mode.val=="poly" then
  1680.         kid= herd_breed_poly(first,last)
  1681.         -- get kid by orgy breeding
  1682.  else
  1683.         assert(false,'function herd_breed: herd.breed.mode.val is invalid: '..tostring(herd.breed.mode.val))
  1684.  end -- herd.breed.mode.val
  1685.  
  1686.  local i
  1687.  for i=first,last do
  1688.  -- move kids to herd
  1689.  -- overwrite old clus
  1690.     clu[i]= kid[i]
  1691.     clu[i].name= clu_name_get(i,"b")
  1692.  end -- for i
  1693.  
  1694.  return clu
  1695.  -- return new clu table
  1696. end -- function herd_breed
  1697.  
  1698. function herd_breed_dual(first,last)
  1699.  local kid={}
  1700.  -- intialize kid clus breeding section
  1701.  
  1702.  local i
  1703.  for i=first,last do
  1704.  -- fill breeding section
  1705.      local dad
  1706.      if herd.breed.roulette.dad then
  1707.         dad=roulette()
  1708.      else
  1709.         dad= range_wrap((i-first+1),1,herd.size,1)
  1710.      end -- if herd.breed.roulette.dad
  1711.  
  1712.      local mom
  1713.      if herd.breed.roulette.mom then
  1714.         mom= roulette()
  1715.         while mom==dad do
  1716.               mom=roulette()
  1717.         end -- while mom
  1718.      else
  1719.         mom= range_wrap((dad+1),1,herd.size,1)
  1720.      end -- if herd.breed.roulette.dad
  1721.  
  1722.      print('Breeding clu#'..i..'(kid)  from: '..
  1723.                                   'clu#'..dad..'(dad*'..crop_digits(herd.breed.dad_genes_prob,3)..')'..
  1724.                                 ' + '..
  1725.                                   'clu#'..mom..'(mom*'..crop_digits((1-herd.breed.dad_genes_prob),3)..')')
  1726.      kid[i]={}
  1727.      for j=1,#clu[i] do
  1728.          if random_flag1(herd.breed.dad_genes_prob) then
  1729.             print_gene(j,dad,"dad")
  1730.             kid[i][j]=clu[dad][j]
  1731.          else
  1732.             print_gene(j,mom,"mom")
  1733.             kid[i][j]=clu[mom][j]
  1734.          end -- if random_flag1
  1735.      end -- for j
  1736.  end -- for i
  1737.  return kid
  1738. end -- function function herd_breed_dual
  1739.  
  1740. function herd_breed_poly(first,last)
  1741.  local kid={}
  1742.  -- intialize kid clus breeding section
  1743.  
  1744.  local i
  1745.  for i=first,last do
  1746.  -- fill breeding section
  1747.      print('Breeding clu#'..i..'(kid)  from: whole herd')
  1748.      kid[i]={}
  1749.      for j=1,#clu[i] do
  1750.          local parent= roulette()
  1751.          print_gene(j,parent,"roulette")
  1752.          kid[i][j]=clu[parent][j]
  1753.      end -- for j
  1754.  end -- for i
  1755.  return kid
  1756. end -- function herd_breed_poly
  1757.  
  1758. function print_gene(j,parent_val,parent_text)
  1759.  if herd.breed.genes_show.act then
  1760.  -- detailed gene view activated?
  1761.     print('Gene #'..j..': clu#'..tostring(parent_val)..'('..tostring(parent_text)..')')
  1762.  end -- if herd.breed.genes_show act
  1763. end -- function print_gene
  1764.  
  1765. function roulette()
  1766.  local fitness_target= math.random()
  1767.  -- set random fitness sum goal
  1768.  -- print('Fitness target:'..crop_digits(fitness_target,6))
  1769.  
  1770.  local wheel= math.random(1,herd.size)
  1771.  -- initialize random roulette wheel position
  1772.  local fitness_sum= clu[wheel].fitness
  1773.  -- get fitness val at wheel position
  1774.  -- print('Wheel current:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
  1775.  
  1776.  while fitness_sum<=fitness_target do
  1777.  -- as long as fitness sum hasn't reached fitness sum goal
  1778.        if herd.breed.roulette.israndom then
  1779.        -- if roulette is random (not default)
  1780.        -- set another random roulette wheel position
  1781.           wheel= math.random(1,herd.size)
  1782.        else
  1783.        -- if roulette is not random (default)
  1784.           wheel= range_wrap((wheel+1),1,herd.size,1)
  1785.           -- spin wheel
  1786.        end -- if herd.breed.roulette.israndom
  1787.        fitness_sum= fitness_sum+clu[wheel].fitness
  1788.        -- print('Wheel current:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
  1789.  end -- while fitness_sum
  1790.  -- print('Wheel end:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
  1791.  return wheel
  1792. end -- function roulette
  1793.  
  1794. function main()
  1795.  print('\nMain Programm start.')
  1796.  puzzle.random_seed= random_seed_set_val(puzzle.random_seed)
  1797.  
  1798.  print('Puzzle segs mutability: '..tostring(puzzle.ismutable))
  1799.  if puzzle.ismutable==false then
  1800.     puzzle.mutate.act= false
  1801.  end -- if puzzle.ismutable
  1802.  print('Puzzle segs mutation: '..tostring(puzzle.mutate.act))
  1803.  
  1804.  print('Herd genes off prob: '..herd.mutate.prob.off)
  1805.  print('Herd mutability prob: '..herd.mutate.prob.vals)
  1806.  if herd.mutate.prob.vals<=0 then
  1807.  -- herd mutate probability is not given
  1808.     herd.mutate.act= false
  1809.     -- deactivate hed genes mutating
  1810.     -- (not needed, but prevents calling function)
  1811.  end -- if herd.mutate.prob.vals
  1812.  print('Herd mutation: '..tostring(herd.mutate.act))
  1813.  
  1814.  if herd.breed.first>herd.breed.last then
  1815.     herd.breed.first,herd.breed.last= herd.breed.last,herd.breed.first
  1816.  end -- if herd.breed.first
  1817.  
  1818.  print('EO mode: '..herd.EO_mode.cur)
  1819.  print('Breed mode: '..herd.breed.mode.val)
  1820.  
  1821.  print('Clu band mode old: '..clu.band_to.val)
  1822.  if type(puzzle.seg_center.val)=="number" then
  1823.  -- "center" seg already given by user?
  1824.     clu.band_to.val= "user"
  1825.  end -- if type(puzzle.seg_center.val)
  1826.  
  1827.  if     clu.band_to.val=="center" then
  1828.  -- banding to center
  1829.         if puzzle.seg_center.get_mode=="start" then
  1830.         -- get center seg once?
  1831.            puzzle.seg_center.val= seg_center_get()
  1832.         end -- if puzzle.seg_center.get_mode
  1833.  
  1834.  elseif clu.band_to.val=="user" then
  1835.  -- banding to user-defined seg idx
  1836.     assert((puzzle.seg_center.val>0) and (puzzle.seg_center.val<(puzzle.seg_count+1)),'function main: puzzle.seg_center.val is invalid: '..tostring(puzzle.seg_center.val))
  1837.     puzzle.seg_center.get_mode="start"
  1838.     -- get center seg once!
  1839.     clu.band_to.val= "center"
  1840.     -- "user" -> "center"
  1841.  
  1842.  elseif string.sub(clu.band_to.val, 1, 6)=="random" then
  1843.  -- using any random bands?
  1844.         if clu.band_to.val=="random1" then
  1845.            puzzle.seg_random.get_mode= "list"
  1846.         else -- if clu.band_to.val=="random2"
  1847.            puzzle.seg_random.get_mode= "all"
  1848.         end -- if clu.band_to.val
  1849.     clu.band_to.val= "random"
  1850.  -- elseif (clu.band_to.val=="space") or (clu.band_to.val=="furthest")
  1851.  end -- if clu.band_to.val
  1852.  print('Clu band mode new: '..clu.band_to.val)
  1853.  
  1854.  print('Seg center get_mode: '..puzzle.seg_center.get_mode)
  1855.  print('Seg random get_mode: '..puzzle.seg_random.get_mode)
  1856.  if (clu.band_to.val=="center") and (puzzle.seg_center.get_mode== "start") then
  1857.     -- always the same "center" seg used?
  1858.     table.insert(seg_use.exclude.idx,puzzle.seg_center.val)
  1859.     -- add it's idx to exclude candidates
  1860.  end -- if clu.band_to.val,puzzle.seg_center.get_mode
  1861.  
  1862.  seg_use= seg_use_list_create(seg_use)
  1863.  -- create seg list based on informations given at declaration
  1864.  
  1865.  -- for debugging before generation testing, uncomment this:
  1866.  -- prms_show()
  1867.  
  1868.  gen.cur= 1
  1869.  -- initialize gen counter
  1870.  
  1871.  quicksave_score={}
  1872.  --[[
  1873.  saveslots:
  1874.  1: script start
  1875.  2: gen/clu start (before applying bands/pull)
  1876.  3: after pull    (before        release/fuse start)
  1877.  4: after each release /fuse  step
  1878.  5: after  all releases/fuses per clu (best result for current clu)
  1879.  6: best result for current gen
  1880.  7: best result so far
  1881.  --]]
  1882.  
  1883.  -- save to all slots to initialize states & scores:
  1884.  quicksave_do_batch("save",1,7)
  1885.  recentbest.Save()
  1886.  -- print('Set Recent Best')
  1887.  
  1888.  clu=herd_generate(clu,1,herd.size)
  1889.  -- list_show_deep(clu,"clu") --show all clu informations
  1890.  
  1891.  herd.test={first=1,last=herd.size}
  1892.  -- normally, test all generated clus
  1893.  
  1894.  while gen.cur<=gen.max do
  1895.     print('\n\nGen: '..gen.cur)
  1896.  
  1897.     if herd.use.hybrid.state~=nil then
  1898.     -- hybrid loading is used, change loading state
  1899.        if gen.cur%herd.use.hybrid.gens==1 then
  1900.        -- number of gens to trigger reloading start state is reached
  1901.           herd.use.state.val= "start"
  1902.           -- load start state
  1903.        else
  1904.        -- number of gens to trigger reloading start state is not reached
  1905.           herd.use.state.val= herd.use.hybrid.state
  1906.           -- load specified state
  1907.        end -- if gen.cur
  1908.     end -- if herd.use.hybrid.state
  1909.  
  1910.     local loaded_text
  1911.     -- load puzzle state before pulling:
  1912.         if herd.use.state.val=="start" then
  1913.            quicksave_do("load",1)
  1914.            loaded_text= "Script Start State"
  1915.     elseif herd.use.state.val=="gen" then
  1916.            quicksave_do("load",6)
  1917.            loaded_text= "Gen's Best State"
  1918.     elseif herd.use.state.val=="script" then
  1919.            quicksave_do("load",7)
  1920.            loaded_text= "Script's Best State"
  1921.     else
  1922.            recentbest.Restore()
  1923.            loaded_text= "Recent Best State"
  1924.     end -- if herd.use.state.val
  1925.     print('Loaded: '..loaded_text..' - Score: '..crop_digits(current.GetEnergyScore(),3))
  1926.  
  1927.     -- save to these slots to initialize states & scores:
  1928.     quicksave_do_batch("save",2,6)
  1929.  
  1930.     if (herd.use.state.val=="start") and (herd.use.hybrid.state==nil) then
  1931.     -- if script start state is always loaded
  1932.        herd.test.first= 1
  1933.        -- reset test start clu (first clu of gen to test)
  1934.        while clu[herd.test.first].name.gen~=gen.cur do
  1935.        -- test start clu was not generated in this gen (it is an old one)
  1936.              herd.test.first= herd.test.first+1
  1937.              -- use next clu
  1938.              if herd.test.first>herd.size then
  1939.              -- if next clu is too high (higher than herd size)
  1940.                 herd.test.first=1
  1941.                 -- set it to 1 again
  1942.                 break
  1943.                 -- exit start clu checking
  1944.              end -- if
  1945.        end -- while clu
  1946.     end -- if if herd.use.state.val
  1947.  
  1948.     local clu_cur
  1949.     for clu_cur=herd.test.first,herd.test.last do
  1950.        -- print('clu: '..clu_cur)
  1951.        print('\nTesting: G'..gen.cur..
  1952.                         'C'..clu_cur..
  1953.                         '/'..herd.size..
  1954.                         '  Name: '..clu_name_get_string(clu[clu_cur].name,true))
  1955.        quicksave_do("load",2)
  1956.  
  1957.        band.DeleteAll()
  1958.        clu_apply_bands(clu[clu_cur])
  1959.        pull_do()
  1960.  
  1961.        band.DeleteAll()
  1962.        -- save to these slots to initialize states & scores:
  1963.        quicksave_do_batch("save",3,5)
  1964.        print('Score after pulling: '..crop_digits(quicksave_score[3],3))
  1965.  
  1966.        release_n_fuse()
  1967.  
  1968.        clu[clu_cur].score=quicksave_score[5]
  1969.        clu[clu_cur].scoregain=clu[clu_cur].score-quicksave_score[2]
  1970.        print("This clu's best Score: "..crop_digits(quicksave_score[5],3).." - Gain: "..crop_digits(clu[clu_cur].scoregain,3))
  1971.  
  1972.        if (clu_cur==herd.test.first) or (quicksave_score[5]>quicksave_score[6]) then
  1973.           quicksave_do("load",5)
  1974.           quicksave_do("save",6)
  1975.           print('New best result for this gen: '..crop_digits(quicksave_score[6],3))
  1976.        end -- if clu_cur
  1977.  
  1978.        if quicksave_score[6]>quicksave_score[7] then
  1979.           quicksave_do("load",6)
  1980.           quicksave_do("save",7)
  1981.           print('New best result so far! '..crop_digits(quicksave_score[7],3))
  1982.        end -- if quicksave_score
  1983.     end -- for clu_cur
  1984.  
  1985.     clu=herd_fitnessandsort(clu)
  1986.     -- for each clu calculate fitness given by it's score gain
  1987.     -- sort clus by fitness, best gain on top
  1988.     gen.cur=gen.cur+1
  1989.     -- increase generation counter now,
  1990.     -- so newly generated/breeded clus will
  1991.     -- get an actual "birth date" = next gen
  1992.  
  1993.     if (herd.flush_gain_thr.act==false) or (clu[1].scoregain>=herd.flush_gain_thr.thr) then
  1994.     -- best gain checking is off
  1995.     -- or   gain is good enough
  1996.        clu=breed_n_generate(clu)
  1997.        -- keep good
  1998.        -- breed good over mediocre
  1999.        -- replace bad by new ones
  2000.        herd.flush_gain_reset.cur= 0
  2001.        -- reset flush counter
  2002.     else
  2003.     -- best gain checking is on
  2004.     -- and  gain is bad  enough
  2005.        print('\nTarget result for this gen: '..crop_digits(herd.flush_gain_thr.thr,3))
  2006.        print('Best result for this gen only: '..crop_digits(clu[1].scoregain,3))
  2007.  
  2008.        herd.flush_gain_reset.cur= herd.flush_gain_reset.cur+1
  2009.        -- increase flush counter
  2010.        print('Herd flush #'..herd.flush_gain_reset.cur)
  2011.  
  2012.        clu=herd_generate(clu,1,herd.size)
  2013.        -- flush entire herd
  2014.        -- replace all clus by new ones
  2015.  
  2016.        if herd.flush_gain_reset.act then
  2017.        -- reset after flush activated?
  2018.  
  2019.           if herd.flush_gain_reset.cur>herd.flush_gain_reset.thr then
  2020.              print('Number of flushs exceeded.')
  2021.              print('Restarting from script start state.')
  2022.              quicksave_do("load",1)
  2023.              -- get script start state again
  2024.              -- save to (almost) all slots to flush states & scores:
  2025.              quicksave_do_batch("save",2,7)
  2026.              recentbest.Save()
  2027.              -- print('Set Recent Best')
  2028.  
  2029.              herd.flush_gain_reset.cur= 0
  2030.              -- reset flush counter
  2031.           end -- if herd.flush_gain_reset.cur
  2032.        end -- if herd.flush_gain_reset.act
  2033.     end -- if herd.flush_gain_thr.act,clu[1].scoregain
  2034.  end -- while gen.cur~=gen.max
  2035. end -- function main
  2036.  
  2037. function prms_cng()
  2038. --[[
  2039. input index numbering:
  2040. numerical: information, label (each section is 10*x)
  2041. a:         activity,    checkbox
  2042. t:         value,        textbox
  2043. x:         value,       slider
  2044. m:         minimum,     slider
  2045. n:         maximum,     slider
  2046. --]]
  2047.  
  2048.  local dialog_act={}
  2049.  -- initialize table for dialog activity flags
  2050.  
  2051.  if true then -- dialog 0.0
  2052.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 0/7')
  2053.  
  2054.     ask.Label00= dialog.AddLabel("Change default settings here? There are many!")
  2055.     ask.Label01= dialog.AddLabel("You can activate these dialogs:")
  2056.     ask.Input1a= dialog.AddCheckbox("#1: Random seed & Herd size",false)
  2057.     ask.Input2a= dialog.AddCheckbox("#2: EO mode & Load state",false)
  2058.     ask.Input3a= dialog.AddCheckbox("#3: Band mode",false)
  2059.     ask.Input4a= dialog.AddCheckbox("#4: Release & Fuse",false)
  2060.     ask.Input5a= dialog.AddCheckbox("#5: Band length & strength",false)
  2061.     ask.Input6a= dialog.AddCheckbox("#6: Minimum distance for banding",false)
  2062.     ask.Input7a= dialog.AddCheckbox("#7: Gene probalilities",false)
  2063.     ask.Input8a= dialog.AddCheckbox("#8: Gene breeding & mutating",false)
  2064.     ask.Input9a= dialog.AddCheckbox("#9: Flush & Reset",false)
  2065.  
  2066.     ask.LabelA0= dialog.AddLabel("some checked: OK to change values, then launch")
  2067.     ask.LabelA1= dialog.AddLabel("none checked: OK to launch script")
  2068.  
  2069.     ask=         ask_window(ask)
  2070.  
  2071.     for i=1,9 do
  2072.     -- get all checkbox selections
  2073.         dialog_act[i]= ask["Input"..i.."a"].value
  2074.         -- print('#i: '..tostring(dialog_act[i]))
  2075.     end -- for i
  2076.  end -- if dialog 0.0
  2077.  
  2078.  if dialog_act[1] then -- dialog 1.0
  2079.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 1/9')
  2080.  
  2081.     if puzzle.random_seed==nil then
  2082.        puzzle.random_seed= ""
  2083.     end -- if puzzle.random_seed
  2084.  
  2085.     ask.Input1t= dialog.AddTextbox("Random seed ",tostring(puzzle.random_seed))
  2086.     ask.Label11= dialog.AddLabel("Blank    : use new seed")
  2087.     ask.Label12= dialog.AddLabel("Number: use this seed")
  2088.     ask.Label13= dialog.AddLabel(" ")
  2089.  
  2090.     ask.Input2x= dialog.AddSlider("Herd size",herd.size,4,16,0)
  2091.     ask.Label21= dialog.AddLabel("Number of clu(ster)s for one gen(eration)")
  2092.  
  2093.     ask=         ask_window(ask)
  2094.  
  2095.     puzzle.random_seed= ask.Input1t.value
  2096.     herd.size=          ask.Input2x.value
  2097.  end -- if dialog 1.0
  2098.  
  2099.  if dialog_act[1] then -- dialog 1.1
  2100.  -- user has set herd size
  2101.  -- now set breed:
  2102.     -- first &
  2103.     -- last
  2104.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 1.1/9')
  2105.  
  2106.     local keep=0
  2107.     if (herd.size%2)==0 then
  2108.     -- if number of clus is even
  2109.      keep=2
  2110.      -- keep 2 clus
  2111.     else
  2112.     -- ff number of clu is not even
  2113.      keep=3
  2114.      -- Keep 3 clus
  2115.     end -- if (herd.size%2)
  2116.     local breed=(herd.size-keep)/2
  2117.     -- after subtracting kept clus,
  2118.     -- divide the rest by 2
  2119.     -- first half for breeding:
  2120.     herd.breed.first=keep+1
  2121.     herd.breed.last=keep+breed
  2122.     -- other half for creating new
  2123.     -- herd.breed.last+1...herd.size will be random
  2124.  
  2125.     ask.Label30= dialog.AddLabel("Breed settings:")
  2126.     ask.Label31= dialog.AddLabel("After one gen,")
  2127.     ask.Label32= dialog.AddLabel("replace mediocre clu# by new breeded ones")
  2128.     ask.Label33= dialog.AddLabel(" ")
  2129.  
  2130.     ask.Input4x= dialog.AddSlider("First",herd.breed.first,1,herd.size,0)
  2131.     ask.Label41= dialog.AddLabel("clu# to be replaced")
  2132.     ask.Label42= dialog.AddLabel("All < are kept as parents")
  2133.     ask.Label43= dialog.AddLabel(" ")
  2134.  
  2135.     ask.Input5x= dialog.AddSlider("Last",herd.breed.last,1,herd.size,0)
  2136.     ask.Label51= dialog.AddLabel("clu# to be replaced")
  2137.     ask.Label52= dialog.AddLabel("All > are created new")
  2138.     ask.Label53= dialog.AddLabel(" ")
  2139.  
  2140.     ask.Label60= dialog.AddLabel("Breed settings are also used by EO as orientation")
  2141.  
  2142.     ask=         ask_window(ask)
  2143.  
  2144.     herd.breed.first= ask.Input4x.value
  2145.     herd.breed.last=  ask.Input5x.value
  2146.  end -- if dialog 1.1
  2147.  
  2148.  if dialog_act[2] then -- dialog 2.0
  2149.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 2/9')
  2150.  
  2151.     ask.Label10= dialog.AddLabel("Extremal Optimization (discard mediocre clus)")
  2152.     ask.Input1x= dialog.AddSlider("EO mode",herd.EO_mode.cur,herd.EO_mode.min,herd.EO_mode.max,0)
  2153.     ask.Label12= dialog.AddLabel("0: no   EO (GA!), replace m.clus by breeded ones")
  2154.     ask.Label13= dialog.AddLabel("1: use EO, don't just leave m.clus as they are")
  2155.     ask.Label14= dialog.AddLabel("2: use EO, don't replace m.clus by random ones")
  2156.     ask.Label15= dialog.AddLabel(" ")
  2157.  
  2158.     local state={list=herd.use.state.list}
  2159.     ask.Label20= dialog.AddLabel("Puzzle state for each gen")
  2160.     ask.Input2x= dialog.AddSlider("Load state",key_getbyval(state.list,herd.use.state.val),1,#state.list,0)
  2161.     ask.Label22= dialog.AddLabel(" ")
  2162.     ask.Label23= dialog.AddLabel(list_text(state.list))
  2163.     ask.Label24= dialog.AddLabel(" ")
  2164.     ask.Label25= dialog.AddLabel("start:    as now")
  2165.     ask.Label26= dialog.AddLabel("            (never reach local max)")
  2166.     ask.Label27= dialog.AddLabel("gen:     best result of last gen")
  2167.     ask.Label28= dialog.AddLabel("            (avoid local max)")
  2168.     ask.Label29= dialog.AddLabel("script:  script's best")
  2169.     ask.Label2A= dialog.AddLabel("            (similar to recent)")
  2170.     ask.Label2B= dialog.AddLabel("recent: recent best state")
  2171.     ask.Label2C= dialog.AddLabel("            (can produce local max)")
  2172.  
  2173.     ask=         ask_window(ask)
  2174.  
  2175.     herd.EO_mode.cur=              ask.Input1x.value
  2176.     herd.use.state.val= state.list[ask.Input2x.value]
  2177.  end -- if dialog 2.0
  2178.  
  2179.  if dialog_act[3] then -- dialog 3.0
  2180.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 3/9')
  2181.  
  2182.     local band_to={list=clu.band_to.list}
  2183.     ask.Label30= dialog.AddLabel("Band these segs to target seg:")
  2184.     ask.Label31= dialog.AddLabel("+ in list (detected by script)")
  2185.     ask.Label32= dialog.AddLabel("+ game interface selection (blue)")
  2186.     ask.Label33= dialog.AddLabel(" ")
  2187.     ask.Input3x= dialog.AddSlider("Band mode",key_getbyval(band_to.list,clu.band_to.val),1,#band_to.list,0)
  2188.  
  2189.     ask.Label35= dialog.AddLabel(" ")
  2190.     ask.Label36= dialog.AddLabel(" ")
  2191.     ask.Label37= dialog.AddLabel(list_text(band_to.list))
  2192.     ask.Label38= dialog.AddLabel(" ")
  2193.     ask.Label39= dialog.AddLabel(" ")
  2194.     ask.Label3A= dialog.AddLabel("center:    'center' seg is auto-detected")
  2195.     ask.Label3B= dialog.AddLabel("user:       'center' seg is set manually")
  2196.     ask.Label3C= dialog.AddLabel("random1: uselist (detected & selection) to uselist")
  2197.     ask.Label3D= dialog.AddLabel("random2: uselist to all of puzzle (classic)")
  2198.  
  2199.     ask=         ask_window(ask)
  2200.  
  2201.     clu.band_to.val= band_to.list[ask.Input3x.value]
  2202.  end -- if dialog 3.0
  2203.  
  2204.  if dialog_act[3] and (clu.band_to.val=="user") then -- dialog 3.1
  2205.  -- user wants to set own "center" seg
  2206.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 3.1/9')
  2207.  
  2208.     ask.Label40= dialog.AddLabel("Set your own 'center' seg")
  2209.     ask.Input4x= dialog.AddSlider("Center seg",seg_center_get2(),1,puzzle.seg_count,0)
  2210.  
  2211.     ask=         ask_window(ask)
  2212.  
  2213.     puzzle.seg_center.val= ask.Input4x.value
  2214.  end -- if dialog 3.1
  2215.  
  2216.  if dialog_act[4] then -- dialog 4.0
  2217.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 4/9')
  2218.  
  2219.     ask.Input1a= dialog.AddCheckbox("Mutate sidechains",puzzle.mutate.act)
  2220.     ask.Label11= dialog.AddLabel("Works only if puzzle is mutable")
  2221.     ask.Label12= dialog.AddLabel(" ")
  2222.  
  2223.  
  2224.     ask.Input2a= dialog.AddCheckbox("Pull",pull.act)
  2225.     ask.Input2x= dialog.AddSlider("CI with bands",pull.CI_default,0,1,2)
  2226.     ask.Label22= dialog.AddLabel(" ")
  2227.  
  2228.     ask.Input3a= dialog.AddCheckbox("Release (1-pass)",release.act)
  2229.     ask.Input3x= dialog.AddSlider("CI without bands",release.CI_default,0,1,2)
  2230.     ask.Label32= dialog.AddLabel(" ")
  2231.  
  2232.     ask.Input4a= dialog.AddCheckbox("Fuse(s) (multiple-pass)",fuse.act)
  2233.     ask.Label41= dialog.AddLabel("CI is varied")
  2234.  
  2235.     ask=         ask_window(ask)
  2236.  
  2237.     puzzle.mutate.act=  ask.Input1a.value
  2238.     pull.act=           ask.Input2a.value
  2239.     pull.CI_default=    ask.Input2x.value
  2240.     release.act=        ask.Input3a.value
  2241.     release.CI_default= ask.Input3x.value
  2242.     fuse.act=           ask.Input4a.value
  2243.  end -- if dialog 4.0
  2244.  
  2245.  if dialog_act[5] then -- dialog 5.0
  2246.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 5/9')
  2247.  
  2248.     local prim_min,prim_max
  2249.     if clu.band_to.val=="space" then
  2250.        -- use rho vals for sliders:
  2251.        prim_min= clu.rho.min
  2252.        prim_max= clu.rho.max
  2253.     else -- clu.band_to.val~="space"
  2254.        -- use d_cng vals for sliders:
  2255.        prim_min= clu.d_cng1.min
  2256.        prim_max= clu.d_cng1.max
  2257.     end -- if clu.band_to.val
  2258.  
  2259.     if string.sub(clu.band_to.val, 1, 6)=="random" then
  2260.     -- using any random bands?
  2261.        clu.d_cng2.act= false
  2262.        -- secondary bands off by default
  2263.     end -- if "random"
  2264.  
  2265.     ask.Label10= dialog.AddLabel("Primary bands push distance by +/-")
  2266.     ask.Input1m= dialog.AddSlider("min",prim_min,0,3.8*5,2)
  2267.     ask.Input1n= dialog.AddSlider("max",prim_max,0,3.8*5,2)
  2268.     ask.Input1s= dialog.AddSlider("strength",clu.pull.str1,0,10,2)
  2269.     ask.Label14= dialog.AddLabel(" ")
  2270.  
  2271.     ask.Label20= dialog.AddLabel("Secondary bands push distance by +/-")
  2272.     ask.Input2a= dialog.AddCheckbox("on",clu.d_cng2.act)
  2273.     ask.Input2m= dialog.AddSlider("min",clu.d_cng2.min,0,3.8*5,2)
  2274.     ask.Input2n= dialog.AddSlider("max",clu.d_cng2.max,0,3.8*5,2)
  2275.     ask.Input2s= dialog.AddSlider("strength",clu.pull.str2,0,10,2)
  2276.     ask.Label25= dialog.AddLabel(" ")
  2277.  
  2278.     ask=         ask_window(ask)
  2279.  
  2280.     if ask.Input1m.value>ask.Input1n.value then
  2281.        ask.Input1m.value,ask.Input1n.value= ask.Input1n.value,ask.Input1m.value
  2282.     end -- if ask.Input11,ask.Input12
  2283.     if clu.band_to.val=="space" then
  2284.        clu.rho.min=      ask.Input1m.value
  2285.        clu.rho.max=      ask.Input1n.value
  2286.     else
  2287.        clu.d_cng1.min=   ask.Input1m.value
  2288.        clu.d_cng1.max=   ask.Input1n.value
  2289.     end -- if clu.band_to.val
  2290.  
  2291.     clu.pull.str1=       ask.Input1s.value
  2292.     clu.d_cng2.act=      ask.Input2a.value
  2293.  
  2294.     if ask.Input2m.value>ask.Input2n.value then
  2295.        ask.Input2m.value,ask.Input2n.value= ask.Input2n.value,ask.Input2m.value
  2296.     end -- if ask.Input22,ask.Input23
  2297.     clu.d_cng2.min=      ask.Input2m.value
  2298.     clu.d_cng2.max=      ask.Input2n.value
  2299.  
  2300.     clu.pull.str2=       ask.Input2s.value
  2301.  end -- if dialog 5.0
  2302.  
  2303.  if dialog_act[6] then -- dialog 6.0
  2304.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 6/9')
  2305.     ask.Label30= dialog.AddLabel("Segs with this distance are 'too close'")
  2306.     ask.Input3m= dialog.AddSlider("min",clu.seg_min_dist,0,3.8*5,2)
  2307.     ask.Label32= dialog.AddLabel(" ")
  2308.     ask.Label33= dialog.AddLabel("if 'too close:")
  2309.     ask.Input3a= dialog.AddCheckbox("skip band / don't change t.seg",clu.band_skip_wrong)
  2310.     ask.Label35= dialog.AddLabel("= neither apply band")
  2311.     ask.Label36= dialog.AddLabel("   nor change (correct) target seg idx")
  2312.     ask.Label37= dialog.AddLabel(" ")
  2313.     ask.Label38= dialog.AddLabel("if banding to many segs, possibly:")
  2314.     ask.Label39= dialog.AddLabel("-    activate this or")
  2315.     ask.Label3A= dialog.AddLabel("- deactivate secondary bands")
  2316.  
  2317.     ask=         ask_window(ask)
  2318.  
  2319.     clu.seg_min_dist=    ask.Input3m.value
  2320.     clu.band_skip_wrong= ask.Input3a.value
  2321.  end -- if dialog 6.0
  2322.  
  2323.  if dialog_act[7] then -- dialog 7.0
  2324.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 7/9')
  2325.  
  2326.     ask.Label10= dialog.AddLabel("Band gene probalilities:")
  2327.     ask.Label11= dialog.AddLabel("0.00= 0%   (none)")
  2328.     ask.Label12= dialog.AddLabel("0.50= 50%  (half)")
  2329.     ask.Label13= dialog.AddLabel("1.00= 100% (all)")
  2330.     ask.Label14= dialog.AddLabel(" ")
  2331.  
  2332.     ask.Label20= dialog.AddLabel("Turn this many")
  2333.     ask.Input2x= dialog.AddSlider("genes off",herd.mutate.prob.off,0,1,2)
  2334.     ask.Label22= dialog.AddLabel("(EO+GA)")
  2335.     ask.Label23= dialog.AddLabel(" ")
  2336.  
  2337.     ask.Label30= dialog.AddLabel("Probability of")
  2338.     ask.Input3x= dialog.AddSlider("gene mutating",herd.mutate.prob.vals,0,1,2)
  2339.     ask.Label31= dialog.AddLabel("after breeding (GA)")
  2340.     ask.Label32= dialog.AddLabel(" ")
  2341.  
  2342.     ask.Label40= dialog.AddLabel("Probability of")
  2343.     ask.Input4x= dialog.AddSlider("dad genes",herd.breed.dad_genes_prob,0,1,2)
  2344.     ask.Label42= dialog.AddLabel("(first breeding (GA) partner)")
  2345.     ask.Label44= dialog.AddLabel("Without mutating:")
  2346.     ask.Label45= dialog.AddLabel("1.00: kid is like dad")
  2347.     ask.Label46= dialog.AddLabel("0.00: kid is like mom")
  2348.  
  2349.     ask=         ask_window(ask)
  2350.  
  2351.     herd.mutate.prob.off=      ask.Input2x.value
  2352.     herd.mutate.prob.vals=     ask.Input3x.value
  2353.     herd.breed.dad_genes_prob= ask.Input4x.value
  2354.  end -- if dialog 7.0
  2355.  
  2356.  if dialog_act[8] then -- dialog 8.0
  2357.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 8/9')
  2358.  
  2359.     local breed={mode={list=herd.breed.mode.list}}
  2360.     ask.Label50= dialog.AddLabel("Breeding behaviour (genetic roulette)")
  2361.     ask.Input5x= dialog.AddSlider("Breed mode",key_getbyval(breed.mode.list,herd.breed.mode.val),1,#breed.mode.list,0)
  2362.     ask.Label52= dialog.AddLabel(" ")
  2363.     ask.Label53= dialog.AddLabel(list_text(breed.mode.list))
  2364.     ask.Label54= dialog.AddLabel(" ")
  2365.     ask.Label55= dialog.AddLabel("Each kid from:")
  2366.     ask.Label56= dialog.AddLabel("dual: 2    clus (mom & dad) (classic)")
  2367.     ask.Label57= dialog.AddLabel("poly: any clus (whole herd)")
  2368.     ask.Label58= dialog.AddLabel(" ")
  2369.  
  2370.     ask.Label60= dialog.AddLabel("Roulette is")
  2371.     ask.Input6a= dialog.AddCheckbox("random",herd.breed.roulette.israndom)
  2372.     ask.Label62= dialog.AddLabel("true:  spreaded")
  2373.     ask.Label63= dialog.AddLabel("false: inertial (classic)")
  2374.     ask.Label64= dialog.AddLabel(" ")
  2375.  
  2376.     ask.Label70= dialog.AddLabel("Show breeding details")
  2377.     ask.Input7a= dialog.AddCheckbox("gene origin clu#(parent)",herd.breed.genes_show.act)
  2378.  
  2379.     ask.Label80= dialog.AddLabel("Show mutating details")
  2380.     ask.Input8a= dialog.AddCheckbox("gene value (old & new)",herd.mutate.genes_show.act)
  2381.  
  2382.     ask=         ask_window(ask)
  2383.  
  2384.     herd.breed.mode.val=          breed.mode.list[ask.Input5x.value]
  2385.     herd.breed.roulette.israndom=                 ask.Input6a.value
  2386.     herd.breed.genes_show.act=                    ask.Input7a.value
  2387.     herd.mutate.genes_show.act=                   ask.Input8a.value
  2388.  end -- if dialog 8.0
  2389.  
  2390.  if dialog_act[9] then -- dialog 9.0
  2391.     local ask=   dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 9/9')
  2392.  
  2393.     ask.Label10= dialog.AddLabel("If best clu gain is less than")
  2394.     ask.Input1m= dialog.AddSlider("min",
  2395.                                   herd.flush_gain_thr.thr,
  2396.                                   herd.flush_gain_thr.min,
  2397.                                   herd.flush_gain_thr.max,
  2398.                                   1)
  2399.     ask.Input1a= dialog.AddCheckbox("flush herd completely",herd.flush_gain_thr.act)
  2400.     ask.Label13= dialog.AddLabel(" ")
  2401.  
  2402.     ask.Label20= dialog.AddLabel("When flushed more than this time")
  2403.     ask.Input2n= dialog.AddSlider("max",
  2404.                                   herd.flush_gain_reset.thr,
  2405.                                   herd.flush_gain_reset.min,
  2406.                                   herd.flush_gain_reset.max,
  2407.                                   0)
  2408.     ask.Input2a= dialog.AddCheckbox("reset puzzle to script start state",herd.flush_gain_reset.act)
  2409.  
  2410.     ask=         ask_window(ask)
  2411.  
  2412.     herd.flush_gain_thr.thr=    ask.Input1m.value
  2413.     herd.flush_gain_thr.act=    ask.Input1a.value
  2414.     herd.flush_gain_reset.thr=  ask.Input2n.value
  2415.     herd.flush_gain_reset.act=  ask.Input2a.value
  2416.  end -- if dialog 9.0
  2417. end -- function prms_cng
  2418.  
  2419. function ask_window(ask)
  2420.  ask.LabelX1=      dialog.AddLabel(" ")
  2421.  ask.LabelX2=      dialog.AddLabel(" ")
  2422.  ask.OK=           dialog.AddButton("OK", 1)
  2423.  ask.Cancel=       dialog.AddButton("Cancel", 0)
  2424.  local button_val= dialog.Show(ask)
  2425.  assert((button_val==1),'Script canceled!')
  2426.  return ask
  2427. end -- function ask_window
  2428.  
  2429. function list_text(list)
  2430. -- create output text with multiple lines from list
  2431.  local text= ""
  2432.  local i
  2433.  for i=1,#list do
  2434.      if text~="" then
  2435.         text= text.."\n"
  2436.      end -- if text
  2437.      text= text..tostring(i)..": "..list[i]
  2438.  end -- for i
  2439.  return text
  2440. end -- function list_text
  2441.  
  2442.  
  2443. -- declaration section:
  2444.    -- all global variables (mostly organized as table) can be set here.
  2445.    -- some of them here are used as default vals only
  2446.    -- & can be altered by gui in change section
  2447. puzzle={seg_count= structure.GetCount();
  2448.         random_seed=nil
  2449.         -- set random seed to this val
  2450.         -- if there is none,
  2451.         -- os.time()+recipe.GetrandomSeed() will be used
  2452.        }
  2453. print('Puzzle has '..puzzle.seg_count..' segments.')
  2454. puzzle.ismutable=puzzle_ismutable()
  2455. -- check if there are mutable segments
  2456. puzzle.mutate={act=(puzzle.ismutable or false)}
  2457. -- set mutating puzzle activity to the same val
  2458. -- (foldit-mutation, not equal to: mutate herd-cluster-bands)
  2459. puzzle.isligand=puzzle_isligand()
  2460. -- check if there is a ligand
  2461. puzzle.seg_center={
  2462.                    val=nil;
  2463.                    --[[
  2464.                    set which seg is considered as seg_center
  2465.                    integer number between first...last segment: use this segment index as center segment
  2466.                    puzzle.seg_count (same as last segment):     use last segment index as center segment
  2467.                    -- nil:                                      get "start" or "current"  center segment
  2468.                    --]]
  2469.                    get_mode="current"
  2470.                    --[[
  2471.                    set when seg_center is to be fetched
  2472.                    "start":                  only at script start
  2473.                                              use this when setting val to a constant number or banding to ligand
  2474.                    "current" (or any other): each time before applying bands
  2475.                    --]]
  2476.                   }
  2477. puzzle.seg_random={
  2478.                    -- get random seg from
  2479.                    get_mode="all"
  2480.                    -- "list": uselist segs
  2481.                    -- "all":  puzzle  segs
  2482.                   }
  2483.  
  2484. -- create list containing following segs:
  2485. seg_use={
  2486.          include={
  2487.                   idx={1;puzzle.seg_count};
  2488.                   -- with idx number: first & last
  2489.                   --[[
  2490.                   you can also set:
  2491.                   -- ranges instead of single indices:
  2492.                      -- idx={seg_blocks({{1;5}})};
  2493.                             includes segs 1-5
  2494.                      -- idx={seg_blocks({{1;5};{10;20}})};
  2495.                             includes segs 1-5 & 10-20
  2496.                      -- idx={seg_blocks({{1;puzzle.seg_count}})};
  2497.                             includes all segs
  2498.                   -- mix single segs & ranges:
  2499.                      -- idx=seg_use_list_append_all({1;puzzle.seg_count},seg_blocks({{10;20}});
  2500.                             includes first seg, last seg & 10-20
  2501.                   --]]
  2502.                   selected={act=true;val=true};
  2503.                   -- if act==true, include:
  2504.                   -- val:
  2505.                      -- true:    selected segs
  2506.                      -- false: unselected segs
  2507.                   frozen={act=false;backbone=true;sidechain=false};
  2508.                   -- if act==true:
  2509.                   -- add frozen segs
  2510.                   -- given in backbone & sidechain val
  2511.                   ss={};
  2512.                   -- with secondary structures
  2513.                      -- "L"=loop
  2514.                      -- "H"=helix
  2515.                      -- "E"=sheet
  2516.                   ss_cngs=true;
  2517.                   -- where secondary structure changes occur: yes
  2518.                   aa={"g"}
  2519.                   -- with amino acids
  2520.                   -- here:
  2521.                      -- include glycine
  2522.                   -- example:
  2523.                      -- aa={"f";"g"}
  2524.                      -- include phenylalanine; glycine
  2525.                  };
  2526.          exclude={
  2527.                   idx={};
  2528.                   -- without idx number: none
  2529.                   selected={act=false;val=false};
  2530.                   -- if act==true, exclude:
  2531.                   -- val:
  2532.                      -- true:    selected segs
  2533.                      -- false: unselected segs
  2534.                   frozen={act=false;backbone=true;sidechain=false};
  2535.                   -- if act==true:
  2536.                   -- remove frozen segs
  2537.                   -- given in backbone & sidechain val
  2538.                   -- note:
  2539.                      -- if you turn this on (act==true)
  2540.                      -- & set backbone to false & sidechain to false,
  2541.                      -- all unfrozen segs will be removed!
  2542.                   ss={};
  2543.                   -- without secondary structures
  2544.                      -- "L"=loop
  2545.                      -- "H"=helix
  2546.                      -- "E"=sheet
  2547.                   aa={}
  2548.                   -- without amino acids
  2549.                   -- example:
  2550.                      -- aa={"a";"v";"p";"w"}
  2551.                      -- exclude alanine; valine; proline; tryptophan
  2552.                  };
  2553.          append_all=false;
  2554.          -- append all segs to uselist
  2555.             -- false: append only segs which are not already in list
  2556.             --        (more to check when adding)
  2557.             -- true:  append all  segs (double segs will be removed later when sorting)
  2558.             --        (more to check when removing)
  2559.          remove_double=true;
  2560.          -- remove double segs from uselist after adding
  2561.             -- true:        remove
  2562.             -- false: don't remove (may not work, depending on how bands are applied)
  2563.          sort_ascending=true;
  2564.          -- sort segs in uselist by idx
  2565.             -- true:               lowest  idx first
  2566.             -- false:              highest idx first
  2567.             -- nil (or any other): don't sort
  2568.         }
  2569.  
  2570. gen={max=math.huge}
  2571. -- set number of maximum gens to test
  2572.  
  2573. herd={
  2574.       size=8;
  2575.       -- number of individuums
  2576.          -- won't grow anymore in this script version
  2577.       breed={first=3;
  2578.              -- first mediocre clu to be replaced by breeded one (GA)
  2579.              -- clus with lower  idx will be kept as good ones
  2580.              last=5;
  2581.              -- last mediocre clu to be replaced by breeded one (GA)
  2582.              -- clus with higher idx will be replaced by new random ones (flushed)
  2583.              mode={
  2584.              -- breed mode (if EO_mode==0)
  2585.              -- general breeding behaviour
  2586.                    val="dual";
  2587.                    -- set breed mode
  2588.                    list={
  2589.                          "dual"; -- breed kid from 2 partners only (regular)
  2590.                                  -- before breeding, select mom (& dad) once via roulette
  2591.                                  -- while breeding, select gene from mom or dad
  2592.                          "poly" --  breed kid from whole herd (each gene can be from any clu)
  2593.                                 --  while breeding, select gene-donor for each gene via roulette
  2594.                                 --  ignore mom & dad options
  2595.                         }
  2596.                   };
  2597.              genes_show={
  2598.              -- show detailed gene information whenn breeding
  2599.                          act=false
  2600.                          -- show which gene is from which clu
  2601.                             -- true:  show clu#(parent)
  2602.                             -- false: show possible parents only
  2603.                         };
  2604.              roulette={
  2605.              -- roulette wheel selection
  2606.                        dad=false;
  2607.                        -- use for dad (first breeding partner)
  2608.                           -- true:        use
  2609.                           -- false: don't use (1st dad is clu#1, 2nd dad is clu#2 ...)
  2610.                        mom=true;
  2611.                        -- use for mom (2nd breeding partner)
  2612.                           -- true:        use
  2613.                           -- false: don't use (mom: next clu# after dad)
  2614.                        israndom=false
  2615.                        -- 'wheel' is complete random
  2616.                           -- true:  yes, don't spin wheel - let it jump & ignore clu order
  2617.                           --                                special, makes breeding partner selection behave different.
  2618.                           --                                -> useful for "poly" breed mode, as genes will be more scattered.
  2619.                           --                                fitness is considered, nevertheless
  2620.                           -- false:  no,       spin wheel - default, as it is usually done in GA.
  2621.                           --                                fitness is considered, but more inertially
  2622.                       };
  2623.              dad_genes_prob=0.55
  2624.              -- set the (probability) ratio of dad genes (first breeding partner):
  2625.              -- float val between 0...1
  2626.                 -- <=0 :   mom genes only
  2627.                 -- 0.25 :  1/4 dad
  2628.                 -- .5 :    1/2 dad & mom
  2629.                 -- 0.75 :  3/4 dad
  2630.                 -- >=1 :   dad genes only
  2631.             };
  2632.       mutate={
  2633.       -- mutate herd cluster bands after breeding
  2634.       -- (GA-mutation, not equal to: mutate puzzle-segs)
  2635.               act=true;
  2636.               -- boolean val
  2637.                  -- true:  mutate vals depending on prob.vals
  2638.                  -- false: mutate off (don't mutate breeded bands)
  2639.               genes_show={
  2640.               -- show detailed gene information whenn mutating
  2641.                           act=false
  2642.                           -- show which gene is from which clu
  2643.                              -- true:  show clu#(parent)
  2644.                              -- false: show possible parents only
  2645.                          };
  2646.               prob={off=0.25;vals=0.1};
  2647.               -- mutate probability ratios
  2648.               -- each: float val between 0...1
  2649.                  -- <=0 :  never
  2650.                  -- 0.5 :  1/2 of cases
  2651.                  -- >=1 :  always
  2652.  
  2653.                  -- off ratio: turn bands off when generated
  2654.                  -- this prevents too many act bands for 1 clu
  2655.                  -- (as a clu loads the complete uselist)
  2656.                     -- example:
  2657.                     -- if you have 10 segments in uselist,
  2658.                     -- & off==0.25,
  2659.                     -- 1/4 of clu band genes (about 2...3 will be off)
  2660.  
  2661.                  -- vals ratio: mutate band vals when breeded
  2662.                     -- toggles (switches) band activity (activated)
  2663.                        -- (off bands -> on & vice versa)
  2664.                     -- changes band vand vals (len, rho, theta, phi)
  2665.  
  2666.                  -- examples for vals:
  2667.                     -- <=0.0 :  all  band genes will be changed (then you can set herd.mutate.act= false)
  2668.                     -- ==0.1 :  1/10 of band genes
  2669.                     -- ==0.5 :  1/2  of band genes
  2670.                     -- >=1.0 :  all  band genes will be changed
  2671.               rng10e={min=-3;max=-1}
  2672.               -- mutate band float vals (len, rho, phi theta, not segs)
  2673.               -- by +/-10^(min...max)
  2674.               -- examples:
  2675.                  -- min=-1;max=-1: change by +/-0.1
  2676.                  -- min=-2;max=-1: change by +/-0.01
  2677.                  -- min=-3;max=-3: change by +/-0.001
  2678.                  -- min=-3;max=-1: change by +/-0.001, +/-0.01 +/-or 0.1
  2679.              };
  2680.       EO_mode={
  2681.       -- Extremal Optimization mode
  2682.                cur=0;
  2683.                -- integer val between 0...2
  2684.                -- 0 :    no EO - breed clus (regular GAB)             (default: keep 2, breed 3, generate 3)
  2685.                -- 1 :  soft EO - keep  clus instead of breeding them  (default: keep 5,          generate 3)
  2686.                -- 2 :  hard EO - flush clus instead of breeding them  (default: keep 2,          generate 6)
  2687.                min=0;
  2688.                -- for gui
  2689.                max=2
  2690.                -- for gui
  2691.               };
  2692.       flush_gain_thr={
  2693.       -- flush herd (& load start state)
  2694.       -- if best gen's clu score gain is less than threshold
  2695.                       act=true;
  2696.                       -- boolean val
  2697.                          -- true:        check best gain
  2698.                          -- false: don't check (& flush)
  2699.                       thr=0.5;
  2700.                       -- if score "gain" of best cluster is less than this thr
  2701.                       -- can be negative, too
  2702.                       min=-200;
  2703.                       -- for gui
  2704.                       max=200;
  2705.                       -- for gui
  2706.                      };
  2707.       flush_gain_reset={
  2708.       -- reset puzzle to script start state
  2709.                         act=false;
  2710.                         -- boolean val
  2711.                         -- true:        reset
  2712.                         -- false: don't reset
  2713.                         cur=0;
  2714.                         -- flush counter
  2715.                         thr=2;
  2716.                         -- reset if flush counter exceeds this thr
  2717.                         min=0;
  2718.                         -- for gui
  2719.                         max=20
  2720.                         -- for gui
  2721.                        };
  2722.       fitness_e=1;
  2723.       -- exponent for herd fitness "bending"
  2724.       -- allows worse clus to appear more often.
  2725.       -- tweaks distribution of fitness vals
  2726.       -- by passing them through this exponential function:
  2727.  
  2728.       -- fitness^(1/fitness_e) is a root function
  2729.       -- exponent vals <1 bend fitness vals towards 1
  2730.       -- same is done with small random vals in R= rho^(1/3) calculating section
  2731.  
  2732.       -- value examples: fitness_e -> fitness val
  2733.          -- 1/1 (exponent 1):  exponent won't have an effect (routine will will be skipped)
  2734.          -- 1/2 (square root): fitness 0.01  -> 0.1, then normalized
  2735.          -- 1/3 (cubic root):  fitness 0.001 -> 0.1, then normalized
  2736.          -- ... etc.
  2737.       use={
  2738.            state={
  2739.            -- load state mode
  2740.                   val="recent";
  2741.                   -- set which state will be loaded before each cluster pulling
  2742.                   -- use one of these vals (also for gui):
  2743.                   list={
  2744.                         "start"; --  initial state at script start
  2745.                                  --  use if you are really stuck or have a new puzzle
  2746.                                  --  never leads to local maximum
  2747.                         "gen"; --    best result of last gen
  2748.                                --    use to allow score dropping
  2749.                                --    and to (hopefully) escape local maximum
  2750.                         "script"; -- script's best (script-internal "recent best")
  2751.                                   -- what the script considers as best solution so far
  2752.                                   -- may not catch all states (as scores are gotten after single relax/fuse steps)
  2753.                                   -- may lead to local maximum
  2754.                         "recent" --  recent best
  2755.                                  --  what the game considers as best solution so far
  2756.                                  --  catches really best states (also inbetween relax/fuse steps)
  2757.                                  --  these states may not be stable
  2758.                                  --  may lead to local maximum
  2759.                        }
  2760.                  };
  2761.            hybrid={
  2762.            -- hybrid state loading
  2763.            -- loads selected puzzle state given below,
  2764.            -- but "start" state each gens to reset puzzle
  2765.            -- useful if you are really stuck
  2766.            -- or just beginning
  2767.                    state=nil;
  2768.                    -- nil:      don't use hybrid state loading
  2769.                    -- "gen":    best result of last gen
  2770.                    -- "script": script's best
  2771.                    -- "recent": recent best
  2772.                    gens=10;
  2773.                    -- load "start" state each this number of gens
  2774.                    -- for all other gens, load state given above
  2775.                   }
  2776.           }
  2777.      }
  2778.  
  2779. clu={
  2780.      fix={
  2781.           -- here you can set some seg-pairs, which dsts should be fixed by a band
  2782.           -- example:
  2783.           -- {2;21};
  2784.           -- {31;46};
  2785.           -- fix seg2  with seg21 &
  2786.           --     seg31 with seg46
  2787.           str=2;
  2788.           -- set str of fixing bands
  2789.           lencng=0;
  2790.           -- lencng=-3.8/4;
  2791.           -- add this val to measured dst between segs
  2792.           -- giving fixing band len
  2793.           -- use vals
  2794.              -- =0 :  just keep dst of segs
  2795.              -- <0 :  do some compression
  2796.              -- >1 :  do some expansion
  2797.          };
  2798.      pull={str1=1;str2=0.1};
  2799.      -- set str of pulling bands
  2800.         -- str1:   primary bands
  2801.         -- str2: secondary bands (used if d_cng2==act)
  2802.      band_to={
  2803.      -- banding mode
  2804.               val="random2";
  2805.               -- set where segs of uselist will be banded to
  2806.               -- use one of these vals (also for gui):
  2807.               list={
  2808.                     "space"; --    band to space          (3D-Angles)
  2809.                     "center"; --   band to seg:  center   (auto-detection)
  2810.                     "user"; --     band to seg:  center   (user-defined in puzzle.seg_center.val)
  2811.                     "furthest"; -- band to seg:  furthest
  2812.                     "random1"; --  band to seg:  random      in uselist
  2813.                     "random2" --   band to seg:  random      in puzzle (classical behaviour)
  2814.                    }
  2815.              };
  2816.      rho={min=3.8/8;max=3.8};
  2817.      -- if band_to.val=="space" (seg to "air")
  2818.      -- absolute random bandlen minimum & maximum
  2819.      d_cng1={min=3.8/8;max=3.8};
  2820.      -- if band_to.val~="space"
  2821.      -- relative primary random bandlen minimum & maximum
  2822.      -- resulting band len: current seg dist+min..max
  2823.  
  2824.      d_cng2={act=true;min=0;max=3.8/8};
  2825.      -- if act==true
  2826.      -- relative secondary random bandlen (uselist-seg to uselist-seg)
  2827.      -- resulting band len=current seg dist+min..max
  2828.      band_sys_lim={
  2829.      -- band len allowed (by "system")
  2830.                    min=3.8/2;
  2831.                    -- you can also put 0 here,
  2832.                    -- but then seg to seg bands can get 'too close'
  2833.                    max=10000
  2834.                    -- as said on fold.it homepage
  2835.                   };
  2836.      seg_min_dist=3.8*1.25;
  2837.      -- minimum spatial dst for seg-banding
  2838.      -- (bandable segs detection thr based on dst)
  2839.      -- segs with dst less than this val are considered as 'too close'
  2840.      -- use this to prevent:
  2841.         -- connecting one segment to its index-neighbour, but allow closing cuts
  2842.         -- creating sharp edges in puzzle
  2843.      band_skip_wrong=false;
  2844.      -- set if "wrong bands" are corrected or rejected
  2845.      -- wrong bands: segs to be banded are too close
  2846.         -- true:  reject actual band
  2847.         --        (you will have fewer bands, in worst case 0!)
  2848.         -- false: correct band target segment
  2849.         --        (will take nearest possible segment)
  2850.     }
  2851.  
  2852. -- set which methods are performed when pulling:
  2853. pull={act=true;
  2854.       CI_default=0.5;
  2855.       -- if no CI is given
  2856.       {CI=nil;cmd="w";itr=2;backbone=true;sidechains=false}
  2857.        -- CI=nil: don't change CI, use current (last) set value
  2858.      }
  2859.  
  2860. -- set which methods are performed at each end of releasing & fusing:
  2861. release_n_fuse_end={
  2862.                     -- no
  2863.                        -- act
  2864.                        -- CI_default
  2865.                     -- because this list is appended only
  2866.                     {CI=nil;cmd="m";itr=1};
  2867.                      -- CI=nil: don't change CI, use current (last) set value
  2868.                     {CI=nil;cmd="w";itr=8;backbone=true; sidechains=true};
  2869.                     {CI=nil;cmd="m";itr=1};
  2870.                     {CI=nil;cmd="s";itr=1};
  2871.                     {CI=nil;cmd="w";itr=1;backbone=true; sidechains=true}
  2872.                    }
  2873.  
  2874. -- set which methods are performed when releasing:
  2875. release={act=false;
  2876.          -- fast "fuse" (quickstab) activated?
  2877.          CI_default=1;
  2878.          -- if no CI is given
  2879.          {CI=nil;cmd="m";itr=1};
  2880.           -- CI=nil: don't change CI, use current (last) set value
  2881.          {CI=nil;cmd="s";itr=1};
  2882.          {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2883.  
  2884.          -- at the end, always the same:
  2885.          release_n_fuse_end[1];
  2886.          release_n_fuse_end[2];
  2887.          release_n_fuse_end[3];
  2888.          release_n_fuse_end[4];
  2889.          release_n_fuse_end[5]
  2890.         }
  2891.  
  2892. -- set which methods are performed when fusing:
  2893. -- currently there are 4 sequences of methods,
  2894. -- but you can change their number (& length for each sequence)
  2895. -- to do this,
  2896. -- copy & paste a complete sequence (each begins with --fuse#x:)
  2897. -- but take care of the braces!
  2898. fuse={act=true;
  2899.       -- complex fuse activated?
  2900.       CI_default=0.3;
  2901.       -- if no CI is given
  2902. --sequence start:
  2903. --fuse#1:
  2904.       {
  2905.        {CI=0.1;cmd="m";itr=1};
  2906.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2907.         -- CI=nil: don't change CI, use current (last) set value
  2908.  
  2909.        {CI=0.7;cmd="m";itr=1};
  2910.        {CI=nil;cmd="s";itr=1};
  2911.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2912.  
  2913.        {CI=1.0;cmd="s";itr=0};
  2914.        -- itr=0: just set CI back to 1
  2915.  
  2916.        -- at the end, always the same:
  2917.        release_n_fuse_end[1];
  2918.        release_n_fuse_end[2];
  2919.        release_n_fuse_end[3];
  2920.        release_n_fuse_end[4];
  2921.        release_n_fuse_end[5]
  2922.       };
  2923. --fuse#2:
  2924.       {
  2925.        {CI=0.3;cmd="m";itr=1};
  2926.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2927.         -- CI=nil: don't change CI, use current (last) set value
  2928.  
  2929.        {CI=0.6;cmd="m";itr=1};
  2930.        {CI=nil;cmd="s";itr=1};
  2931.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2932.  
  2933.        {CI=1.0;cmd="s";itr=0};
  2934.        -- itr=0: just set CI back to 1
  2935.  
  2936.        release_n_fuse_end[1];
  2937.        release_n_fuse_end[2];
  2938.        release_n_fuse_end[3];
  2939.        release_n_fuse_end[4];
  2940.        release_n_fuse_end[5]
  2941.       };
  2942. --fuse#3:
  2943.       {
  2944.        {CI=0.2;cmd="m";itr=1};
  2945.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2946.         -- CI=nil: don't change CI, use current (last) set value
  2947.  
  2948.        {CI=0.5;cmd="m";itr=1};
  2949.        {CI=nil;cmd="s";itr=1};
  2950.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2951.  
  2952.        {CI=1.0;cmd="s";itr=0};
  2953.        -- itr=0: just set CI back to 1
  2954.  
  2955.        release_n_fuse_end[1];
  2956.        release_n_fuse_end[2];
  2957.        release_n_fuse_end[3];
  2958.        release_n_fuse_end[4];
  2959.        release_n_fuse_end[5]
  2960.      };
  2961. --fuse#4:
  2962.       {
  2963.        {CI=0.4;cmd="m";itr=1};
  2964.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2965.         -- CI=nil: don't change CI, use current (last) set value
  2966.  
  2967.        {CI=0.3;cmd="m";itr=1};
  2968.        {CI=nil;cmd="s";itr=1};
  2969.        {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
  2970.  
  2971.        {CI=1.0;cmd="s";itr=0};
  2972.         -- itr=0: just set CI back to 1
  2973.  
  2974.        release_n_fuse_end[1];
  2975.        release_n_fuse_end[2];
  2976.        release_n_fuse_end[3];
  2977.        release_n_fuse_end[4];
  2978.        release_n_fuse_end[5]
  2979.       }
  2980. --sequence end:
  2981.      }
  2982.  
  2983.  
  2984. -- debugging section:
  2985. function prms_show()
  2986. -- a call of this function will show complete content
  2987. -- of each table which is uncommented here
  2988. -- you can also use this function to print out values,
  2989. -- then copy & paste them back into script
  2990.  
  2991.    list_show_deep(puzzle,"puzzle")
  2992. -- list_show_deep(seg_use,"seg_use")
  2993. -- list_show_deep(gen,"gen")
  2994. -- list_show_deep(herd,"herd")
  2995.    list_show_deep(clu,"clu")
  2996. -- list_show_deep(release_n_fuse_end,"release_n_fuse_end")
  2997. -- list_show_deep(release,"release")
  2998. -- list_show_deep(fuse,"fuse")
  2999. end -- function prms_show()
  3000.  
  3001. -- for debugging before prm changes, uncomment this:
  3002. -- prms_show()
  3003.  
  3004.  
  3005. -- change section:
  3006.    -- call function to change some variables/tables via gui
  3007. prms_cng()
  3008.  
  3009.  
  3010. -- show section:
  3011.    -- for debugging after prm changes, uncomment this:
  3012. -- prms_show()
  3013.  
  3014.  
  3015.  
  3016. -- launch section:
  3017.    -- call main program
  3018. main()
Add Comment
Please, Sign In to add comment