Ignore:
Timestamp:
03/15/18 22:55:05 (6 years ago)
Author:
Maciej Komosinski
Message:
  • added support for new API for neuron types and their properties
  • added support for checkpoints
File:
1 edited

Legend:

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

    r671 r760  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2017  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
    55// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
     6// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
    67
    78#include "f4_general.h"
     9#include "../oper_fx.h" //for GENOPER_ constants
    810#include <common/nonstd_stl.h>
    911#include <common/log.h>
    1012#include <frams/model/model.h> // for min and max attributes
    11 #include "../oper_fx.h" //for GENOPER_ constants
    12 #include <stdio.h>
    1313#include <common/nonstd_math.h>
    1414
     
    1717#endif
    1818
    19 
    20 f4_Props::f4_Props()
    21 {
    22         length = 1.0;
    23         curvedness = 0.0;
    24         weight = 1.0;
    25         friction = 0.4;
    26         muscle_power = 0.25; // biol
    27         assimilation = 0.25; // biol
    28         stamina = 0.25; // biol
    29         ingestion = 0.25; // biol
    30         twist = 0.0;
    31         energy = 1.0;
    32         normalizeBiol4();
    33 }
    34 
    35 void f4_Props::normalizeBiol4()
    36 {
    37         // make them sum to 1
    38         double sum = muscle_power + assimilation + stamina + ingestion;
    39         if (sum == 0)
    40         {
    41                 muscle_power = assimilation = stamina = ingestion = 0.25;
    42         }
    43         else
    44         {
    45                 muscle_power /= sum;
    46                 assimilation /= sum;
    47                 stamina /= sum;
    48                 ingestion /= sum;
    49         }
    50 }
    51 
    52 void f4_Props::executeModifier(char modif)
    53 {
    54         switch (modif)
    55         {
    56         case 'L': length += (2.5 - length) * 0.3;
    57                 length = min(length, Model::getMaxJoint().d.x); break;
    58         case 'l': length += (0.3 - length) * 0.3;
    59                 length = max(length, Model::getMinJoint().d.x); break;
    60         case 'C': curvedness += (2.0 - curvedness) * 0.25;  break;
    61         case 'c': curvedness += (-2.0 - curvedness) * 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': assimilation += (1 - assimilation) * 0.8; normalizeBiol4(); break;
    65         case 'a': assimilation -= assimilation * 0.4;       normalizeBiol4(); break;
    66         case 'I': ingestion += (1 - ingestion) * 0.8;   normalizeBiol4(); break;
    67         case 'i': ingestion -= ingestion * 0.4;         normalizeBiol4(); break;
    68         case 'S': stamina += (1 - stamina) * 0.8; normalizeBiol4(); break;
    69         case 's': stamina -= stamina * 0.4;       normalizeBiol4(); break;
    70         case 'M': muscle_power += (1 - muscle_power) * 0.8;   normalizeBiol4(); break;
    71         case 'm': muscle_power -= muscle_power * 0.4;         normalizeBiol4(); break;
    72         case 'F': friction += (4 - friction) * 0.2; break;
    73         case 'f': friction -= friction * 0.2;       break;
    74         case 'W': weight += (2.0 - weight) * 0.3;   break;
    75         case 'w': weight += (0.5 - weight) * 0.3;   break;
    76         case 'E': energy += (10.0 - energy) * 0.1; break;
    77         case 'e': energy -= energy * 0.1;          break;
    78         }
    79 }
    80 
    81 void f4_Props::adjust()
    82 {
    83         length = 0.5*length + 0.5*stdProps.length;
    84         curvedness = 0.66 * curvedness;
    85         twist = 0.66 * twist;
    86 }
    87 
    88 f4_Props stdProps;
    89 
    90 
    9119void rolling_dec(double * v)
    9220{
     
    9826        *v += 0.7853;  // 0.7853981  45 degrees
    9927}
    100 
    10128
    10229int scanrec(const char * s, unsigned int slen, char stopchar)
     
    13663
    13764f4_Cell::f4_Cell(int nname,
    138         f4_Cell * ndad, int nangle, f4_Props newP)
     65        f4_Cell * ndad, int nangle, GeneProps newP)
    13966{
    14067        name = nname;
     
    14572        gcur = NULL;
    14673        active = 1;
    147         repeat.null();
     74        repeat.clear();
    14875        //genoRange.clear(); -- implicit
    14976
     
    187114
    188115
    189 f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, f4_Props newP)
     116f4_Cell::f4_Cell(f4_Cells * nO, int nname, f4_node * ngeno, f4_node * ngcur, f4_Cell * ndad, int nangle, GeneProps newP)
    190117{
    191118        name = nname;
     
    196123        gcur = ngcur;
    197124        active = 1;
    198         repeat.null();
     125        repeat.clear();
    199126        //genoRange.clear(); -- implicit
    200127        // preserve geno range of parent cell
     
    261188int f4_Cell::onestep()
    262189{
    263         int i, j, k, relfrom, t;
    264         double w;
    265         f4_Cell * tmp;
    266         f4_Cell * tneu;
    267190        if (gcur == NULL)
    268191        {
     
    275198                // currently this is the last one processed
    276199                // the current genotype code is processed
    277                 genoRange.add(gcur->pos);
    278                 switch (gcur->name)
    279                 {
    280                 case '<':
    281                         // cell division!
    282                         //DB( printf("  div! %d\n", name); )
    283 
    284                         // error: sticks cannot divide
    285                         if (T_STICK4 == type)
    286                         {
    287                                 // cannot fix
    288                                 org->setError(gcur->pos);
    289                                 return 1;  // stop
    290                         }
    291 
    292                         // undiff divides
    293                         if (T_UNDIFF4 == type)
    294                         {
    295                                 // commacount is set only when daughter turns into X
    296                                 // daughter cell
    297                                 // adjust new len
    298                                 f4_Props newP = P;
    299                                 newP.adjust();
    300                                 tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP);
    301                                 tmp->repeat = repeat;
    302                                 repeat.null();
    303                                 org->addCell(tmp);
    304                         }
    305                         // a neuron divides: create a new, duplicate links
    306                         if (T_NEURON4 == type) {
    307                                 // daughter cell
    308                                 tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
    309                                         // has the same dadlink
    310                                         this->dadlink, commacount, P);
    311                                 tmp->repeat = repeat;
    312                                 repeat.null();
    313                                 // it is a neuron from start
    314                                 tmp->type = T_NEURON4;
    315                                 // duplicate links
    316                                 f4_CellLink * ll;
    317                                 for (i = 0; i < nolink; i++)
    318                                 {
    319                                         ll = links[i];
    320                                         tmp->addlink(ll->from, ll->w, ll->t);
    321                                 }
    322                                 org->addCell(tmp);
    323                         }
    324                         // adjustments for this cell
    325                         gcur = gcur->child;
    326                         // halt development
    327                         return 0;
    328 
    329                 case '>':
    330                         // finish
    331                         // see if there is a repet count
    332                         if (repeat.top > 0)
    333                         { // there is a repeat counter
    334                                 if (!repeat.first()->isNull())
    335                                 { // repeat counter is not null
    336                                         repeat.first()->dec();
    337                                         if (repeat.first()->count > 0)
     200                //genoRange.add(gcur->pos,gcur->pos+gcur->name.length()-1);
     201                bool neuclasshandler = false; // if set to true, then there is a set of characters that can be assigned to a neuron class type
     202                // old semantics, one-character
     203                if (gcur->name.length() == 1)
     204                {
     205                        genoRange.add(gcur->pos, gcur->pos);
     206                        char name = gcur->name[0];
     207                        switch (name)
     208                        {
     209                        case '<':
     210                        {
     211                                // cell division!
     212                                //DB( printf("  div! %d\n", name); )
     213
     214                                // error: sticks cannot divide
     215                                if (T_STICK4 == type)
     216                                {
     217                                        // cannot fix
     218                                        org->setError(gcur->pos);
     219                                        return 1;  // stop
     220                                }
     221
     222                                // undiff divides
     223                                if (T_UNDIFF4 == type)
     224                                {
     225                                        // commacount is set only when daughter turns into X
     226                                        // daughter cell
     227                                        // adjust new len
     228                                        GeneProps newP = P;
     229                                        newP.propagateAlong(false);
     230                                        f4_Cell * tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP);
     231                                        tmp->repeat = repeat;
     232                                        repeat.clear();
     233                                        org->addCell(tmp);
     234                                }
     235                                // a neuron divides: create a new, duplicate links
     236                                if (T_NEURON4 == type) {
     237                                        // daughter cell
     238                                        f4_Cell *tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
     239                                                // has the same dadlink
     240                                                this->dadlink, commacount, P);
     241                                        tmp->repeat = repeat;
     242                                        repeat.clear();
     243                                        // it is a neuron from start
     244                                        tmp->type = T_NEURON4;
     245                                        // it has the same type as the parent neuron
     246                                        tmp->neuclass = neuclass;
     247                                        // duplicate links
     248                                        f4_CellLink * ll;
     249                                        for (int i = 0; i < nolink; i++)
    338250                                        {
    339                                                 // return to repeat
    340                                                 gcur = repeat.first()->node->child;
     251                                                ll = links[i];
     252                                                tmp->addlink(ll->from, ll->w, ll->t);
     253                                        }
     254                                        org->addCell(tmp);
     255                                }
     256                                // adjustments for this cell
     257                                gcur = gcur->child;
     258                                // halt development
     259                                return 0;
     260                        }
     261                        case '>':
     262                        {
     263                                // finish
     264                                // see if there is a repet count
     265                                if (repeat.top > 0)
     266                                { // there is a repeat counter
     267                                        if (!repeat.first()->isNull())
     268                                        { // repeat counter is not null
     269                                                repeat.first()->dec();
     270                                                if (repeat.first()->count > 0)
     271                                                {
     272                                                        // return to repeat
     273                                                        gcur = repeat.first()->node->child;
     274                                                }
     275                                                else
     276                                                {
     277                                                        // continue
     278                                                        gcur = repeat.first()->node->child2;
     279                                                        repeat.pop();
     280                                                }
     281                                                break;
    341282                                        }
    342283                                        else
    343284                                        {
    344                                                 // continue
    345                                                 gcur = repeat.first()->node->child2;
    346285                                                repeat.pop();
    347286                                        }
     287                                }
     288                                else
     289                                {
     290                                        // error: still undiff
     291                                        if (T_UNDIFF4 == type)
     292                                        {
     293                                                // fix it: insert an 'X'
     294                                                f4_node *insertnode = new f4_node("X", NULL, gcur->pos);
     295                                                if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release
     296                                                        delete insertnode;
     297                                                return 1;
     298                                        }
     299                                        repeat.clear();
     300                                        active = 0;  // stop
     301                                        // eat up rest
     302                                        gcur = NULL;
     303                                        return 0;
     304                                }
     305                        }
     306                                /* no break */
     307                        case '#':
     308                        {
     309                                // repetition marker
     310                                if (repeat.top >= repeat_stack::stackSize)
     311                                {
     312                                        // repeat pointer stack is full, cannot remember this one.
     313                                        // fix: delete it
     314                                        org->setRepairRemove(gcur->pos, gcur);
     315                                        return 1;  // stop
     316                                }
     317                                repeat.push(repeat_ptr(gcur, gcur->i1));
     318                                gcur = gcur->child;
     319                                break;
     320                        }
     321                        case ',':
     322                        {
     323                                commacount++;
     324                                gcur = gcur->child;
     325                                break;
     326                        }
     327                        case 'r':  case 'R':
     328                        {
     329                                // error: if neuron
     330                                if (T_NEURON4 == type)
     331                                {
     332                                        // fix: delete it
     333                                        org->setRepairRemove(gcur->pos, gcur);
     334                                        return 1;  // stop
     335                                }
     336                                switch (name)
     337                                {
     338                                case 'r':   rolling_dec(&rolling); break;
     339                                case 'R':   rolling_inc(&rolling); break;
     340                                }
     341                                gcur = gcur->child;
     342                                break;
     343                        }
     344                        case 'l':  case 'L':
     345                        case 'c':  case 'C':
     346                        case 'q':  case 'Q':
     347                        case 'a':  case 'A':
     348                        case 'i':  case 'I':
     349                        case 's':  case 'S':
     350                        case 'm':  case 'M':
     351                        case 'f':  case 'F':
     352                        case 'w':  case 'W':
     353                        case 'e':  case 'E':
     354                        case 'd':  case 'D':
     355                        case 'g':  case 'G':
     356                        case 'b':  case 'B':
     357                        case 'h':  case 'H':
     358                        {
     359                                // error: if neuron
     360                                if (T_NEURON4 == type)
     361                                {
     362                                        // fix: delete it
     363                                        org->setRepairRemove(gcur->pos, gcur);
     364                                        return 1;  // stop
     365                                }
     366                                P.executeModifier(name);
     367                                gcur = gcur->child;
     368                                break;
     369                        }
     370                        case 'X':
     371                        {
     372                                // turn undiff. cell into a stick
     373                                // error: already differentiated
     374                                if (T_UNDIFF4 != type)
     375                                {
     376                                        // fix: delete this node
     377                                        org->setRepairRemove(gcur->pos, gcur);
     378                                        return 1;  // stop
     379                                }
     380                                type = T_STICK4;
     381                                // fix dad commacount and own anglepos
     382                                if (NULL != dadlink)
     383                                {
     384                                        dadlink->commacount++;
     385                                        anglepos = dadlink->commacount;
     386                                }
     387                                // change of type halts developments, see comment at 'N'
     388                                gcur = gcur->child;
     389                                return 0;
     390                        }
     391                        case 'N':
     392                        {
     393                                // turn undiff. cell into a neuron
     394                                // error: already differentiated
     395                                if (T_UNDIFF4 != type)
     396                                {
     397                                        // fix: delete this node
     398                                        org->setRepairRemove(gcur->pos, gcur);
     399                                        return 1;  // stop
     400                                }
     401                                // error: if no previous
     402                                if (NULL == dadlink)
     403                                {
     404                                        // fix: delete it
     405                                        org->setRepairRemove(gcur->pos, gcur);
     406                                        return 1;  // stop
     407                                }
     408                                string temp1 = "N";
     409                                char *temp = (char*)temp1.c_str();
     410                                neuclass = GenoOperators::parseNeuroClass(temp);
     411                                type = T_NEURON4;
     412                                // change of type also halts development, to give other
     413                                // cells a chance for adjustment.  Namely, it is important
     414                                // to wait for other cells to turn N before adding links
     415                                gcur = gcur->child;
     416                                return 0;
     417                        }
     418                        case '@':
     419                        case '|':
     420                        {
     421                                // neuron rotating / bending
     422                                int j = 1;
     423                                if ('@' == name) j = 1; // rot
     424                                else
     425                                        if ('|' == name) j = 2; // bend
     426
     427                                // if undiff, then this is a new muscle. Thanks to f4_processrec @ and | case we can skip repairing
     428                                if (T_UNDIFF4 == type)
     429                                {
     430                                        neuclasshandler = true;
    348431                                        break;
    349432                                }
    350                                 else
    351                                 {
    352                                         repeat.pop();
    353                                 }
    354                         }
    355                         else
    356                         {
    357                                 // error: still undiff
    358                                 if (T_UNDIFF4 == type)
    359                                 {
    360                                         // fix it: insert an 'X'
    361                                         f4_node * insertnode = new f4_node('X', NULL, gcur->pos);
    362                                         if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release                                           
    363                                                 delete insertnode;
    364                                         return 1;
    365                                 }
    366                                 repeat.null();
    367                                 active = 0;  // stop
    368                                 // eat up rest
    369                                 gcur = NULL;
    370                                 return 0;
    371                         }
    372 
    373                 case '#':
    374                         // repetition marker
    375                         if (repeat.top >= repeat_stack::stackSize)
    376                         {
    377                                 // repepeat pointer stack is full, cannot remember this one.
     433
     434                                // error: not a neuron (stick)
     435                                if (T_NEURON4 != type)
     436                                {
     437                                        // fix: delete it
     438                                        org->setRepairRemove(gcur->pos, gcur);
     439                                        return 1;  // stop
     440                                }
     441                                // error: already has control
     442                                if (ctrl != 0)
     443                                {
     444                                        // fix: delete it
     445                                        org->setRepairRemove(gcur->pos, gcur);
     446                                        return 1;  // stop
     447                                }
     448                                // make neuron ctrl = 1 or 2
     449                                ctrl = j;
     450                                gcur = gcur->child;
     451                                break;
     452                        }
     453                        case '[':
     454                        {
     455                                // link to neuron
     456                                // error: not a neuron
     457                                if (T_NEURON4 != type)
     458                                {
     459                                        // fix: delete it
     460                                        org->setRepairRemove(gcur->pos, gcur);
     461                                        return 1;  // stop
     462                                }
     463                                // input (sensor or %d)
     464                                int t = gcur->i1;
     465                                int relfrom = gcur->l1;
     466                                float w = gcur->f1;
     467                                f4_Cell *tneu = NULL;
     468                                if (t > 0) // sensors
     469                                {
     470                                        char *temp = (char*)gcur->s1.c_str();
     471                                        NeuroClass *sensortest = GenoOperators::parseNeuroClass(temp);
     472                                        if (sensortest == NULL || sensortest->getPreferredInputs() != 0)
     473                                        {
     474                                                // error: unknown code
     475                                                string buf = "wrong sensor in link '";
     476                                                buf.append(gcur->s1);
     477                                                buf.append("'");
     478                                                logMessage("f4_Cell", "onestep", LOG_WARN, buf.c_str()); //TODO ask
     479                                                org->setRepairRemove(gcur->pos, gcur);
     480                                                return 1;
     481                                        }
     482                                }
     483                                else {
     484                                        // input from other neuron
     485                                        // find neuron at relative i
     486                                        // find own index
     487                                        int j = 0, k = 0;
     488                                        for (int i = 0; i < org->nc; i++)
     489                                        {
     490                                                if (org->C[i]->type == T_NEURON4) k++;
     491                                                if (org->C[i] == this) { j = k - 1; break; }
     492                                        }
     493                                        // find index of incoming
     494                                        j = j + relfrom;
     495                                        if (j < 0) goto wait_link;
     496                                        if (j >= org->nc) goto wait_link;
     497                                        // find that neuron
     498                                        k = 0;
     499                                        int i;
     500                                        for (i = 0; i < org->nc; i++)
     501                                        {
     502                                                if (org->C[i]->type == T_NEURON4) k++;
     503                                                if (j == (k - 1)) break;
     504                                        }
     505                                        if (i >= org->nc) goto wait_link;
     506                                        tneu = org->C[i];
     507                                }
     508                                // add link
     509                                // error: could not add link (too many?)
     510                                if (addlink(tneu, w, gcur->s1))
     511                                {
     512                                        // cannot fix
     513                                        org->setError(gcur->pos);
     514                                        return 1;  // stop
     515                                }
     516                                gcur = gcur->child;
     517                                break;
     518                        }
     519                        wait_link:
     520                        {
     521                                // wait for other neurons to develop
     522                                // if there are others still active
     523                                active = 0;
     524                                int j = 0;
     525                                for (int i = 0; i < org->nc; i++)
     526                                {
     527                                        if (org->C[i]->active) j++;
     528                                }
     529                                if (j > 0)
     530                                        return 0;  // there is other active, halt, try again
     531                                // no more actives, cannot add link, ignore, but treat not as an error
     532                                gcur = gcur->child;
     533                        }
     534                                break;
     535                        case ':':
     536                        {
     537                                // neuron parameter
     538                                // error: not a neuron
     539                                if (T_NEURON4 != type)
     540                                {
     541                                        // fix: delete it
     542                                        org->setRepairRemove(gcur->pos, gcur);
     543                                        return 1;  // stop
     544                                }
     545                                int j = (int)gcur->l1;
     546                                switch ((char)gcur->i1)
     547                                {
     548                                case '!':
     549                                        if (j)
     550                                                force += (1.0 - force) * 0.2;
     551                                        else
     552                                                force -= force * 0.2;
     553                                        break;
     554                                case '=':
     555                                        if (j)
     556                                                inertia += (1.0 - inertia) * 0.2;
     557                                        else
     558                                                inertia -= inertia * 0.2;
     559                                        break;
     560                                case '/':
     561                                        if (j)
     562                                                sigmo *= 1.4;
     563                                        else
     564                                                sigmo /= 1.4;
     565                                        break;
     566                                default:
     567                                        org->setRepairRemove(gcur->pos, gcur);
     568                                        return 1;  // stop
     569                                }
     570                                gcur = gcur->child;
     571                                break;
     572                        }
     573                        case ' ':
     574                        {
     575                                // space has no effect, should not occur
     576                                // fix: delete it
     577                                org->setRepairRemove(gcur->pos, gcur);
     578                                gcur = gcur->child;
     579                                break;
     580                        }
     581                        default:
     582                        {
     583                                // because there are one-character neuron classes, default move control to neuclasshandler
     584                                neuclasshandler = true;
     585                        }
     586                        }
     587                }
     588                else
     589                {
     590                        // if many characters, then it needs to be parsed below
     591                        neuclasshandler = true;
     592                }
     593
     594                if (neuclasshandler)
     595                {
     596                        genoRange.add(gcur->pos, gcur->pos + gcur->name.length() + 2 - 1); // +2 for N:
     597                        if (T_UNDIFF4 != type)
     598                        {
     599                                // fix: delete this node
     600                                org->setRepairRemove(gcur->pos, gcur);
     601                                return 1;  // stop
     602                        }
     603                        // error: if no previous
     604                        if (NULL == dadlink)
     605                        {
    378606                                // fix: delete it
    379607                                org->setRepairRemove(gcur->pos, gcur);
    380608                                return 1;  // stop
    381609                        }
    382                         repeat.push(repeat_ptr(gcur, gcur->i1));
     610                        // multiple characters are neuron types. Need to check if exists
     611                        char *temp = (char*)gcur->name.c_str();
     612                        neuclass = GenoOperators::parseNeuroClass(temp);
     613                        if (neuclass == NULL)
     614                        {
     615                                // error: unknown code
     616                                string buf = "unknown code '";
     617                                buf.append(gcur->name);
     618                                buf.append("'");
     619                                logMessage("f4_Cell", "onestep", 2, buf.c_str());
     620                                org->setRepairRemove(gcur->pos, gcur);
     621                                return 1;
     622                        }
     623                        type = T_NEURON4; //they belong to neurons
    383624                        gcur = gcur->child;
    384                         break;
    385 
    386                 case ',':
    387                         commacount++;
    388                         gcur = gcur->child;
    389                         break;
    390 
    391                 case 'r':  case 'R':
    392                         // error: if neuron
    393                         if (T_NEURON4 == type)
    394                         {
    395                                 // fix: delete it
    396                                 org->setRepairRemove(gcur->pos, gcur);
    397                                 return 1;  // stop
    398                         }
    399                         switch (gcur->name)
    400                         {
    401                         case 'r':   rolling_dec(&rolling); break;
    402                         case 'R':   rolling_inc(&rolling); break;
    403                         }
    404                         gcur = gcur->child;
    405                         break;
    406 
    407                 case 'l':  case 'L':
    408                 case 'c':  case 'C':
    409                 case 'q':  case 'Q':
    410                 case 'a':  case 'A':
    411                 case 'i':  case 'I':
    412                 case 's':  case 'S':
    413                 case 'm':  case 'M':
    414                 case 'f':  case 'F':
    415                 case 'w':  case 'W':
    416                 case 'e':  case 'E':
    417                         // error: if neuron
    418                         if (T_NEURON4 == type)
    419                         {
    420                                 // fix: delete it
    421                                 org->setRepairRemove(gcur->pos, gcur);
    422                                 return 1;  // stop
    423                         }
    424                         P.executeModifier(gcur->name);
    425                         gcur = gcur->child;
    426                         break;
    427 
    428                 case 'X':
    429                         // turn undiff. cell into a stick
    430                         // error: already differentiated
    431                         if (T_UNDIFF4 != type)
    432                         {
    433                                 // fix: delete this node
    434                                 org->setRepairRemove(gcur->pos, gcur);
    435                                 return 1;  // stop
    436                         }
    437                         type = T_STICK4;
    438                         // fix dad commacount and own anglepos
    439                         if (NULL != dadlink)
    440                         {
    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                         {
    453                                 // fix: delete this node
    454                                 org->setRepairRemove(gcur->pos, gcur);
    455                                 return 1;  // stop
    456                         }
    457                         // error: if no previous
    458                         if (NULL == dadlink)
    459                         {
    460                                 // fix: delete it
    461                                 org->setRepairRemove(gcur->pos, gcur);
    462                                 return 1;  // stop
    463                         }
    464                         type = T_NEURON4;
    465                         // change of type also halts development, to give other
    466                         // cells a chance for adjustment.  Namely, it is important
    467                         // to wait for other cells to turn N before adding links
    468                         gcur = gcur->child;
    469                         return 0;
    470 
    471                 case '@':
    472                 case '|':
    473                         // neuron rotating / bending
    474                         j = 1;
    475                         if ('@' == gcur->name) j = 1; // rot
    476                         if ('|' == gcur->name) j = 2; // bend
    477                         // error: not a neuron (undiff)
    478                         if (T_UNDIFF4 == type)
    479                         {
    480                                 // fix: delete it
    481                                 org->setRepairRemove(gcur->pos, gcur);
    482                                 return 1;  // stop
    483                         }
    484                         // error: not a neuron (stick)
    485                         if (T_NEURON4 != type)
    486                         {
    487                                 // fix: delete it
    488                                 org->setRepairRemove(gcur->pos, gcur);
    489                                 return 1;  // stop
    490                         }
    491                         // error: already has control
    492                         if (ctrl != 0)
    493                         {
    494                                 // fix: delete it
    495                                 org->setRepairRemove(gcur->pos, gcur);
    496                                 return 1;  // stop
    497                         }
    498                         // make neuron ctrl = 1 or 2
    499                         ctrl = j;
    500                         gcur = gcur->child;
    501                         break;
    502 
    503                 case '[':
    504                         // link to neuron
    505                         // error: not a neuron
    506                         if (T_NEURON4 != type)
    507                         {
    508                                 // fix: delete it
    509                                 org->setRepairRemove(gcur->pos, gcur);
    510                                 return 1;  // stop
    511                         }
    512                         // input ('*', 'G', 'T', 'S', or %d)
    513                         t = gcur->i1;
    514                         relfrom = gcur->l1;
    515                         w = gcur->f1;
    516                         if (t > 0)
    517                         {
    518                                 // * or G
    519                                 tneu = NULL;
    520                         }
    521                         else {
    522                                 // input from other neuron
    523                                 // find neuron at relative i
    524                                 // find own index
    525                                 j = 0; k = 0;
    526                                 for (i = 0; i < org->nc; i++)
    527                                 {
    528                                         if (org->C[i]->type == T_NEURON4) k++;
    529                                         if (org->C[i] == this) { j = k - 1; break; }
    530                                 }
    531                                 // find index of incoming
    532                                 j = j + relfrom;
    533                                 if (j < 0) goto wait_link;
    534                                 if (j >= org->nc) goto wait_link;
    535                                 // find that neuron
    536                                 k = 0;
    537                                 for (i = 0; i < org->nc; i++)
    538                                 {
    539                                         if (org->C[i]->type == T_NEURON4) k++;
    540                                         if (j == (k - 1)) break;
    541                                 }
    542                                 if (i >= org->nc) goto wait_link;
    543                                 tneu = org->C[i];
    544                         }
    545                         // add link
    546                         // error: could not add link (too many?)
    547                         if (addlink(tneu, w, t))
    548                         {
    549                                 // cannot fix
    550                                 org->setError(gcur->pos);
    551                                 return 1;  // stop
    552                         }
    553                         gcur = gcur->child;
    554                         break;
    555                 wait_link:
    556                         // wait for other neurons to develop
    557                         // if there are others still active
    558                         active = 0;
    559                         j = 0;
    560                         for (i = 0; i < org->nc; i++)
    561                         {
    562                                 if (org->C[i]->active) j++;
    563                         }
    564                         if (j > 0)
    565                                 return 0;  // there is other active, halt, try again
    566                         // no more actives, cannot add link, ignore, but treat not as an error
    567                         gcur = gcur->child;
    568                         break;
    569 
    570                 case ':':
    571                         // neuron parameter
    572                         // error: not a neuron
    573                         if (T_NEURON4 != type)
    574                         {
    575                                 // fix: delete it
    576                                 org->setRepairRemove(gcur->pos, gcur);
    577                                 return 1;  // stop
    578                         }
    579                         j = (int)gcur->l1;
    580                         switch ((char)gcur->i1)
    581                         {
    582                         case '!':
    583                                 if (j) force += (1.0 - force) * 0.2;
    584                                 else   force -= force * 0.2; break;
    585                         case '=':
    586                                 if (j) inertia += (1.0 - inertia) * 0.2;
    587                                 else   inertia -= inertia * 0.2; break;
    588                         case '/':
    589                                 if (j) sigmo *= 1.4;
    590                                 else   sigmo /= 1.4; break;
    591                         default:
    592                                 org->setRepairRemove(gcur->pos, gcur);
    593                                 return 1;  // stop
    594                         }
    595                         gcur = gcur->child;
    596                         break;
    597 
    598                 case ' ':
    599                         // space has no effect, should not occur
    600                         // fix: delete it
    601                         org->setRepairRemove(gcur->pos, gcur);
    602                         gcur = gcur->child;
    603                         break;
    604 
    605                 default:
    606                         // error: unknown code
    607                         char buf[40];
    608                         sprintf(buf, "unknown code '%c'", gcur->name);
    609                         logMessage("f4_Cell", "onestep", 2, buf);
    610                         // fix: delete it
    611                         org->setRepairRemove(gcur->pos, gcur);
    612                         return 1; // stop
     625                        return 0; //stop
    613626                }
    614627        }
     
    618631
    619632
    620 int f4_Cell::addlink(f4_Cell * nfrom, double nw, int nt)
    621 {
     633int f4_Cell::addlink(f4_Cell * nfrom, double nw, string nt)
     634{
     635        // if incoming neuron does not produce output, return error
     636        if (nfrom != NULL && nfrom->neuclass->getPreferredOutput() == 0) return -1;
     637        if (neuclass->getPreferredInputs() != -1 && nolink >= neuclass->getPreferredInputs()) return -1;
    622638        if (nolink >= MAXINPUTS - 1) return -1; // full!
    623639        links[nolink] = new f4_CellLink(nfrom, nw, nt);
     
    664680                {
    665681                        //firstend = dadlink->lastend;
    666                         f4_Props Pdad = dadlink->P;
    667                         f4_Props Padj = Pdad;
    668                         Padj.adjust();
     682                        GeneProps Pdad = dadlink->P;
     683                        GeneProps Padj = Pdad;
     684                        Padj.propagateAlong(false);
    669685
    670686                        //rot = Orient_1;
     
    700716
    701717
    702 f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, int nt)
     718f4_CellLink::f4_CellLink(f4_Cell * nfrom, double nw, string nt)
    703719{
    704720        from = nfrom;
     
    720736        tmpcel = NULL;
    721737        f4rootnode = NULL;
    722 
    723         C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, stdProps);
     738        C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values);
    724739        nc = 1;
    725740}
     
    748763
    749764        // create ancestor cell
    750         C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, stdProps);
     765        C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, GeneProps::standard_values);
    751766        nc = 1;
    752767}
     
    939954{
    940955        if (tmpcel) delete tmpcel;
    941         tmpcel = new f4_Cell(-1, NULL, 0, stdProps);
     956        tmpcel = new f4_Cell(-1, NULL, 0, GeneProps::standard_values);
    942957        out = "";
    943958        toF1GenoRec(0, out);
     
    962977
    963978        // adjust length, curvedness, etc.
    964         tmpcel->P.adjust();
     979        tmpcel->P.propagateAlong(false);
    965980        while (tmpcel->P.length > thisti->P.length)
    966981        {
     
    10151030                                        if (NULL == thneu->links[j]->from)
    10161031                                        {
    1017                                                 // sensory
    1018                                                 if (1 == thneu->links[j]->t) out += "*";
    1019                                                 if (2 == thneu->links[j]->t) out += "G";
    1020                                                 if (3 == thneu->links[j]->t) out += "T";
    1021                                                 if (4 == thneu->links[j]->t) out += "S";
     1032                                                // sensors
     1033                                                out += thneu->links[j]->t.c_str();
    10221034                                        }
    10231035                                        else
     
    10731085f4_node::f4_node()
    10741086{
    1075         name = '?';
     1087        name = "?";
    10761088        parent = NULL;
    10771089        child = NULL;
    10781090        child2 = NULL;
    10791091        pos = -1;
    1080 }
    1081 
    1082 f4_node::f4_node(char nname, f4_node * nparent, int npos)
     1092        l1 = 0;
     1093        i1 = 0;
     1094        f1 = 0.0f;
     1095}
     1096
     1097f4_node::f4_node(string nname, f4_node *nparent, int npos)
    10831098{
    10841099        name = nname;
     
    10881103        pos = npos;
    10891104        if (parent) parent->addChild(this);
     1105        l1 = 0;
     1106        i1 = 0;
     1107        f1 = 0.0f;
     1108}
     1109
     1110f4_node::f4_node(char nname, f4_node * nparent, int npos)
     1111{
     1112        name = nname;
     1113        parent = nparent;
     1114        child = NULL;
     1115        child2 = NULL;
     1116        pos = npos;
     1117        if (parent) parent->addChild(this);
     1118        l1 = 0;
     1119        i1 = 0;
     1120        f1 = 0.0f;
    10901121}
    10911122
     
    11941225}
    11951226
    1196 void f4_node::sprint(SString & out)
    1197 {
    1198         char buf2[20];
     1227void f4_node::sprint(SString& out)
     1228{
     1229        string buf2 = "";
    11991230        // special case: repetition code
    1200         if ('#' == name)
     1231        if (name == "#")
    12011232        {
    12021233                out += "#";
    12031234                if (i1 != 1)
    12041235                {
    1205                         sprintf(buf2, "%d", i1);
    1206                         out += buf2;
     1236                        sprintf((char*)buf2.c_str(), "%d", i1);
     1237                        out += buf2.c_str();
    12071238                }
    12081239        }
    12091240        else {
    12101241                // special case: neuron link
    1211                 if ('[' == name)
     1242                if (name == "[")
    12121243                {
    12131244                        out += "[";
     
    12151246                        {
    12161247                                // sensor input
    1217                                 if (1 == i1) out += "*";
    1218                                 if (2 == i1) out += "G";
    1219                                 if (3 == i1) out += "T";
    1220                                 if (4 == i1) out += "S";
     1248                                out += s1.c_str();
    12211249                        }
    12221250                        else
    12231251                        {
    1224                                 sprintf(buf2, "%ld", l1);
    1225                                 out += buf2;
    1226                         }
    1227                         sprintf(buf2, ":%g]", f1);
    1228                         out += buf2;
    1229                 }
    1230                 else if (':' == name)
    1231                 {
    1232                         sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
    1233                         out += buf2;
     1252                                sprintf((char*)buf2.c_str(), "%ld", l1);
     1253                                out += buf2.c_str();
     1254                        }
     1255                        sprintf((char*)buf2.c_str(), ":%g]", f1);
     1256                        out += buf2.c_str();
     1257                }
     1258                else if (name == ":")
     1259                {
     1260                        sprintf((char*)buf2.c_str(), ":%c%c:", l1 ? '+' : '-', (char)i1);
     1261                        out += buf2.c_str();
     1262                }
     1263                else if (name == "@" || name == "|")
     1264                {
     1265                        if (parent->name == "N")
     1266                        {
     1267                                buf2 = name;
     1268                                out += buf2.c_str();
     1269                        }
     1270                        else
     1271                        {
     1272                                out += "N:";
     1273                                buf2 = name;
     1274                                out += buf2.c_str();
     1275                        }
    12341276                }
    12351277                else
    12361278                {
    1237                         buf2[0] = name;
    1238                         buf2[1] = 0;
    1239                         out += buf2;
     1279                        char *temp = (char*)name.c_str();
     1280                        NeuroClass * nc = GenoOperators::parseNeuroClass(temp);
     1281                        if (nc != NULL)
     1282                        {
     1283                                out += "N:";
     1284                        }
     1285                        buf2 = name;
     1286                        out += buf2.c_str();
    12401287                }
    12411288        }
     
    13011348}
    13021349
    1303 
    13041350// scan genotype string and build tree
    13051351// return >1 for error (errorpos)
    13061352int f4_processrec(const char * genot, unsigned pos0, f4_node * parent)
    13071353{
    1308         int i, j, t, res;
    1309         char tc1, tc2;
     1354        int i, j, res, t;
     1355        char tc1, tc2, tc3; // tc3 is only to ensure that in the end  of neuron parameter definition
    13101356        int relfrom;
    13111357        double w;
    13121358        unsigned gpos, oldpos;
    13131359        f4_node * node1, *par;
     1360        unsigned beginindex;
     1361        string neutype = "";
    13141362
    13151363        gpos = pos0;
     
    13181366        while (gpos < strlen(genot))
    13191367        {
    1320                 //DB( printf(" processing '%c' %d %s\n", genot[gpos], gpos, genot); )
     1368                neutype = "";
     1369                // first switch across cell dividers and old semantics
    13211370                switch (genot[gpos])
    13221371                {
    13231372                case '<':
    1324                         // cell division!
    1325                         //DB( printf("  div! %d\n", name); )
    1326 
     1373                {
    13271374                        // find out genotype start for child
    13281375                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
    13291376
    1330                         node1 = new f4_node('<', par, gpos);
     1377                        node1 = new f4_node("<", par, gpos);
    13311378                        par = node1;
    13321379                        res = f4_processrec(genot, gpos + 1, par);
     
    13391386                        else // ran out
    13401387                        {
    1341                                 node1 = new f4_node('>', par, strlen(genot) - 1);
     1388                                node1 = new f4_node(">", par, strlen(genot) - 1);
    13421389                                par = node1;
    13431390                        }
    1344                         // adjustments
    13451391                        gpos++;
    13461392                        return 0;  // OK
    1347 
     1393                }
    13481394                case '>':
    1349                         node1 = new f4_node('>', par, gpos);
     1395                {
     1396                        node1 = new f4_node(">", par, gpos);
    13501397                        par = node1;
    13511398                        gpos = strlen(genot);
    13521399                        return 0;  // OK
    1353 
     1400                }
    13541401                case '#':
     1402                {
    13551403                        // repetition marker, 1 by default
    13561404                        if (sscanf(genot + gpos, "#%d", &i) != 1) i = 1;
     
    13611409                        gpos++;
    13621410                        while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;
    1363                         node1 = new f4_node('#', par, oldpos);
     1411                        node1 = new f4_node("#", par, oldpos);
    13641412                        node1->i1 = i;
    13651413                        par = node1;
     
    13731421                        else // ran out
    13741422                        {
    1375                                 node1 = new f4_node('>', par, strlen(genot) - 1);
     1423                                node1 = new f4_node(">", par, strlen(genot) - 1);
    13761424                        }
    13771425                        return 0;  // OK
    1378 
    1379                         // 'simple' nodes:
    1380                 case ',':
     1426                }
     1427                case ' ':
     1428                case '\n':
     1429                case '\r':
     1430                case '\t':
     1431                {
     1432                        // whitespace: ignore
     1433                        gpos++;
     1434                        break;
     1435                }
    13811436                case 'l':  case 'L':
    13821437                case 'c':  case 'C':
    13831438                case 'q':  case 'Q':
    13841439                case 'r':  case 'R':
    1385                 case 'X':  case 'N':
    1386                 case '@':  case '|':
     1440                case 'X':  case ',':
    13871441                case 'a':  case 'A':
    13881442                case 's':  case 'S':
     
    13921446                case 'w':  case 'W':
    13931447                case 'e':  case 'E':
     1448                {
    13941449                        node1 = new f4_node(genot[gpos], par, gpos);
    13951450                        par = node1;
    13961451                        gpos++;
    13971452                        break;
    1398 
     1453                }
     1454                case '@':  case '|':
     1455                {
     1456                        // in order to prevent the presence of "free muscles", we need to ensure that a muscle is written as N@/N| or N:@/N:|
     1457                        if (par != NULL && par->name == "N")
     1458                        {
     1459                                node1 = new f4_node(genot[gpos], par, gpos);
     1460                                par = node1;
     1461                                gpos++;
     1462                        }
     1463                        else
     1464                        {
     1465                                return gpos + 1;
     1466                        }
     1467                        break;
     1468                }
     1469
     1470                case 'N':
     1471                {
     1472                        // if there is no colon after N, then there is no class definition
     1473                        if (gpos + 1 >= strlen(genot) || genot[gpos + 1] != ':')
     1474                        {
     1475                                node1 = new f4_node(genot[gpos], par, gpos);
     1476                                par = node1;
     1477                                gpos++;
     1478                                break;
     1479                        }
     1480                        // if there is a colon determining neuron parameter, then let the switch case colon handle this
     1481                        else if (sscanf(genot + gpos + 1, ":%c%c%[:]", &tc1, &tc2, &tc3) == 3)
     1482                        {
     1483                                node1 = new f4_node(genot[gpos], par, gpos);
     1484                                par = node1;
     1485                                gpos++;
     1486                                break;
     1487                        }
     1488                        int forgenorange = gpos;
     1489                        gpos += 2; //skipping "N:"
     1490                        beginindex = gpos;
     1491                        char * end = (char*)genot + beginindex;
     1492                        GenoOperators::parseNeuroClass(end);
     1493                        gpos += end - genot - beginindex;
     1494                        neutype = string(genot + beginindex, genot + gpos);
     1495                        node1 = new f4_node(neutype, par, forgenorange);
     1496                        par = node1;
     1497                        break;
     1498                }
     1499                case ':':
     1500                {
     1501                        // neuron parameter  +! -! += -= +/ or -/
     1502                        if (sscanf(genot + gpos, ":%c%c%[:]", &tc1, &tc2, &tc3) != 3)
     1503                                // error: incorrect format
     1504                                return gpos + 1 + 1;
     1505                        if ('+' == tc1) j = 1;
     1506                        else if ('-' == tc1) j = 0;
     1507                        else return gpos + 1 + 1;
     1508                        switch (tc2)
     1509                        {
     1510                        case '!':  case '=':  case '/':  break;
     1511                        default:
     1512                                return gpos + 1 + 1;
     1513                        }
     1514                        node1 = new f4_node(":", par, gpos);
     1515                        node1->l1 = j;
     1516                        node1->i1 = (int)tc2;
     1517                        par = node1;
     1518                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
     1519                        gpos += j + 2;
     1520                        break;
     1521                }
    13991522                case '[':
    1400                         // link to neuron
    1401                         // input (%d, '*', 'G', 'T', 'S')
    1402                         t = -1;
    1403                         if (sscanf(genot + gpos, "[%ld:%lf]", &relfrom, &w) == 2) t = 0;
    1404                         else if (sscanf(genot + gpos, "[*:%lf]", &w) == 1) t = 1;
    1405                         else if (sscanf(genot + gpos, "[G:%lf]", &w) == 1) t = 2;
    1406                         else if (sscanf(genot + gpos, "[T:%lf]", &w) == 1) t = 3;
    1407                         else if (sscanf(genot + gpos, "[S:%lf]", &w) == 1) t = 4;
    1408                         // error: no correct format
    1409                         if (t < 0) return gpos + 1 + 1;
    1410                         node1 = new f4_node('[', par, gpos);
     1523                {
     1524                        const char *end = parseConnection(genot + gpos, relfrom, w);
     1525                        if (end == NULL)
     1526                        {
     1527                                end = parseConnectionWithNeuron(genot + gpos, neutype, w);
     1528                                if (end == NULL) t = -1;
     1529                                t = 1;
     1530                        }
     1531                        else
     1532                        {
     1533                                t = 0;
     1534                        }
     1535                        node1 = new f4_node("[", par, gpos);
     1536                        node1->s1 = neutype;
    14111537                        node1->i1 = t;
    14121538                        node1->l1 = relfrom;
     
    14161542                        gpos += j + 2;
    14171543                        break;
    1418 
    1419                 case ':':
    1420                         // neuron parameter  +! -! += -= +/ or -/
    1421                         if (sscanf(genot + gpos, ":%c%c:", &tc1, &tc2) != 2)
    1422                                 // error: incorrect format
    1423                                 return gpos + 1 + 1;
    1424                         if ('+' == tc1) j = 1;
    1425                         else if ('-' == tc1) j = 0;
    1426                         else return gpos + 1 + 1;
    1427                         switch (tc2)
    1428                         {
    1429                         case '!':  case '=':  case '/':  break;
    1430                         default:
    1431                                 return gpos + 1 + 1;
    1432                         }
    1433                         node1 = new f4_node(':', par, gpos);
    1434                         node1->l1 = j;
    1435                         node1->i1 = (int)tc2;
    1436                         par = node1;
    1437                         j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
    1438                         gpos += j + 2;
    1439                         break;
    1440 
    1441                 case ' ':
    1442                 case '\n':
    1443                 case '\t':
    1444                         // whitespace: ignore
    1445                         //node1 = new f4_node(' ', par, gpos );
    1446                         //par = node1;
    1447                         gpos++;
    1448                         break;
    1449 
     1544                }
    14501545                default:
     1546                {
    14511547                        //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
    14521548                        //add it, build will give the error or repair
     
    14561552                        break;
    14571553                }
    1458         }
     1554                }
     1555        }
     1556
    14591557        // should end with a '>'
    14601558        if (par)
    14611559        {
    1462                 if ('>' != par->name)
     1560                if (par->name != ">")
    14631561                {
    14641562                        node1 = new f4_node('>', par, strlen(genot) - 1);
     
    14671565        }
    14681566
    1469         return 0;  // OK
    1470 }
    1471 
     1567        return 0;
     1568}
     1569
     1570const char* parseConnection(const char *fragm, int& relfrom, double &weight)
     1571{
     1572        const char *parser = fragm;
     1573        if (*parser != '[') return NULL;
     1574        parser++;
     1575        ExtValue val;
     1576        parser = val.parseNumber(parser, ExtPType::TInt);
     1577        if (parser == NULL) return NULL;
     1578        relfrom = val.getInt();
     1579        if (*parser != ':') return NULL;
     1580        parser++;
     1581        parser = val.parseNumber(parser, ExtPType::TDouble);
     1582        if (parser == NULL) return NULL;
     1583        weight = val.getDouble();
     1584        if (*parser != ']') return NULL;
     1585        parser++;
     1586        return parser;
     1587}
     1588
     1589const char* parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight)
     1590{
     1591        const char *parser = fragm;
     1592        if (*parser != '[') return NULL;
     1593        parser++;
     1594        char * p = (char*)parser;
     1595        if (GenoOperators::parseNeuroClass(p) == NULL) return NULL;
     1596        neutype = string(parser, (const char *)p);
     1597        parser = p;
     1598        if (*parser != ':') return NULL;
     1599        parser++;
     1600        ExtValue val;
     1601        parser = val.parseNumber(parser, ExtPType::TDouble);
     1602        if (parser == NULL) return NULL;
     1603        weight = val.getDouble();
     1604        if (*parser != ']') return NULL;
     1605        parser++;
     1606        return parser;
     1607}
    14721608
    14731609f4_node * f4_processtree(const char * geno)
Note: See TracChangeset for help on using the changeset viewer.