Ignore:
Timestamp:
03/25/14 03:22:37 (8 years ago)
Author:
Maciej Komosinski
Message:

Updated f4 sources and made f4 available for GDK demo apps

Location:
cpp/frams/genetics/f4
Files:
1 added
1 moved

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/f4/f4_general.cpp

    r193 r196  
    1 /*
    2  *  f4_general.cpp - f4 genotype functions.
    3  *
    4  *  f4genotype - f4 format genotype conversions for FramSticks
    5  *
    6  *  Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com)
    7  *
    8  *  This library is free software; you can redistribute it and/or
    9  *  modify it under the terms of the GNU Lesser General Public
    10  *  License as published by the Free Software Foundation; either
    11  *  version 2.1 of the License, or (at your option) any later version.
    12  *
    13  *  This library is distributed in the hope that it will be useful,
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16  *  Lesser General Public License for more details.
    17  *
    18  *  You should have received a copy of the GNU Lesser General Public
    19  *  License along with this library; if not, write to the Free Software
    20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    21  *
    22  */
     1// This file is a part of the Framsticks GDK.
     2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
     3// Refer to http://www.framsticks.com/ for further information.
     4
     5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// Copyright (C) since 2001 Maciej Komosinski
    237
    248#include "f4_general.h"
    25 #include "nonstd.h"
    26 #include "framsg.h"
    27 #include "model.h" // for min and max attributes
    28 #include "geno_fx.h" //for GENOPER_ constants
     9#include <common/nonstd_stl.h>
     10#include <common/framsg.h>
     11#include <frams/model/model.h> // for min and max attributes
     12#include "../oper_fx.h" //for GENOPER_ constants
    2913#include <stdio.h>
    30 #include <math.h>
     14#include <common/nonstd_math.h>
    3115
    3216#ifdef DMALLOC
     
    3721f4_Props::f4_Props()
    3822{
    39   len      = 1.0;
    40   curv    = 0.0;
    41   mass     = 1.0;
    42   friction = 0.4;
    43   ruch    = 0.25; // bio
    44   assim    = 0.25; // bio
    45   odpor    = 0.25; // bio
    46   ingest  = 0.25; // bio
    47   twist    = 0.0;
    48   energ    = 1.0;
    49   normalizeBiol4();
     23        len = 1.0;
     24        curv = 0.0;
     25        mass = 1.0;
     26        friction = 0.4;
     27        ruch = 0.25; // bio
     28        assim = 0.25; // bio
     29        odpor = 0.25; // bio
     30        ingest = 0.25; // bio
     31        twist = 0.0;
     32        energ = 1.0;
     33        normalizeBiol4();
    5034}
    5135
    5236void f4_Props::normalizeBiol4()
    5337{
    54   // must sum to 1
    55   double sum = ruch + assim + odpor + ingest;
    56   if (0 == sum)
    57   {
    58     ruch = assim = odpor = ingest = 0.25;
    59   } else {
    60     ruch   /= sum;
    61     assim  /= sum;
    62     odpor  /= sum;
    63     ingest /= sum;
    64   }
     38        // must sum to 1
     39        double sum = ruch + assim + odpor + ingest;
     40        if (0 == sum)
     41        {
     42                ruch = assim = odpor = ingest = 0.25;
     43        }
     44        else {
     45                ruch /= sum;
     46                assim /= sum;
     47                odpor /= sum;
     48                ingest /= sum;
     49        }
    6550}
    6651
    6752void f4_Props::executeModifier(char modif)
    6853{
    69   switch (modif)
    70   {
    71    case 'L': len += (2.5 - len) * 0.3;
    72              len = min(len, Model::getMaxJoint().d.x); break;
    73    case 'l': len += (0.3 - len) * 0.3;
    74              len = max(len, Model::getMinJoint().d.x); break;
    75    case 'C': curv += ( 2.0 - curv) * 0.25;  break;
    76    case 'c': curv += (-2.0 - curv) * 0.25;  break;
    77    case 'Q': twist += ( 1.58 - twist) * 0.3; break;
    78    case 'q': twist += (-1.58 - twist) * 0.3; break;
    79    case 'A': assim += (1 - assim) * 0.8; normalizeBiol4(); break;
    80    case 'a': assim -= assim * 0.4;       normalizeBiol4(); break;
    81    case 'I': ingest += (1 - ingest) * 0.8;   normalizeBiol4(); break;
    82    case 'i': ingest -= ingest * 0.4;         normalizeBiol4(); break;
    83    case 'S': odpor += (1 - odpor) * 0.8; normalizeBiol4(); break;
    84    case 's': odpor -= odpor * 0.4;       normalizeBiol4(); break;
    85    case 'M': ruch += (1 - ruch) * 0.8;   normalizeBiol4(); break;
    86    case 'm': ruch -= ruch * 0.4;         normalizeBiol4(); break;
    87    case 'F': friction += (4 - friction) * 0.2; break;
    88    case 'f': friction -= friction * 0.2;       break;
    89    case 'W': mass += (2.0 - mass) * 0.3;   break;
    90    case 'w': mass += (0.5 - mass) * 0.3;   break;
    91    case 'E': energ += (10.0 - energ) * 0.1; break;
    92    case 'e': energ -= energ * 0.1;          break;
    93   }
     54        switch (modif)
     55        {
     56        case 'L': len += (2.5 - len) * 0.3;
     57                len = min(len, Model::getMaxJoint().d.x); break;
     58        case 'l': len += (0.3 - len) * 0.3;
     59                len = max(len, Model::getMinJoint().d.x); break;
     60        case 'C': curv += (2.0 - curv) * 0.25;  break;
     61        case 'c': curv += (-2.0 - curv) * 0.25;  break;
     62        case 'Q': twist += (1.58 - twist) * 0.3; break;
     63        case 'q': twist += (-1.58 - twist) * 0.3; break;
     64        case 'A': assim += (1 - assim) * 0.8; normalizeBiol4(); break;
     65        case 'a': assim -= assim * 0.4;       normalizeBiol4(); break;
     66        case 'I': ingest += (1 - ingest) * 0.8;   normalizeBiol4(); break;
     67        case 'i': ingest -= ingest * 0.4;         normalizeBiol4(); break;
     68        case 'S': odpor += (1 - odpor) * 0.8; normalizeBiol4(); break;
     69        case 's': odpor -= odpor * 0.4;       normalizeBiol4(); break;
     70        case 'M': ruch += (1 - ruch) * 0.8;   normalizeBiol4(); break;
     71        case 'm': ruch -= ruch * 0.4;         normalizeBiol4(); break;
     72        case 'F': friction += (4 - friction) * 0.2; break;
     73        case 'f': friction -= friction * 0.2;       break;
     74        case 'W': mass += (2.0 - mass) * 0.3;   break;
     75        case 'w': mass += (0.5 - mass) * 0.3;   break;
     76        case 'E': energ += (10.0 - energ) * 0.1; break;
     77        case 'e': energ -= energ * 0.1;          break;
     78        }
    9479}
    9580
    9681void f4_Props::adjust()
    9782{
    98   len = 0.5*len + 0.5*stdProps.len;
    99   curv = 0.66 * curv;
    100   twist = 0.66 * twist;
     83        len = 0.5*len + 0.5*stdProps.len;
     84        curv = 0.66 * curv;
     85        twist = 0.66 * twist;
    10186}
    10287
     
    10590
    10691void rolling_dec(double * v) {
    107   *v -= 0.7853;  // 0.7853981  45 degrees
     92        *v -= 0.7853;  // 0.7853981  45 degrees
    10893}
    10994void rolling_inc(double * v) {
    110   *v += 0.7853;  // 0.7853981  45 degrees
     95        *v += 0.7853;  // 0.7853981  45 degrees
    11196}
    11297
     
    11499int scanrec(const char * s, unsigned int slen, char stopchar)
    115100{
    116   unsigned int i = 0;
    117   //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
    118   while (1)
    119   {
    120     if (i >= slen)  // ran out the string, should never happen with correct string
    121       return 1;
    122     if (stopchar == s[i])  // bumped into stopchar
    123       return i;
    124     if (i < slen-1) 
    125     { // s[i] is not the last char
    126       if (s[i] == '(')
    127       {
    128         i += 2+scanrec(s+i+1, slen-i-1, ')');
    129         continue;
    130       }
    131       if (s[i] == '<')
    132       {
    133         i += 2+scanrec(s+i+1, slen-i-1, '>');
    134         continue;
    135       }
    136       if (s[i] == '#')
    137       {
    138         i += 2+scanrec(s+i+1, slen-i-1, '>');
    139         continue;
    140       }
    141     }
    142     // s[i] a non-special character
    143     i++;
    144   }
    145   return i;
     101        unsigned int i = 0;
     102        //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
     103        while (1)
     104        {
     105                if (i >= slen)  // ran out the string, should never happen with correct string
     106                        return 1;
     107                if (stopchar == s[i])  // bumped into stopchar
     108                        return i;
     109                if (i < slen - 1)
     110                { // s[i] is not the last char
     111                        if (s[i] == '(')
     112                        {
     113                                i += 2 + scanrec(s + i + 1, slen - i - 1, ')');
     114                                continue;
     115                        }
     116                        if (s[i] == '<')
     117                        {
     118                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
     119                                continue;
     120                        }
     121                        if (s[i] == '#')
     122                        {
     123                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
     124                                continue;
     125                        }
     126                }
     127                // s[i] a non-special character
     128                i++;
     129        }
     130        return i;
    146131}
    147132
    148133
    149134f4_Cell::f4_Cell(int nname,
    150     f4_Cell * ndad, int nangle, f4_Props newP)
    151 {
    152   name    = nname;
    153   type    = T_UNDIFF4;
    154   dadlink = ndad;
    155   org    = NULL;
    156   genot  = NULL;
    157   gcur    = NULL;
    158   active = 1;
    159   repeat.null();
    160   //genoRange.clear(); -- implicit
    161 
    162   anglepos  = nangle;
    163   commacount = 0;
    164   childcount = 0;
    165   P          = newP;
    166   rolling    = 0;
    167   xrot      = 0;
    168   zrot      = 0;
    169   //OM = Orient_1;
    170   ctrl    = 0;
    171   state  = 0;
    172   inertia = 0.8;
    173   force  = 0.04;
    174   sigmo  = 2;
    175   nolink = 0;
    176 
    177   // adjust firstend and OM if there is a stick dad
    178   if (ndad != NULL)
    179   {
    180     // make sure it is a stick (and not a stick f4_Cell!)
    181     if (T_STICK4 == ndad->type)
    182     {
    183       //firstend = ndad->lastend;
    184       //OM = ndad->OM;
    185       ndad->childcount++;
    186     }
    187     if (T_NEURON4 == ndad->type)
    188     {
    189       state  = ndad->state;
    190       inertia = ndad->inertia;
    191       force  = ndad->force;
    192       sigmo  = ndad->sigmo;
    193     }
    194   }
    195   // adjust lastend
    196   //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
    197   mz = 1;
     135        f4_Cell * ndad, int nangle, f4_Props newP)
     136{
     137        name = nname;
     138        type = T_UNDIFF4;
     139        dadlink = ndad;
     140        org = NULL;
     141        genot = NULL;
     142        gcur = NULL;
     143        active = 1;
     144        repeat.null();
     145        //genoRange.clear(); -- implicit
     146
     147        anglepos = nangle;
     148        commacount = 0;
     149        childcount = 0;
     150        P = newP;
     151        rolling = 0;
     152        xrot = 0;
     153        zrot = 0;
     154        //OM = Orient_1;
     155        ctrl = 0;
     156        state = 0;
     157        inertia = 0.8;
     158        force = 0.04;
     159        sigmo = 2;
     160        nolink = 0;
     161
     162        // adjust firstend and OM if there is a stick dad
     163        if (ndad != NULL)
     164        {
     165                // make sure it is a stick (and not a stick f4_Cell!)
     166                if (T_STICK4 == ndad->type)
     167                {
     168                        //firstend = ndad->lastend;
     169                        //OM = ndad->OM;
     170                        ndad->childcount++;
     171                }
     172                if (T_NEURON4 == ndad->type)
     173                {
     174                        state = ndad->state;
     175                        inertia = ndad->inertia;
     176                        force = ndad->force;
     177                        sigmo = ndad->sigmo;
     178                }
     179        }
     180        // adjust lastend
     181        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
     182        mz = 1;
    198183}
    199184
    200185
    201186f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur,
    202     f4_Cell * ndad, int nangle, f4_Props newP)
    203 {
    204   name    = nname;
    205   type    = T_UNDIFF4;
    206   dadlink = ndad;
    207   org    = nO;
    208   genot  = ngeno;
    209   gcur    = ngcur;
    210   active = 1;
    211   repeat.null();
    212   //genoRange.clear(); -- implicit
    213   // preserve geno range of parent cell
    214   if (NULL != ndad)
    215     genoRange.add( ndad->genoRange );
    216 
    217   anglepos  = nangle;
    218   commacount = 0;
    219   childcount = 0;
    220   P          = newP;
    221   rolling    = 0;
    222   xrot      = 0;
    223   zrot      = 0;
    224   //OM = Orient_1;
    225   ctrl    = 0;
    226   state  = 0;
    227   inertia = 0.8;
    228   force  = 0.04;
    229   sigmo  = 2;
    230   nolink = 0;
    231 
    232   // adjust firstend and OM if there is a stick dad
    233   if (ndad != NULL)
    234   {
    235     // make sure it is a stick (and not a stick f4_Cell!)
    236     if (T_STICK4 == ndad->type) {
    237       //firstend = ndad->lastend;
    238       //OM = ndad->OM;
    239       ndad->childcount++;
    240     }
    241     if (T_NEURON4 == ndad->type)
    242     {
    243       state  = ndad->state;
    244       inertia = ndad->inertia;
    245       force  = ndad->force;
    246       sigmo  = ndad->sigmo;
    247     }
    248   }
    249   // adjust lastend
    250   //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
    251   mz = 1;
     187        f4_Cell * ndad, int nangle, f4_Props newP)
     188{
     189        name = nname;
     190        type = T_UNDIFF4;
     191        dadlink = ndad;
     192        org = nO;
     193        genot = ngeno;
     194        gcur = ngcur;
     195        active = 1;
     196        repeat.null();
     197        //genoRange.clear(); -- implicit
     198        // preserve geno range of parent cell
     199        if (NULL != ndad)
     200                genoRange.add(ndad->genoRange);
     201
     202        anglepos = nangle;
     203        commacount = 0;
     204        childcount = 0;
     205        P = newP;
     206        rolling = 0;
     207        xrot = 0;
     208        zrot = 0;
     209        //OM = Orient_1;
     210        ctrl = 0;
     211        state = 0;
     212        inertia = 0.8;
     213        force = 0.04;
     214        sigmo = 2;
     215        nolink = 0;
     216
     217        // adjust firstend and OM if there is a stick dad
     218        if (ndad != NULL)
     219        {
     220                // make sure it is a stick (and not a stick f4_Cell!)
     221                if (T_STICK4 == ndad->type) {
     222                        //firstend = ndad->lastend;
     223                        //OM = ndad->OM;
     224                        ndad->childcount++;
     225                }
     226                if (T_NEURON4 == ndad->type)
     227                {
     228                        state = ndad->state;
     229                        inertia = ndad->inertia;
     230                        force = ndad->force;
     231                        sigmo = ndad->sigmo;
     232                }
     233        }
     234        // adjust lastend
     235        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
     236        mz = 1;
    252237}
    253238
     
    255240f4_Cell::~f4_Cell()
    256241{
    257   // remove links
    258   if (nolink)
    259   {
    260     int i;
    261     for (i=nolink-1; i>=0; i--)
    262       delete links[i];
    263     nolink=0;
    264   }
     242        // remove links
     243        if (nolink)
     244        {
     245                int i;
     246                for (i = nolink - 1; i >= 0; i--)
     247                        delete links[i];
     248                nolink = 0;
     249        }
    265250}
    266251
    267252
    268253/* return codes:
    269     >1 error at pos
    270      0  halt development for a cycle
    271     -1  development finished OK
    272 */
     254        >1 error at pos
     255        0  halt development for a cycle
     256        -1  development finished OK
     257        */
    273258int f4_Cell::onestep()
    274259{
    275   int i, j, k, relfrom, t;
    276   double w;
    277   f4_Cell * tmp;
    278   f4_Cell * tneu;
    279   if (gcur == NULL)
    280   {
    281     active = 0;
    282     return 0;  // stop
    283   }
    284   while ( NULL != gcur )
    285   {
    286     //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
    287     // currently this is the last one processed
    288     // the current genotype code is processed
    289     genoRange.add( gcur->pos );
    290     switch (gcur->name)
    291     {
    292     case '<':
    293       // cell division!
    294       //DB( printf("  div! %d\n", name); )
    295 
    296       // error: sticks cannot divide
    297       if (T_STICK4 == type) {
    298         // cannot fix
    299         org->setError(gcur->pos);
    300         return 1;  // stop
    301       }
    302 
    303       // undiff divides
    304       if (T_UNDIFF4 == type) {
    305         // commacount is set only when daughter turns into X
    306         // daughter cell
    307         // adjust new len
    308         f4_Props newP = P;
    309         newP.adjust();
    310         tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    311          this,  commacount, newP);
    312         tmp->repeat = repeat;
    313         repeat.null();
    314         org->addCell( tmp );
    315       }
    316       // a neuron divides: create a new, duplicate links
    317       if (T_NEURON4 == type) {
    318         // daughter cell
    319         tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    320           // has the same dadlink
    321           this->dadlink, commacount, P);
    322         tmp->repeat = repeat;
    323         repeat.null();
    324         // it is a neuron from start
    325         tmp->type = T_NEURON4;
    326         // duplicate links
    327         f4_CellLink * ll;
    328         for (i=0; i<nolink; i++) {
    329           ll = links[i];
    330           tmp->addlink(ll->from, ll->w, ll->t);
    331         }
    332         org->addCell( tmp );
    333       }
    334       // adjustments for this cell
    335       gcur = gcur->child;
    336       // halt development
    337       return 0;
    338 
    339     case '>':
    340       // finish
    341       // see if there is a repet count
    342       if (repeat.top > 0)
    343       { // there is a repeat counter
    344         if (!repeat.first()->isNull())
    345         { // repeat counter is not null
    346           repeat.first()->dec();
    347           if (repeat.first()->count > 0)
    348           {
    349             // return to repeat
    350             gcur = repeat.first()->node->child;
    351           } else {
    352             // continue
    353             gcur = repeat.first()->node->child2;
    354             repeat.pop();
    355           }
    356           break;
    357         } else {
    358           repeat.pop();
    359         }
    360       } else {
    361         // error: still undiff
    362         if (T_UNDIFF4 == type)
    363         {
    364           // fix it: insert an 'X'
    365           f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
    366           if (org->setRepairInsert(gcur->pos, gcur, insertnode))
    367             // not in repair mode, release
    368             delete insertnode;
    369           return 1;
    370         }
    371         repeat.null();
    372         active = 0;  // stop
    373         // eat up rest
    374         gcur = NULL;
    375         return 0;
    376       }
    377 
    378     case '#':
    379       // repetition marker
    380       if (repeat.top >= repeat_stack::stackSize)
    381       {
    382         // repepeat pointer stack is full, cannot remember this one.
    383         // fix: delete it
    384         org->setRepairRemove(gcur->pos, gcur);
    385         return 1;  // stop
    386       }
    387       repeat.push( repeat_ptr(gcur, gcur->i1) );
    388       gcur = gcur->child;
    389       break;
    390 
    391     case ',':
    392       commacount++;
    393       gcur = gcur->child;
    394       break;
    395 
    396     case 'r':  case 'R':
    397       // error: if neuron
    398       if (T_NEURON4 == type) {
    399         // fix: delete it
    400         org->setRepairRemove(gcur->pos, gcur);
    401         return 1;  // stop
    402       }
    403       switch (gcur->name) {
    404        case 'r':   rolling_dec( &rolling ); break;
    405        case 'R':   rolling_inc( &rolling ); break;
    406       }
    407       gcur = gcur->child;
    408       break;
    409 
    410     case 'l':  case 'L':
    411     case 'c':  case 'C':
    412     case 'q':  case 'Q':
    413     case 'a':  case 'A':
    414     case 'i':  case 'I':
    415     case 's':  case 'S':
    416     case 'm':  case 'M':
    417     case 'f':  case 'F':
    418     case 'w':  case 'W':
    419     case 'e':  case 'E':
    420       // error: if neuron
    421       if (T_NEURON4 == type) {
    422         // fix: delete it
    423         org->setRepairRemove(gcur->pos, gcur);
    424         return 1;  // stop
    425       }
    426       P.executeModifier(gcur->name);
    427       gcur = gcur->child;
    428       break;
    429 
    430     case 'X':
    431       // turn undiff. cell into a stick
    432       // error: already differentiated
    433       if (T_UNDIFF4 != type) {
    434         // fix: delete this node
    435         org->setRepairRemove(gcur->pos, gcur);
    436         return 1;  // stop
    437       }
    438       type = T_STICK4;
    439       // fix dad commacount and own anglepos
    440       if (NULL != dadlink) {
    441         dadlink->commacount++;
    442         anglepos = dadlink->commacount;
    443       }
    444       // change of type halts developments, see comment at 'N'
    445       gcur = gcur->child;
    446       return 0;
    447 
    448     case 'N':
    449       // turn undiff. cell into a neuron
    450       // error: already differentiated
    451       if (T_UNDIFF4 != type) {
    452         // fix: delete this node
    453         org->setRepairRemove(gcur->pos, gcur);
    454         return 1;  // stop
    455       }
    456       // error: if no previous
    457       if (NULL == dadlink) {
    458         // fix: delete it
    459         org->setRepairRemove(gcur->pos, gcur);
    460         return 1;  // stop
    461       }
    462       type = T_NEURON4;
    463       // change of type also halts development, to give other
    464       // cells a chance for adjustment.  Namely, it is important
    465       // to wait for other cells to turn N before adding links
    466       gcur = gcur->child;
    467       return 0;
    468 
    469     case '@':
    470     case '|':
    471       // neuron rotating / bending
    472       j = 1;
    473       if ('@' == gcur->name) j = 1; // rot
    474       if ('|' == gcur->name) j = 2; // bend
    475       // error: not a neuron (undiff)
    476       if (T_UNDIFF4 == type) {
    477         // fix: delete it
    478         org->setRepairRemove(gcur->pos, gcur);
    479         return 1;  // stop
    480       }
    481       // error: not a neuron (stick)
    482       if (T_NEURON4 != type) {
    483         // fix: delete it
    484         org->setRepairRemove(gcur->pos, gcur);
    485         return 1;  // stop
    486       }
    487       // error: already has control
    488       if (ctrl != 0) {
    489         // fix: delete it
    490         org->setRepairRemove(gcur->pos, gcur);
    491         return 1;  // stop
    492       }
    493       // make neuron ctrl = 1 or 2
    494       ctrl = j;
    495       gcur = gcur->child;
    496       break;
    497 
    498     case '[':
    499       // link to neuron
    500       // error: not a neuron
    501       if (T_NEURON4 != type) {
    502         // fix: delete it
    503         org->setRepairRemove(gcur->pos, gcur);
    504         return 1;  // stop
    505       }
    506       // input ('*', 'G', 'T', 'S', or %d)
    507       t       = gcur->i1;
    508       relfrom = gcur->l1;
    509       w       = gcur->f1;
    510       if (t>0) {
    511         // * or G
    512         tneu = NULL;
    513       } else {
    514         // input from other neuron
    515         // find neuron at relative i
    516         // find own index
    517         j = 0; k = 0;
    518         for(i=0; i<org->nc; i++) {
    519           if (org->C[i]->type == T_NEURON4) k++;
    520           if (org->C[i] == this) {j=k-1; break;}
    521         }
    522         // find index of incoming
    523         j = j + relfrom;
    524         if (j<0) goto wait_link;
    525         if (j>=org->nc) goto wait_link;
    526         // find that neuron
    527         k = 0;
    528         for(i=0; i<org->nc; i++) {
    529           if (org->C[i]->type == T_NEURON4) k++;
    530           if (j == (k-1)) break;
    531         }
    532         if (i>=org->nc) goto wait_link;
    533         tneu = org->C[i];
    534       }
    535       // add link
    536       // error: could not add link (too many?)
    537       if (addlink(tneu, w, t)) {
    538         // cannot fix
    539         org->setError(gcur->pos);
    540         return 1;  // stop
    541       }
    542       gcur = gcur->child;
    543       break;
    544     wait_link:
    545       // wait for other neurons to develop
    546       // if there are others still active
    547       active = 0;
    548       j = 0;
    549       for(i=0; i<org->nc; i++) {
    550         if (org->C[i]->active) j++;
    551       }
    552       if (j>0)
    553         return 0;  // there is other active, halt, try again
    554       // no more actives, cannot add link, ignore, but treat not as an error
    555       gcur = gcur->child;
    556       break;
    557 
    558     case ':':
    559       // neuron parameter
    560       // error: not a neuron
    561       if (T_NEURON4 != type) {
    562         // fix: delete it
    563         org->setRepairRemove(gcur->pos, gcur);
    564         return 1;  // stop
    565       }
    566       j = (int)gcur->l1;
    567       switch ((char)gcur->i1) {
    568        case '!':
    569         if (j) force += (1.0 - force) * 0.2;
    570         else   force -= force * 0.2; break;
    571        case '=':
    572         if (j) inertia += (1.0 - inertia) * 0.2;
    573         else   inertia -= inertia * 0.2; break;
    574        case '/':
    575         if (j) sigmo *= 1.4;
    576         else   sigmo /= 1.4; break;
    577        default:
    578          org->setRepairRemove(gcur->pos, gcur);
    579          return 1;  // stop
    580       }
    581       gcur = gcur->child;
    582       break;
    583 
    584     case ' ':
    585       // space has no effect, should not occur
    586       // fix: delete it
    587       org->setRepairRemove(gcur->pos, gcur);
    588       gcur = gcur->child;
    589       break;
    590 
    591     default:
    592       // error: unknown code
    593       char buf[40];
    594       sprintf(buf, "unknown code '%c'", gcur->name);
    595       FramMessage("f4_Cell", "onestep", buf, 2);
    596       // fix: delete it
    597       org->setRepairRemove(gcur->pos, gcur);
    598       return 1; // stop
    599     }
    600   }
    601   active = 0;  // done
    602   return 0;
     260        int i, j, k, relfrom, t;
     261        double w;
     262        f4_Cell * tmp;
     263        f4_Cell * tneu;
     264        if (gcur == NULL)
     265        {
     266                active = 0;
     267                return 0;  // stop
     268        }
     269        while (NULL != gcur)
     270        {
     271                //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
     272                // currently this is the last one processed
     273                // the current genotype code is processed
     274                genoRange.add(gcur->pos);
     275                switch (gcur->name)
     276                {
     277                case '<':
     278                        // cell division!
     279                        //DB( printf("  div! %d\n", name); )
     280
     281                        // error: sticks cannot divide
     282                        if (T_STICK4 == type) {
     283                                // cannot fix
     284                                org->setError(gcur->pos);
     285                                return 1;  // stop
     286                        }
     287
     288                        // undiff divides
     289                        if (T_UNDIFF4 == type) {
     290                                // commacount is set only when daughter turns into X
     291                                // daughter cell
     292                                // adjust new len
     293                                f4_Props newP = P;
     294                                newP.adjust();
     295                                tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     296                                        this, commacount, newP);
     297                                tmp->repeat = repeat;
     298                                repeat.null();
     299                                org->addCell(tmp);
     300                        }
     301                        // a neuron divides: create a new, duplicate links
     302                        if (T_NEURON4 == type) {
     303                                // daughter cell
     304                                tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     305                                        // has the same dadlink
     306                                        this->dadlink, commacount, P);
     307                                tmp->repeat = repeat;
     308                                repeat.null();
     309                                // it is a neuron from start
     310                                tmp->type = T_NEURON4;
     311                                // duplicate links
     312                                f4_CellLink * ll;
     313                                for (i = 0; i < nolink; i++) {
     314                                        ll = links[i];
     315                                        tmp->addlink(ll->from, ll->w, ll->t);
     316                                }
     317                                org->addCell(tmp);
     318                        }
     319                        // adjustments for this cell
     320                        gcur = gcur->child;
     321                        // halt development
     322                        return 0;
     323
     324                case '>':
     325                        // finish
     326                        // see if there is a repet count
     327                        if (repeat.top > 0)
     328                        { // there is a repeat counter
     329                                if (!repeat.first()->isNull())
     330                                { // repeat counter is not null
     331                                        repeat.first()->dec();
     332                                        if (repeat.first()->count > 0)
     333                                        {
     334                                                // return to repeat
     335                                                gcur = repeat.first()->node->child;
     336                                        }
     337                                        else {
     338                                                // continue
     339                                                gcur = repeat.first()->node->child2;
     340                                                repeat.pop();
     341                                        }
     342                                        break;
     343                                }
     344                                else {
     345                                        repeat.pop();
     346                                }
     347                        }
     348                        else {
     349                                // error: still undiff
     350                                if (T_UNDIFF4 == type)
     351                                {
     352                                        // fix it: insert an 'X'
     353                                        f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
     354                                        if (org->setRepairInsert(gcur->pos, gcur, insertnode))
     355                                                // not in repair mode, release
     356                                                delete insertnode;
     357                                        return 1;
     358                                }
     359                                repeat.null();
     360                                active = 0;  // stop
     361                                // eat up rest
     362                                gcur = NULL;
     363                                return 0;
     364                        }
     365
     366                case '#':
     367                        // repetition marker
     368                        if (repeat.top >= repeat_stack::stackSize)
     369                        {
     370                                // repepeat pointer stack is full, cannot remember this one.
     371                                // fix: delete it
     372                                org->setRepairRemove(gcur->pos, gcur);
     373                                return 1;  // stop
     374                        }
     375                        repeat.push(repeat_ptr(gcur, gcur->i1));
     376                        gcur = gcur->child;
     377                        break;
     378
     379                case ',':
     380                        commacount++;
     381                        gcur = gcur->child;
     382                        break;
     383
     384                case 'r':  case 'R':
     385                        // error: if neuron
     386                        if (T_NEURON4 == type) {
     387                                // fix: delete it
     388                                org->setRepairRemove(gcur->pos, gcur);
     389                                return 1;  // stop
     390                        }
     391                        switch (gcur->name) {
     392                        case 'r':   rolling_dec(&rolling); break;
     393                        case 'R':   rolling_inc(&rolling); break;
     394                        }
     395                        gcur = gcur->child;
     396                        break;
     397
     398                case 'l':  case 'L':
     399                case 'c':  case 'C':
     400                case 'q':  case 'Q':
     401                case 'a':  case 'A':
     402                case 'i':  case 'I':
     403                case 's':  case 'S':
     404                case 'm':  case 'M':
     405                case 'f':  case 'F':
     406                case 'w':  case 'W':
     407                case 'e':  case 'E':
     408                        // error: if neuron
     409                        if (T_NEURON4 == type) {
     410                                // fix: delete it
     411                                org->setRepairRemove(gcur->pos, gcur);
     412                                return 1;  // stop
     413                        }
     414                        P.executeModifier(gcur->name);
     415                        gcur = gcur->child;
     416                        break;
     417
     418                case 'X':
     419                        // turn undiff. cell into a stick
     420                        // error: already differentiated
     421                        if (T_UNDIFF4 != type) {
     422                                // fix: delete this node
     423                                org->setRepairRemove(gcur->pos, gcur);
     424                                return 1;  // stop
     425                        }
     426                        type = T_STICK4;
     427                        // fix dad commacount and own anglepos
     428                        if (NULL != dadlink) {
     429                                dadlink->commacount++;
     430                                anglepos = dadlink->commacount;
     431                        }
     432                        // change of type halts developments, see comment at 'N'
     433                        gcur = gcur->child;
     434                        return 0;
     435
     436                case 'N':
     437                        // turn undiff. cell into a neuron
     438                        // error: already differentiated
     439                        if (T_UNDIFF4 != type) {
     440                                // fix: delete this node
     441                                org->setRepairRemove(gcur->pos, gcur);
     442                                return 1;  // stop
     443                        }
     444                        // error: if no previous
     445                        if (NULL == dadlink) {
     446                                // fix: delete it
     447                                org->setRepairRemove(gcur->pos, gcur);
     448                                return 1;  // stop
     449                        }
     450                        type = T_NEURON4;
     451                        // change of type also halts development, to give other
     452                        // cells a chance for adjustment.  Namely, it is important
     453                        // to wait for other cells to turn N before adding links
     454                        gcur = gcur->child;
     455                        return 0;
     456
     457                case '@':
     458                case '|':
     459                        // neuron rotating / bending
     460                        j = 1;
     461                        if ('@' == gcur->name) j = 1; // rot
     462                        if ('|' == gcur->name) j = 2; // bend
     463                        // error: not a neuron (undiff)
     464                        if (T_UNDIFF4 == type) {
     465                                // fix: delete it
     466                                org->setRepairRemove(gcur->pos, gcur);
     467                                return 1;  // stop
     468                        }
     469                        // error: not a neuron (stick)
     470                        if (T_NEURON4 != type) {
     471                                // fix: delete it
     472                                org->setRepairRemove(gcur->pos, gcur);
     473                                return 1;  // stop
     474                        }
     475                        // error: already has control
     476                        if (ctrl != 0) {
     477                                // fix: delete it
     478                                org->setRepairRemove(gcur->pos, gcur);
     479                                return 1;  // stop
     480                        }
     481                        // make neuron ctrl = 1 or 2
     482                        ctrl = j;
     483                        gcur = gcur->child;
     484                        break;
     485
     486                case '[':
     487                        // link to neuron
     488                        // error: not a neuron
     489                        if (T_NEURON4 != type) {
     490                                // fix: delete it
     491                                org->setRepairRemove(gcur->pos, gcur);
     492                                return 1;  // stop
     493                        }
     494                        // input ('*', 'G', 'T', 'S', or %d)
     495                        t = gcur->i1;
     496                        relfrom = gcur->l1;
     497                        w = gcur->f1;
     498                        if (t > 0) {
     499                                // * or G
     500                                tneu = NULL;
     501                        }
     502                        else {
     503                                // input from other neuron
     504                                // find neuron at relative i
     505                                // find own index
     506                                j = 0; k = 0;
     507                                for (i = 0; i < org->nc; i++) {
     508                                        if (org->C[i]->type == T_NEURON4) k++;
     509                                        if (org->C[i] == this) { j = k - 1; break; }
     510                                }
     511                                // find index of incoming
     512                                j = j + relfrom;
     513                                if (j < 0) goto wait_link;
     514                                if (j >= org->nc) goto wait_link;
     515                                // find that neuron
     516                                k = 0;
     517                                for (i = 0; i < org->nc; i++) {
     518                                        if (org->C[i]->type == T_NEURON4) k++;
     519                                        if (j == (k - 1)) break;
     520                                }
     521                                if (i >= org->nc) goto wait_link;
     522                                tneu = org->C[i];
     523                        }
     524                        // add link
     525                        // error: could not add link (too many?)
     526                        if (addlink(tneu, w, t)) {
     527                                // cannot fix
     528                                org->setError(gcur->pos);
     529                                return 1;  // stop
     530                        }
     531                        gcur = gcur->child;
     532                        break;
     533                wait_link:
     534                        // wait for other neurons to develop
     535                        // if there are others still active
     536                        active = 0;
     537                        j = 0;
     538                        for (i = 0; i<org->nc; i++) {
     539                                if (org->C[i]->active) j++;
     540                        }
     541                        if (j>0)
     542                                return 0;  // there is other active, halt, try again
     543                        // no more actives, cannot add link, ignore, but treat not as an error
     544                        gcur = gcur->child;
     545                        break;
     546
     547                case ':':
     548                        // neuron parameter
     549                        // error: not a neuron
     550                        if (T_NEURON4 != type) {
     551                                // fix: delete it
     552                                org->setRepairRemove(gcur->pos, gcur);
     553                                return 1;  // stop
     554                        }
     555                        j = (int)gcur->l1;
     556                        switch ((char)gcur->i1) {
     557                        case '!':
     558                                if (j) force += (1.0 - force) * 0.2;
     559                                else   force -= force * 0.2; break;
     560                        case '=':
     561                                if (j) inertia += (1.0 - inertia) * 0.2;
     562                                else   inertia -= inertia * 0.2; break;
     563                        case '/':
     564                                if (j) sigmo *= 1.4;
     565                                else   sigmo /= 1.4; break;
     566                        default:
     567                                org->setRepairRemove(gcur->pos, gcur);
     568                                return 1;  // stop
     569                        }
     570                        gcur = gcur->child;
     571                        break;
     572
     573                case ' ':
     574                        // space has no effect, should not occur
     575                        // fix: delete it
     576                        org->setRepairRemove(gcur->pos, gcur);
     577                        gcur = gcur->child;
     578                        break;
     579
     580                default:
     581                        // error: unknown code
     582                        char buf[40];
     583                        sprintf(buf, "unknown code '%c'", gcur->name);
     584                        FramMessage("f4_Cell", "onestep", buf, 2);
     585                        // fix: delete it
     586                        org->setRepairRemove(gcur->pos, gcur);
     587                        return 1; // stop
     588                }
     589        }
     590        active = 0;  // done
     591        return 0;
    603592}
    604593
     
    606595int f4_Cell::addlink(f4_Cell * nfrom, double nw, long nt)
    607596{
    608   if (nolink >= MAXINPUTS-1) return -1; // full!
    609   links[nolink] = new f4_CellLink(nfrom, nw, nt);
    610   nolink++;
    611   return 0;
     597        if (nolink >= MAXINPUTS - 1) return -1; // full!
     598        links[nolink] = new f4_CellLink(nfrom, nw, nt);
     599        nolink++;
     600        return 0;
    612601}
    613602
     
    615604void f4_Cell::adjustRec()
    616605{
    617   //f4_OrientMat rot;
    618   int     i;
    619 
    620   if (recProcessedFlag)
    621     // already processed
    622     return;
    623 
    624   // mark it processed
    625   recProcessedFlag = 1;
    626 
    627   // make sure its parent is processed first
    628   if (NULL != dadlink)
    629     dadlink->adjustRec();
    630 
    631   // count children
    632   childcount = 0;
    633   for(i=0; i<org->nc; i++)
    634   {
    635     if (org->C[i]->dadlink == this)
    636       if (org->C[i]->type == T_STICK4)
    637         childcount++;
    638   }
    639 
    640   if (type == T_STICK4)
    641   {
    642     if (NULL == dadlink)
    643     {
    644       //firstend = Pt3D_0;
    645       // rotation due to rolling
    646       xrot = rolling;
    647       mz = 1;
    648     } else {
    649       //firstend = dadlink->lastend;
    650       f4_Props Pdad = dadlink->P;
    651       f4_Props Padj = Pdad;
    652       Padj.adjust();
    653 
    654       //rot = Orient_1;
    655 
    656       // rotation due to rolling
    657       xrot = rolling +
    658         // rotation due to twist
    659         Pdad.twist;
    660       if (dadlink->commacount <= 1)
    661       {
    662         // rotation due to curvedness
    663         zrot = Padj.curv;
    664       } else {
    665         zrot = Padj.curv +
    666           // GDK uses 3.141 instead of PI!
    667           (anglepos * 1.0/(dadlink->commacount+1) - 0.5) * 3.141 * 2.0;
    668       }
    669 
    670       //rot = rot * f4_OrientMat(yOz, xrot);
    671       //rot = rot * f4_OrientMat(xOy, zrot);
    672       // rotation relative to parent stick
    673       //OM = rot * OM;
    674 
    675       // rotation in world coordinates
    676       //OM =  ((f4_OrientMat)dadlink->OM) * OM;
    677       mz = dadlink->mz / dadlink->childcount;
    678     }
    679     //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
    680     //lastend = firstend + lastoffset;
    681   }
     606        //f4_OrientMat rot;
     607        int     i;
     608
     609        if (recProcessedFlag)
     610                // already processed
     611                return;
     612
     613        // mark it processed
     614        recProcessedFlag = 1;
     615
     616        // make sure its parent is processed first
     617        if (NULL != dadlink)
     618                dadlink->adjustRec();
     619
     620        // count children
     621        childcount = 0;
     622        for (i = 0; i < org->nc; i++)
     623        {
     624                if (org->C[i]->dadlink == this)
     625                        if (org->C[i]->type == T_STICK4)
     626                                childcount++;
     627        }
     628
     629        if (type == T_STICK4)
     630        {
     631                if (NULL == dadlink)
     632                {
     633                        //firstend = Pt3D_0;
     634                        // rotation due to rolling
     635                        xrot = rolling;
     636                        mz = 1;
     637                }
     638                else {
     639                        //firstend = dadlink->lastend;
     640                        f4_Props Pdad = dadlink->P;
     641                        f4_Props Padj = Pdad;
     642                        Padj.adjust();
     643
     644                        //rot = Orient_1;
     645
     646                        // rotation due to rolling
     647                        xrot = rolling +
     648                                // rotation due to twist
     649                                Pdad.twist;
     650                        if (dadlink->commacount <= 1)
     651                        {
     652                                // rotation due to curvedness
     653                                zrot = Padj.curv;
     654                        }
     655                        else {
     656                                zrot = Padj.curv +
     657                                        // GDK uses 3.141 instead of PI!
     658                                        (anglepos * 1.0 / (dadlink->commacount + 1) - 0.5) * 3.141 * 2.0;
     659                        }
     660
     661                        //rot = rot * f4_OrientMat(yOz, xrot);
     662                        //rot = rot * f4_OrientMat(xOy, zrot);
     663                        // rotation relative to parent stick
     664                        //OM = rot * OM;
     665
     666                        // rotation in world coordinates
     667                        //OM =  ((f4_OrientMat)dadlink->OM) * OM;
     668                        mz = dadlink->mz / dadlink->childcount;
     669                }
     670                //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
     671                //lastend = firstend + lastoffset;
     672        }
    682673}
    683674
     
    686677f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, long nt)
    687678{
    688   from = nfrom;
    689   w    = nw;
    690   t    = nt;
     679        from = nfrom;
     680        w = nw;
     681        t = nt;
    691682}
    692683
     
    695686f4_Cells::f4_Cells(f4_node * genome, int nrepair)
    696687{
    697   // create ancestor cell
    698   repair = nrepair;
    699   error = 0;
    700   errorpos = -1;
    701   repair_remove = NULL;
    702   repair_parent = NULL;
    703   repair_insert = NULL;
    704   tmpcel = NULL;
    705   f4rootnode = NULL;
    706 
    707   C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
    708   nc  = 1;
     688        // create ancestor cell
     689        repair = nrepair;
     690        error = 0;
     691        errorpos = -1;
     692        repair_remove = NULL;
     693        repair_parent = NULL;
     694        repair_insert = NULL;
     695        tmpcel = NULL;
     696        f4rootnode = NULL;
     697
     698        C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
     699        nc = 1;
    709700}
    710701
     
    712703f4_Cells::f4_Cells(SString & genome, int nrepair)
    713704{
    714   int res;
    715   repair = nrepair;
    716   error = 0;
    717   errorpos = -1;
    718   repair_remove = NULL;
    719   repair_parent = NULL;
    720   repair_insert = NULL;
    721   tmpcel = NULL;
    722   f4rootnode = NULL;
    723 
    724   // transform geno from string to nodes
    725   f4rootnode = new f4_node();
    726   res = f4_processrec((const char*)genome, (unsigned)0, f4rootnode);
    727   if ((res<0) || (1 != f4rootnode->childCount()))
    728   {
    729     error = GENOPER_OPFAIL;
    730     errorpos = -1;
    731   }
    732 
    733   // create ancestor cell
    734   C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child,
    735     NULL, 0, stdProps);
    736   nc  = 1;
     705        int res;
     706        repair = nrepair;
     707        error = 0;
     708        errorpos = -1;
     709        repair_remove = NULL;
     710        repair_parent = NULL;
     711        repair_insert = NULL;
     712        tmpcel = NULL;
     713        f4rootnode = NULL;
     714
     715        // transform geno from string to nodes
     716        f4rootnode = new f4_node();
     717        res = f4_processrec((const char*)genome, (unsigned)0, f4rootnode);
     718        if ((res < 0) || (1 != f4rootnode->childCount()))
     719        {
     720                error = GENOPER_OPFAIL;
     721                errorpos = -1;
     722        }
     723
     724        // create ancestor cell
     725        C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child,
     726                NULL, 0, stdProps);
     727        nc = 1;
    737728}
    738729
    739730f4_Cells::~f4_Cells()
    740731{
    741   // release cells
    742   int i;
    743   if (nc)
    744   {
    745     for (i=nc-1; i>=0; i--)
    746       delete C[i];
    747     nc = 0;
    748   }
    749   if (f4rootnode)
    750     delete f4rootnode;
     732        // release cells
     733        int i;
     734        if (nc)
     735        {
     736                for (i = nc - 1; i >= 0; i--)
     737                        delete C[i];
     738                nc = 0;
     739        }
     740        if (f4rootnode)
     741                delete f4rootnode;
    751742}
    752743
     
    754745int f4_Cells::onestep()
    755746{
    756   int i, ret, oldnc, ret2;
    757   oldnc = nc;
    758   ret=0;
    759   for (i=0; i<oldnc; i++) {
    760     ret2 = C[i]->onestep();
    761     if (ret2>0) {
    762       // error
    763       C[i]->active = 0;  // stop
    764       return 0;
    765     }
    766     // if still active
    767     if (C[i]->active)
    768       ret=1;
    769   }
    770   return ret;
     747        int i, ret, oldnc, ret2;
     748        oldnc = nc;
     749        ret = 0;
     750        for (i = 0; i<oldnc; i++) {
     751                ret2 = C[i]->onestep();
     752                if (ret2>0) {
     753                        // error
     754                        C[i]->active = 0;  // stop
     755                        return 0;
     756                }
     757                // if still active
     758                if (C[i]->active)
     759                        ret = 1;
     760        }
     761        return ret;
    771762}
    772763
     
    774765int f4_Cells::simulate()
    775766{
    776   int i;
    777   error = GENOPER_OK;
    778 
    779   for (i=0; i<nc; i++)  C[i]->active = 1;
    780 
    781   // execute onestep() in a cycle
    782   while (onestep()) ;
    783 
    784   if (GENOPER_OK != error) return error;
    785 
    786   // fix neuron attachements
    787   for(i=0; i<nc; i++)
    788     if (C[i]->type == T_NEURON4) {
    789       while (T_NEURON4 == C[i]->dadlink->type) {
    790         C[i]->dadlink = C[i]->dadlink->dadlink;
    791       }
    792   }
    793 
    794   // there should be no undiff. cells
    795   // make undifferentiated cells sticks
    796   for (i=0; i<nc ; i++)
    797     if (C[i]->type == T_UNDIFF4) {
    798       C[i]->type = T_STICK4;
    799       //seterror();
    800   }
    801 
    802   // recursive adjust
    803   // reset recursive traverse flags
    804   for(i=0; i<nc; i++)
    805     C[i]->recProcessedFlag = 0;
    806   // process every cell
    807   for(i=0; i<nc; i++)
    808     C[i]->adjustRec();
    809 
    810   //DB( printf("Cell simulation done, %d cells. \n", nc); )
    811 
    812   return error;
     767        int i;
     768        error = GENOPER_OK;
     769
     770        for (i = 0; i < nc; i++)  C[i]->active = 1;
     771
     772        // execute onestep() in a cycle
     773        while (onestep());
     774
     775        if (GENOPER_OK != error) return error;
     776
     777        // fix neuron attachements
     778        for (i = 0; i < nc; i++)
     779                if (C[i]->type == T_NEURON4) {
     780                        while (T_NEURON4 == C[i]->dadlink->type) {
     781                                C[i]->dadlink = C[i]->dadlink->dadlink;
     782                        }
     783                }
     784
     785        // there should be no undiff. cells
     786        // make undifferentiated cells sticks
     787        for (i = 0; i < nc; i++)
     788                if (C[i]->type == T_UNDIFF4) {
     789                        C[i]->type = T_STICK4;
     790                        //seterror();
     791                }
     792
     793        // recursive adjust
     794        // reset recursive traverse flags
     795        for (i = 0; i < nc; i++)
     796                C[i]->recProcessedFlag = 0;
     797        // process every cell
     798        for (i = 0; i < nc; i++)
     799                C[i]->adjustRec();
     800
     801        //DB( printf("Cell simulation done, %d cells. \n", nc); )
     802
     803        return error;
    813804}
    814805
     
    816807void f4_Cells::addCell(f4_Cell * newcell)
    817808{
    818   if (nc >= MAX4CELLS-1) {
    819     delete newcell;
    820     return;
    821   }
    822   C[nc] = newcell;
    823   nc++;
     809        if (nc >= MAX4CELLS - 1) {
     810                delete newcell;
     811                return;
     812        }
     813        C[nc] = newcell;
     814        nc++;
    824815}
    825816
     
    827818void f4_Cells::setError(int nerrpos)
    828819{
    829   error = GENOPER_OPFAIL;
    830   errorpos = nerrpos;
     820        error = GENOPER_OPFAIL;
     821        errorpos = nerrpos;
    831822}
    832823
    833824void f4_Cells::setRepairRemove(int nerrpos, f4_node * rem)
    834825{
    835   if (!repair) {
    836     // not in repair mode, treat as repairable error
    837     error = GENOPER_REPAIR;
    838     errorpos = nerrpos;
    839   } else {
    840     error = GENOPER_REPAIR;
    841     errorpos = nerrpos;
    842     repair_remove = rem;
    843   }
     826        if (!repair) {
     827                // not in repair mode, treat as repairable error
     828                error = GENOPER_REPAIR;
     829                errorpos = nerrpos;
     830        }
     831        else {
     832                error = GENOPER_REPAIR;
     833                errorpos = nerrpos;
     834                repair_remove = rem;
     835        }
    844836}
    845837
    846838int f4_Cells::setRepairInsert(int nerrpos, f4_node * parent, f4_node * insert)
    847839{
    848   if (!repair) {
    849     // not in repair mode, treat as repairable error
    850     error = GENOPER_REPAIR;
    851     errorpos = nerrpos;
    852     return -1;
    853   } else {
    854     error = GENOPER_REPAIR;
    855     errorpos = nerrpos;
    856     repair_parent = parent;
    857     repair_insert = insert;
    858     return 0;
    859   }
     840        if (!repair) {
     841                // not in repair mode, treat as repairable error
     842                error = GENOPER_REPAIR;
     843                errorpos = nerrpos;
     844                return -1;
     845        }
     846        else {
     847                error = GENOPER_REPAIR;
     848                errorpos = nerrpos;
     849                repair_parent = parent;
     850                repair_insert = insert;
     851                return 0;
     852        }
    860853}
    861854
    862855void f4_Cells::repairGeno(f4_node * geno, int whichchild)
    863856{
    864   // assemble repaired geno, if the case
    865   if (!repair) return;
    866   if ((NULL==repair_remove) && (NULL==repair_insert)) return;
    867   // traverse genotype tree, remove / insert node
    868   f4_node * g2;
    869   if (1==whichchild) g2 = geno->child;
    870     else             g2 = geno->child2;
    871   if (NULL == g2)
    872     return;
    873   if (g2 == repair_remove) {
    874     f4_node * oldgeno;
    875     geno->removeChild(g2);
    876     if (g2->child) {
    877       // add g2->child as child to geno
    878       if (1==whichchild) geno->child = g2->child;
    879         else             geno->child2 = g2->child;
    880       g2->child->parent = geno;
    881     }
    882     oldgeno = g2;
    883     oldgeno->child = NULL;
    884     delete oldgeno;
    885     if (NULL == geno->child) return;
    886     // check this new
    887     repairGeno(geno, whichchild);
    888     return;
    889   }
    890   if (g2 == repair_parent) {
    891     geno->removeChild(g2);
    892     geno->addChild(repair_insert);
    893     repair_insert->parent = geno;
    894     repair_insert->child = g2;
    895     repair_insert->child2 = NULL;
    896     g2->parent = repair_insert;
    897   }
    898   // recurse
    899   if (g2->child)  repairGeno(g2, 1);
    900   if (g2->child2) repairGeno(g2, 2);
     857        // assemble repaired geno, if the case
     858        if (!repair) return;
     859        if ((NULL == repair_remove) && (NULL == repair_insert)) return;
     860        // traverse genotype tree, remove / insert node
     861        f4_node * g2;
     862        if (1 == whichchild) g2 = geno->child;
     863        else             g2 = geno->child2;
     864        if (NULL == g2)
     865                return;
     866        if (g2 == repair_remove) {
     867                f4_node * oldgeno;
     868                geno->removeChild(g2);
     869                if (g2->child) {
     870                        // add g2->child as child to geno
     871                        if (1 == whichchild) geno->child = g2->child;
     872                        else             geno->child2 = g2->child;
     873                        g2->child->parent = geno;
     874                }
     875                oldgeno = g2;
     876                oldgeno->child = NULL;
     877                delete oldgeno;
     878                if (NULL == geno->child) return;
     879                // check this new
     880                repairGeno(geno, whichchild);
     881                return;
     882        }
     883        if (g2 == repair_parent) {
     884                geno->removeChild(g2);
     885                geno->addChild(repair_insert);
     886                repair_insert->parent = geno;
     887                repair_insert->child = g2;
     888                repair_insert->child2 = NULL;
     889                g2->parent = repair_insert;
     890        }
     891        // recurse
     892        if (g2->child)  repairGeno(g2, 1);
     893        if (g2->child2) repairGeno(g2, 2);
    901894}
    902895
     
    904897void f4_Cells::toF1Geno(SString &out)
    905898{
    906   if (tmpcel) delete tmpcel;
    907   tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
    908   out = "";
    909   toF1GenoRec(0, out);
    910   delete tmpcel;
     899        if (tmpcel) delete tmpcel;
     900        tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
     901        out = "";
     902        toF1GenoRec(0, out);
     903        delete tmpcel;
    911904}
    912905
     
    914907void f4_Cells::toF1GenoRec(int curc, SString &out)
    915908{
    916   int i, j, ccount;
    917   f4_Cell * thisti;
    918   f4_Cell * thneu;
    919   char buf[200];
    920 
    921   if (curc >= nc) return;
    922 
    923   if (T_STICK4 != C[curc]->type) return;
    924 
    925   thisti = C[curc];
    926   if (NULL != thisti->dadlink) 
    927     *tmpcel = *(thisti->dadlink);
    928 
    929   // adjust length, curvedness, etc.
    930   tmpcel->P.adjust();
    931   while (tmpcel->P.len > thisti->P.len)
    932   {
    933     tmpcel->P.executeModifier('l');
    934     out += "l";
    935   }
    936   while (tmpcel->P.len < thisti->P.len)
    937   {
    938     tmpcel->P.executeModifier('L');
    939     out += "L";
    940   }
    941   while (tmpcel->P.curv > thisti->P.curv)
    942   {
    943     tmpcel->P.executeModifier('c');
    944     out += "c";
    945   }
    946   while (tmpcel->P.curv < thisti->P.curv)
    947   {
    948     tmpcel->P.executeModifier('C');
    949     out += "C";
    950   }
    951   while (thisti->rolling > 0.0f) {
    952     rolling_dec( &(thisti->rolling) );
    953     out += "R";
    954   }
    955   while (thisti->rolling < 0.0f) {
    956     rolling_inc( &(thisti->rolling) );
    957     out += "r";
    958   }
    959 
    960   // output X for this stick
    961   out += "X";
    962 
    963   // neurons attached to it
    964   for (i=0; i<nc; i++)
    965     if (C[i]->type == T_NEURON4) {
    966       if (C[i]->dadlink == thisti) {
    967         thneu = C[i];
    968         out += "[";
    969         // ctrl
    970         if (1 == thneu->ctrl) out += "@";
    971         if (2 == thneu->ctrl) out += "|";
    972         // links
    973         for (j=0; j<thneu->nolink; j++)
    974         {
    975           if (j) out += ",";
    976           if (NULL == thneu->links[j]->from)
    977           {
    978             // sensory
    979             if (1 == thneu->links[j]->t) out += "*";
    980             if (2 == thneu->links[j]->t) out += "G";
    981             if (3 == thneu->links[j]->t) out += "T";
    982             if (4 == thneu->links[j]->t) out += "S";
    983           } else {
    984             sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
    985             out += buf;
    986           }
    987           out += ":";
    988           // weight
    989           sprintf(buf, "%g", thneu->links[j]->w );
    990           out += buf;
    991         }
    992         out += "]";
    993     }
    994   }
    995 
    996   // sticks connected to it
    997   if (thisti->commacount>=2)
    998     out += "(";
    999 
    1000   ccount=1;
    1001   for (i=0; i<nc; i++)
    1002    if (C[i]->type == T_STICK4)
    1003     if (C[i]->dadlink == thisti) {
    1004       while (ccount < (C[i])->anglepos) {
    1005         ccount++;
    1006         out += ",";
    1007       }
    1008       toF1GenoRec(i, out);
    1009   }
    1010   while (ccount < thisti->commacount) {
    1011     ccount++;
    1012     out += ",";
    1013   }
    1014 
    1015   if (thisti->commacount >= 2)
    1016     out += ")";
     909        int i, j, ccount;
     910        f4_Cell * thisti;
     911        f4_Cell * thneu;
     912        char buf[200];
     913
     914        if (curc >= nc) return;
     915
     916        if (T_STICK4 != C[curc]->type) return;
     917
     918        thisti = C[curc];
     919        if (NULL != thisti->dadlink)
     920                *tmpcel = *(thisti->dadlink);
     921
     922        // adjust length, curvedness, etc.
     923        tmpcel->P.adjust();
     924        while (tmpcel->P.len > thisti->P.len)
     925        {
     926                tmpcel->P.executeModifier('l');
     927                out += "l";
     928        }
     929        while (tmpcel->P.len < thisti->P.len)
     930        {
     931                tmpcel->P.executeModifier('L');
     932                out += "L";
     933        }
     934        while (tmpcel->P.curv > thisti->P.curv)
     935        {
     936                tmpcel->P.executeModifier('c');
     937                out += "c";
     938        }
     939        while (tmpcel->P.curv < thisti->P.curv)
     940        {
     941                tmpcel->P.executeModifier('C');
     942                out += "C";
     943        }
     944        while (thisti->rolling > 0.0f) {
     945                rolling_dec(&(thisti->rolling));
     946                out += "R";
     947        }
     948        while (thisti->rolling < 0.0f) {
     949                rolling_inc(&(thisti->rolling));
     950                out += "r";
     951        }
     952
     953        // output X for this stick
     954        out += "X";
     955
     956        // neurons attached to it
     957        for (i = 0; i < nc; i++)
     958                if (C[i]->type == T_NEURON4) {
     959                        if (C[i]->dadlink == thisti) {
     960                                thneu = C[i];
     961                                out += "[";
     962                                // ctrl
     963                                if (1 == thneu->ctrl) out += "@";
     964                                if (2 == thneu->ctrl) out += "|";
     965                                // links
     966                                for (j = 0; j < thneu->nolink; j++)
     967                                {
     968                                        if (j) out += ",";
     969                                        if (NULL == thneu->links[j]->from)
     970                                        {
     971                                                // sensory
     972                                                if (1 == thneu->links[j]->t) out += "*";
     973                                                if (2 == thneu->links[j]->t) out += "G";
     974                                                if (3 == thneu->links[j]->t) out += "T";
     975                                                if (4 == thneu->links[j]->t) out += "S";
     976                                        }
     977                                        else {
     978                                                sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
     979                                                out += buf;
     980                                        }
     981                                        out += ":";
     982                                        // weight
     983                                        sprintf(buf, "%g", thneu->links[j]->w);
     984                                        out += buf;
     985                                }
     986                                out += "]";
     987                        }
     988                }
     989
     990        // sticks connected to it
     991        if (thisti->commacount >= 2)
     992                out += "(";
     993
     994        ccount = 1;
     995        for (i = 0; i < nc; i++)
     996                if (C[i]->type == T_STICK4)
     997                        if (C[i]->dadlink == thisti) {
     998                                while (ccount < (C[i])->anglepos) {
     999                                        ccount++;
     1000                                        out += ",";
     1001                                }
     1002                                toF1GenoRec(i, out);
     1003                        }
     1004        while (ccount < thisti->commacount) {
     1005                ccount++;
     1006                out += ",";
     1007        }
     1008
     1009        if (thisti->commacount >= 2)
     1010                out += ")";
    10171011}
    10181012
     
    10231017f4_node::f4_node()
    10241018{
    1025   name  = '?';
    1026   parent = NULL;
    1027   child = NULL;
    1028   child2 = NULL;
    1029   pos    = -1;
     1019        name = '?';
     1020        parent = NULL;
     1021        child = NULL;
     1022        child2 = NULL;
     1023        pos = -1;
    10301024}
    10311025
    10321026f4_node::f4_node(char nname, f4_node * nparent, int npos)
    10331027{
    1034   name  = nname;
    1035   parent = nparent;
    1036   child = NULL;
    1037   child2 = NULL;
    1038   pos    = npos;
    1039   if (parent) parent->addChild(this);
     1028        name = nname;
     1029        parent = nparent;
     1030        child = NULL;
     1031        child2 = NULL;
     1032        pos = npos;
     1033        if (parent) parent->addChild(this);
    10401034}
    10411035
    10421036f4_node::~f4_node()
    10431037{
    1044   // (destroy() copied here for efficiency)
    1045   // children are destroyed (recursively) through the destructor
    1046   if (NULL != child2)  delete child2;
    1047   if (NULL != child)   delete child;
     1038        // (destroy() copied here for efficiency)
     1039        // children are destroyed (recursively) through the destructor
     1040        if (NULL != child2)  delete child2;
     1041        if (NULL != child)   delete child;
    10481042}
    10491043
    10501044int f4_node::addChild(f4_node * nchi)
    10511045{
    1052   if (NULL==child) {
    1053     child = nchi;
    1054     return 0;
    1055   }
    1056   if (NULL==child2) {
    1057     child2 = nchi;
    1058     return 0;
    1059   }
    1060   return -1;
     1046        if (NULL == child) {
     1047                child = nchi;
     1048                return 0;
     1049        }
     1050        if (NULL == child2) {
     1051                child2 = nchi;
     1052                return 0;
     1053        }
     1054        return -1;
    10611055}
    10621056
    10631057int f4_node::removeChild(f4_node * nchi)
    10641058{
    1065   if (nchi==child2) {
    1066     child2 = NULL;
    1067     return 0;
    1068   }
    1069   if (nchi==child) {
    1070     child = NULL;
    1071     return 0;
    1072   }
    1073   return -1;
     1059        if (nchi == child2) {
     1060                child2 = NULL;
     1061                return 0;
     1062        }
     1063        if (nchi == child) {
     1064                child = NULL;
     1065                return 0;
     1066        }
     1067        return -1;
    10741068}
    10751069
    10761070int f4_node::childCount()
    10771071{
    1078   if (NULL!=child) {
    1079     if (NULL!=child2) return 2;
    1080                  else return 1;
    1081   } else {
    1082     if (NULL!=child2) return 1;
    1083                  else return 0;
    1084   }
     1072        if (NULL != child) {
     1073                if (NULL != child2) return 2;
     1074                else return 1;
     1075        }
     1076        else {
     1077                if (NULL != child2) return 1;
     1078                else return 0;
     1079        }
    10851080}
    10861081
    10871082int f4_node::count()
    10881083{
    1089   int c=1;
    1090   if (NULL!=child)  c+=child->count();
    1091   if (NULL!=child2) c+=child2->count();
    1092   return c;
     1084        int c = 1;
     1085        if (NULL != child)  c += child->count();
     1086        if (NULL != child2) c += child2->count();
     1087        return c;
    10931088}
    10941089
    10951090f4_node * f4_node::ordNode(int n)
    10961091{
    1097   int n1;
    1098   if (0 == n) return this;
    1099   n--;
    1100   if (NULL != child) {
    1101     n1 = child->count();
    1102     if (n<n1) return child->ordNode(n);
    1103     n -= n1;
    1104   }
    1105   if (NULL != child2) {
    1106     n1 = child2->count();
    1107     if (n<n1) return child2->ordNode(n);
    1108     n -= n1;
    1109   }
    1110   return NULL;
     1092        int n1;
     1093        if (0 == n) return this;
     1094        n--;
     1095        if (NULL != child) {
     1096                n1 = child->count();
     1097                if (n < n1) return child->ordNode(n);
     1098                n -= n1;
     1099        }
     1100        if (NULL != child2) {
     1101                n1 = child2->count();
     1102                if (n < n1) return child2->ordNode(n);
     1103                n -= n1;
     1104        }
     1105        return NULL;
    11111106}
    11121107
    11131108f4_node * f4_node::randomNode()
    11141109{
    1115   int n, i;
    1116   n = count();
    1117   // pick a random node, between 0 and n-1
    1118   i = (int)( ((float)n-0.0001) / RAND_MAX * rand());
    1119   return ordNode(i);
     1110        int n = count();
     1111        // pick a random node, between 0 and n-1
     1112        return ordNode(randomN(n));
    11201113}
    11211114
    11221115f4_node * f4_node::randomNodeWithSize(int min, int max)
    11231116{
    1124   // try random nodes, and accept if size in range
    1125   // limit to maxlim tries
    1126   int i, n, maxlim;
    1127   f4_node * nod = NULL;
    1128   maxlim = count();
    1129   for (i=0; i<maxlim; i++) {
    1130     nod = randomNode();
    1131     n = nod->count();
    1132     if ((n>=min) && (n<=max)) return nod;
    1133   }
    1134   // failed, doesn't matter
    1135   return nod;
     1117        // try random nodes, and accept if size in range
     1118        // limit to maxlim tries
     1119        int i, n, maxlim;
     1120        f4_node * nod = NULL;
     1121        maxlim = count();
     1122        for (i = 0; i < maxlim; i++) {
     1123                nod = randomNode();
     1124                n = nod->count();
     1125                if ((n >= min) && (n <= max)) return nod;
     1126        }
     1127        // failed, doesn't matter
     1128        return nod;
    11361129}
    11371130
    11381131void f4_node::sprint(SString & out)
    11391132{
    1140   char buf2[20];
    1141   // special case: repetition code
    1142   if ('#' == name)
    1143   {
    1144     out += "#";
    1145     if (i1 != 1) {
    1146       sprintf(buf2, "%d", i1);
    1147       out += buf2;
    1148     }
    1149   } else {
    1150   // special case: neuron link
    1151   if ('[' == name) {
    1152     out += "[";
    1153     if (i1>0) {
    1154       // sensor input
    1155       if (1==i1) out += "*";
    1156       if (2==i1) out += "G";
    1157       if (3==i1) out += "T";
    1158       if (4==i1) out += "S";
    1159     } else {
    1160       sprintf(buf2, "%ld", l1);
    1161       out += buf2;
    1162     }
    1163     sprintf(buf2, ":%g]", f1);
    1164     out += buf2;
    1165   } else if (':' == name) {
    1166     sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
    1167     out += buf2;
    1168   } else {
    1169     buf2[0] = name;
    1170     buf2[1] = 0;
    1171     out += buf2;
    1172   }}
    1173   if (NULL != child)     child->sprint(out);
    1174   // if two children, make sure last char is a '>'
    1175   if (2 == childCount())
    1176     if (0 == out[0]) out += ">"; else
    1177       if ('>' != out[out.len()-1]) out += ">";
    1178   if (NULL != child2)    child2->sprint(out);
    1179   // make sure last char is a '>'
    1180   if (0 == out[0]) out += ">"; else
    1181     if ('>' != out[out.len()-1]) out += ">";
     1133        char buf2[20];
     1134        // special case: repetition code
     1135        if ('#' == name)
     1136        {
     1137                out += "#";
     1138                if (i1 != 1) {
     1139                        sprintf(buf2, "%d", i1);
     1140                        out += buf2;
     1141                }
     1142        }
     1143        else {
     1144                // special case: neuron link
     1145                if ('[' == name) {
     1146                        out += "[";
     1147                        if (i1 > 0) {
     1148                                // sensor input
     1149                                if (1 == i1) out += "*";
     1150                                if (2 == i1) out += "G";
     1151                                if (3 == i1) out += "T";
     1152                                if (4 == i1) out += "S";
     1153                        }
     1154                        else {
     1155                                sprintf(buf2, "%ld", l1);
     1156                                out += buf2;
     1157                        }
     1158                        sprintf(buf2, ":%g]", f1);
     1159                        out += buf2;
     1160                }
     1161                else if (':' == name) {
     1162                        sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
     1163                        out += buf2;
     1164                }
     1165                else {
     1166                        buf2[0] = name;
     1167                        buf2[1] = 0;
     1168                        out += buf2;
     1169                }
     1170        }
     1171        if (NULL != child)     child->sprint(out);
     1172        // if two children, make sure last char is a '>'
     1173        if (2 == childCount())
     1174                if (0 == out[0]) out += ">"; else
     1175                        if ('>' != out[out.len() - 1]) out += ">";
     1176        if (NULL != child2)    child2->sprint(out);
     1177        // make sure last char is a '>'
     1178        if (0 == out[0]) out += ">"; else
     1179                if ('>' != out[out.len() - 1]) out += ">";
    11821180}
    11831181
    11841182void f4_node::sprintAdj(char *& buf)
    11851183{
    1186   unsigned int len;
    1187   // build in a SString, with initial size
    1188   SString out(strlen(buf)+2000);
    1189   out="";
    1190 
    1191   sprint(out);
    1192 
    1193   // very last '>' can be omitted
    1194   len = out.len();
    1195   if (len>1)
    1196     if ('>' == out[len-1]) { (out.directWrite())[len-1]=0; out.endWrite();};
    1197   // copy back to string
    1198   // if new is longer, reallocate buf
    1199   if (len+1 > strlen(buf)) {
    1200     buf = (char*) realloc(buf, len+1 );
    1201   }
    1202   strcpy(buf, (const char*) out);
     1184        unsigned int len;
     1185        // build in a SString, with initial size
     1186        SString out(strlen(buf) + 2000);
     1187        out = "";
     1188
     1189        sprint(out);
     1190
     1191        // very last '>' can be omitted
     1192        len = out.len();
     1193        if (len > 1)
     1194                if ('>' == out[len - 1]) { (out.directWrite())[len - 1] = 0; out.endWrite(); };
     1195        // copy back to string
     1196        // if new is longer, reallocate buf
     1197        if (len + 1 > strlen(buf)) {
     1198                buf = (char*)realloc(buf, len + 1);
     1199        }
     1200        strcpy(buf, (const char*)out);
    12031201}
    12041202
    12051203f4_node * f4_node::duplicate()
    12061204{
    1207   f4_node * copy;
    1208   copy = new f4_node(*this);
    1209   copy->parent = NULL;  // set later
    1210   copy->child = NULL;
    1211   copy->child2 = NULL;
    1212   if (NULL != child ) {
    1213     copy->child  = child ->duplicate();
    1214     copy->child ->parent = copy;
    1215   }
    1216   if (NULL != child2 ) {
    1217     copy->child2 = child2->duplicate();
    1218     copy->child2->parent = copy;
    1219   }
    1220   return copy;
     1205        f4_node * copy;
     1206        copy = new f4_node(*this);
     1207        copy->parent = NULL;  // set later
     1208        copy->child = NULL;
     1209        copy->child2 = NULL;
     1210        if (NULL != child) {
     1211                copy->child = child->duplicate();
     1212                copy->child->parent = copy;
     1213        }
     1214        if (NULL != child2) {
     1215                copy->child2 = child2->duplicate();
     1216                copy->child2->parent = copy;
     1217        }
     1218        return copy;
    12211219}
    12221220
     
    12241222void f4_node::destroy()
    12251223{
    1226   // children are destroyed (recursively) through the destructor
    1227   if (NULL != child2)  delete child2;
    1228   if (NULL != child)   delete child;
     1224        // children are destroyed (recursively) through the destructor
     1225        if (NULL != child2)  delete child2;
     1226        if (NULL != child)   delete child;
    12291227}
    12301228
     
    12341232int f4_processrec(const char * genot, unsigned pos0, f4_node * parent)
    12351233{
    1236   int i, j, t, res;
    1237   char tc1, tc2;
    1238   long relfrom;
    1239   double w;
    1240   unsigned gpos, oldpos;
    1241   f4_node * node1, * par;
    1242 
    1243   gpos = pos0;
    1244   par = parent;
    1245   if (gpos >= strlen(genot) ) return 1;
    1246   while (gpos<strlen(genot)) {
    1247     //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
    1248     switch (genot[gpos]) {
    1249     case '<':
    1250       // cell division!
    1251       //DB( printf("  div! %d\n", name); )
    1252 
    1253       // find out genotype start for child
    1254       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
    1255 
    1256       node1 = new f4_node('<', par, gpos);
    1257       par = node1;
    1258       res = f4_processrec(genot, gpos+1,   par);
    1259       if (res) return res;
    1260       if (gpos+j+2 < strlen(genot)) {
    1261         res = f4_processrec(genot, gpos+j+2, par);
    1262         if (res) return res;
    1263       } else {  // ran out
    1264         node1 = new f4_node('>', par, strlen(genot)-1 );
    1265         par = node1;
    1266       }
    1267       // adjustments
    1268       gpos++;
    1269       return 0;  // OK
    1270 
    1271     case '>':
    1272       node1 = new f4_node('>', par, gpos );
    1273       par = node1;
    1274       gpos = strlen(genot);
    1275       return 0;  // OK
    1276 
    1277     case '#':
    1278       // repetition marker, 1 by default
    1279       if (sscanf(genot+gpos, "#%d", &i) != 1) i=1;
    1280       // find out genotype start for continuation
    1281       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), '>');
    1282       // skip number
    1283       oldpos = gpos;
    1284       gpos++;
    1285       while ((genot[gpos]>='0') && (genot[gpos]<='9')) gpos++;
    1286       node1 = new f4_node('#', par, oldpos );
    1287       node1->i1 = i;
    1288       par = node1;
    1289       res = f4_processrec(genot, gpos,   node1);
    1290       if (res) return res;
    1291       if (oldpos+j+2 < strlen(genot) ) {
    1292         res = f4_processrec(genot, oldpos+j+2, node1);
    1293         if (res) return res;
    1294       } else {  // ran out
    1295         node1 = new f4_node('>', par, strlen(genot)-1 );
    1296       }
    1297       return 0;  // OK
    1298 
    1299     // 'simple' nodes:
    1300     case ',':
    1301     case 'l':  case 'L':
    1302     case 'c':  case 'C':
    1303     case 'q':  case 'Q':
    1304     case 'r':  case 'R':
    1305     case 'X':  case 'N':
    1306     case '@':  case '|':
    1307     case 'a':  case 'A':
    1308     case 's':  case 'S':
    1309     case 'm':  case 'M':
    1310     case 'i':  case 'I':
    1311     case 'f':  case 'F':
    1312     case 'w':  case 'W':
    1313     case 'e':  case 'E':
    1314       node1 = new f4_node(genot[gpos], par, gpos );
    1315       par = node1;
    1316       gpos++;
    1317       break;
    1318 
    1319     case '[':
    1320       // link to neuron
    1321       // input (%d, '*', 'G', 'T', 'S')
    1322       t = -1;
    1323       if (sscanf(genot+gpos, "[%ld:%lf]", &relfrom, &w) == 2) t=0;
    1324       else if (sscanf(genot+gpos, "[*:%lf]", &w) == 1) t=1;
    1325       else if (sscanf(genot+gpos, "[G:%lf]", &w) == 1) t=2;
    1326       else if (sscanf(genot+gpos, "[T:%lf]", &w) == 1) t=3;
    1327       else if (sscanf(genot+gpos, "[S:%lf]", &w) == 1) t=4;
    1328       // error: no correct format
    1329       if (t<0) return gpos+1+1;
    1330       node1 = new f4_node('[', par, gpos );
    1331       node1->i1 = t;
    1332       node1->l1 = relfrom;
    1333       node1->f1 = w;
    1334       par = node1;
    1335       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ']');
    1336       gpos += j+2;
    1337       break;
    1338 
    1339     case ':':
    1340       // neuron parameter  +! -! += -= +/ or -/
    1341       if (sscanf(genot+gpos, ":%c%c:", &tc1, &tc2) != 2)
    1342         // error: incorrect format
    1343         return gpos+1+1;
    1344       if ('+' == tc1) j=1;
    1345       else if ('-' == tc1) j=0;
    1346       else return gpos+1+1;
    1347       switch (tc2) {
    1348        case '!':  case '=':  case '/':  break;
    1349        default:
    1350         return gpos+1+1;
    1351       }
    1352       node1 = new f4_node(':', par, gpos );
    1353       node1->l1 = j;
    1354       node1->i1 = (int)tc2;
    1355       par = node1;
    1356       j = scanrec(genot+gpos+1, strlen(genot+gpos+1), ':');
    1357       gpos += j+2;
    1358       break;
    1359 
    1360     case ' ':
    1361     case '\n':
    1362     case '\t':
    1363       // whitespace: ignore
    1364       //node1 = new f4_node(' ', par, gpos );
    1365       //par = node1;
    1366       gpos++;
    1367       break;
    1368 
    1369     default:
    1370       //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
    1371       //add it, build will give the error or repair
    1372       node1 = new f4_node(genot[gpos], par, gpos );
    1373       par = node1;
    1374       gpos++;
    1375       break;
    1376     }
    1377   }
    1378   // should end with a '>'
    1379   if (par)
    1380     if ('>' != par->name) {
    1381       node1 = new f4_node('>', par, strlen(genot)-1 );
    1382       par = node1;
    1383   }
    1384   return 0;  // OK
     1234        int i, j, t, res;
     1235        char tc1, tc2;
     1236        long relfrom;
     1237        double w;
     1238        unsigned gpos, oldpos;
     1239        f4_node * node1, *par;
     1240
     1241        gpos = pos0;
     1242        par = parent;
     1243        if (gpos >= strlen(genot)) return 1;
     1244        while (gpos < strlen(genot)) {
     1245                //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
     1246                switch (genot[gpos]) {
     1247                case '<':
     1248                        // cell division!
     1249                        //DB( printf("  div! %d\n", name); )
     1250
     1251                        // find out genotype start for child
     1252                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
     1253
     1254                        node1 = new f4_node('<', par, gpos);
     1255                        par = node1;
     1256                        res = f4_processrec(genot, gpos + 1, par);
     1257                        if (res) return res;
     1258                        if (gpos + j + 2 < strlen(genot)) {
     1259                                res = f4_processrec(genot, gpos + j + 2, par);
     1260                                if (res) return res;
     1261                        }
     1262                        else {  // ran out
     1263                                node1 = new f4_node('>', par, strlen(genot) - 1);
     1264                                par = node1;
     1265                        }
     1266                        // adjustments
     1267                        gpos++;
     1268                        return 0;  // OK
     1269
     1270                case '>':
     1271                        node1 = new f4_node('>', par, gpos);
     1272                        par = node1;
     1273                        gpos = strlen(genot);
     1274                        return 0;  // OK
     1275
     1276                case '#':
     1277                        // repetition marker, 1 by default
     1278                        if (sscanf(genot + gpos, "#%d", &i) != 1) i = 1;
     1279                        // find out genotype start for continuation
     1280                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
     1281                        // skip number
     1282                        oldpos = gpos;
     1283                        gpos++;
     1284                        while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;
     1285                        node1 = new f4_node('#', par, oldpos);
     1286                        node1->i1 = i;
     1287                        par = node1;
     1288                        res = f4_processrec(genot, gpos, node1);
     1289                        if (res) return res;
     1290                        if (oldpos + j + 2 < strlen(genot)) {
     1291                                res = f4_processrec(genot, oldpos + j + 2, node1);
     1292                                if (res) return res;
     1293                        }
     1294                        else {  // ran out
     1295                                node1 = new f4_node('>', par, strlen(genot) - 1);
     1296                        }
     1297                        return 0;  // OK
     1298
     1299                        // 'simple' nodes:
     1300                case ',':
     1301                case 'l':  case 'L':
     1302                case 'c':  case 'C':
     1303                case 'q':  case 'Q':
     1304                case 'r':  case 'R':
     1305                case 'X':  case 'N':
     1306                case '@':  case '|':
     1307                case 'a':  case 'A':
     1308                case 's':  case 'S':
     1309                case 'm':  case 'M':
     1310                case 'i':  case 'I':
     1311                case 'f':  case 'F':
     1312                case 'w':  case 'W':
     1313                case 'e':  case 'E':
     1314                        node1 = new f4_node(genot[gpos], par, gpos);
     1315                        par = node1;
     1316                        gpos++;
     1317                        break;
     1318
     1319                case '[':
     1320                        // link to neuron
     1321                        // input (%d, '*', 'G', 'T', 'S')
     1322                        t = -1;
     1323                        if (sscanf(genot + gpos, "[%ld:%lf]", &relfrom, &w) == 2) t = 0;
     1324                        else if (sscanf(genot + gpos, "[*:%lf]", &w) == 1) t = 1;
     1325                        else if (sscanf(genot + gpos, "[G:%lf]", &w) == 1) t = 2;
     1326                        else if (sscanf(genot + gpos, "[T:%lf]", &w) == 1) t = 3;
     1327                        else if (sscanf(genot + gpos, "[S:%lf]", &w) == 1) t = 4;
     1328                        // error: no correct format
     1329                        if (t < 0) return gpos + 1 + 1;
     1330                        node1 = new f4_node('[', par, gpos);
     1331                        node1->i1 = t;
     1332                        node1->l1 = relfrom;
     1333                        node1->f1 = w;
     1334                        par = node1;
     1335                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ']');
     1336                        gpos += j + 2;
     1337                        break;
     1338
     1339                case ':':
     1340                        // neuron parameter  +! -! += -= +/ or -/
     1341                        if (sscanf(genot + gpos, ":%c%c:", &tc1, &tc2) != 2)
     1342                                // error: incorrect format
     1343                                return gpos + 1 + 1;
     1344                        if ('+' == tc1) j = 1;
     1345                        else if ('-' == tc1) j = 0;
     1346                        else return gpos + 1 + 1;
     1347                        switch (tc2) {
     1348                        case '!':  case '=':  case '/':  break;
     1349                        default:
     1350                                return gpos + 1 + 1;
     1351                        }
     1352                        node1 = new f4_node(':', par, gpos);
     1353                        node1->l1 = j;
     1354                        node1->i1 = (int)tc2;
     1355                        par = node1;
     1356                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
     1357                        gpos += j + 2;
     1358                        break;
     1359
     1360                case ' ':
     1361                case '\n':
     1362                case '\t':
     1363                        // whitespace: ignore
     1364                        //node1 = new f4_node(' ', par, gpos );
     1365                        //par = node1;
     1366                        gpos++;
     1367                        break;
     1368
     1369                default:
     1370                        //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
     1371                        //add it, build will give the error or repair
     1372                        node1 = new f4_node(genot[gpos], par, gpos);
     1373                        par = node1;
     1374                        gpos++;
     1375                        break;
     1376                }
     1377        }
     1378        // should end with a '>'
     1379        if (par)
     1380                if ('>' != par->name) {
     1381                        node1 = new f4_node('>', par, strlen(genot) - 1);
     1382                        par = node1;
     1383                }
     1384        return 0;  // OK
    13851385}
    13861386
     
    13881388f4_node * f4_processtree(const char * geno)
    13891389{
    1390   f4_node * root;
    1391   int res;
    1392   root = new f4_node();
    1393   res = f4_processrec(geno, 0, root);
    1394   if (res) return NULL;
    1395   //DB( printf("test f4  "); )
    1396   DB(
    1397     if (root->child) {
    1398       char * buf = (char*) malloc( 300 );
    1399       DB( printf("(%d) ", root->child->count() ); )
    1400       buf[0]=0;
    1401       root->child->sprintAdj(buf);
    1402       DB( printf("%s\n", buf); )
    1403       free(buf);
    1404     }
    1405   )
    1406   return root->child;
    1407 }
    1408 
     1390        f4_node * root;
     1391        int res;
     1392        root = new f4_node();
     1393        res = f4_processrec(geno, 0, root);
     1394        if (res) return NULL;
     1395        //DB( printf("test f4  "); )
     1396        DB(
     1397                if (root->child) {
     1398                        char * buf = (char*)malloc(300);
     1399                        DB(printf("(%d) ", root->child->count());)
     1400                                buf[0] = 0;
     1401                        root->child->sprintAdj(buf);
     1402                        DB(printf("%s\n", buf);)
     1403                                free(buf);
     1404                }
     1405        )
     1406                return root->child;
     1407}
Note: See TracChangeset for help on using the changeset viewer.