source: cpp/frams/genetics/f4/f4_general.cpp @ 1095

Last change on this file since 1095 was 973, checked in by Maciej Komosinski, 4 years ago

Increased SString and std::string compatibility: introduced length(), size(), and capacity(), and removed legacy methods that have std::string equivalents

  • Property svn:eol-style set to native
File size: 32.9 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[973]2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[193]4
[196]5// Copyright (C) 1999,2000  Adam Rotaru-Varga (adam_rotaru@yahoo.com), GNU LGPL
[760]6// 2018, Grzegorz Latosinski, added support for new API for neuron types and their properties
[196]7
[193]8#include "f4_general.h"
[779]9#include "../genooperators.h" //for GENOPER_ constants
[196]10#include <common/nonstd_stl.h>
[375]11#include <common/log.h>
[196]12#include <frams/model/model.h> // for min and max attributes
13#include <common/nonstd_math.h>
[193]14
15#ifdef DMALLOC
16#include <dmalloc.h>
17#endif
18
[774]19void rolling_dec(double *v)
[671]20{
[196]21        *v -= 0.7853;  // 0.7853981  45 degrees
[193]22}
[671]23
[774]24void rolling_inc(double *v)
[671]25{
[196]26        *v += 0.7853;  // 0.7853981  45 degrees
[193]27}
28
[774]29int scanrec(const char* s, unsigned int slen, char stopchar)
[193]30{
[196]31        unsigned int i = 0;
32        //DB( printf("    scan('%s', '%c')\n", s, stopchar); )
33        while (1)
34        {
35                if (i >= slen)  // ran out the string, should never happen with correct string
36                        return 1;
37                if (stopchar == s[i])  // bumped into stopchar
38                        return i;
[671]39                if (i < slen - 1) // s[i] is not the last char
40                {
[196]41                        if (s[i] == '(')
42                        {
43                                i += 2 + scanrec(s + i + 1, slen - i - 1, ')');
44                                continue;
45                        }
46                        if (s[i] == '<')
47                        {
48                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
49                                continue;
50                        }
51                        if (s[i] == '#')
52                        {
53                                i += 2 + scanrec(s + i + 1, slen - i - 1, '>');
54                                continue;
55                        }
56                }
57                // s[i] a non-special character
58                i++;
59        }
60        return i;
[193]61}
62
63
64f4_Cell::f4_Cell(int nname,
[774]65        f4_Cell *ndad, int nangle, GeneProps newP)
[193]66{
[196]67        name = nname;
68        type = T_UNDIFF4;
69        dadlink = ndad;
70        org = NULL;
71        genot = NULL;
72        gcur = NULL;
73        active = 1;
[760]74        repeat.clear();
[196]75        //genoRange.clear(); -- implicit
[193]76
[196]77        anglepos = nangle;
78        commacount = 0;
79        childcount = 0;
80        P = newP;
81        rolling = 0;
82        xrot = 0;
83        zrot = 0;
84        //OM = Orient_1;
85        ctrl = 0;
86        inertia = 0.8;
87        force = 0.04;
88        sigmo = 2;
89        nolink = 0;
[193]90
[196]91        // adjust firstend and OM if there is a stick dad
92        if (ndad != NULL)
93        {
94                // make sure it is a stick (and not a stick f4_Cell!)
95                if (T_STICK4 == ndad->type)
96                {
97                        //firstend = ndad->lastend;
98                        //OM = ndad->OM;
99                        ndad->childcount++;
100                }
101                if (T_NEURON4 == ndad->type)
102                {
103                        inertia = ndad->inertia;
104                        force = ndad->force;
105                        sigmo = ndad->sigmo;
106                }
107        }
108        // adjust lastend
109        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
110        mz = 1;
[193]111}
112
113
[774]114f4_Cell::f4_Cell(f4_Cells *nO, int nname, f4_node *ngeno, f4_node *ngcur, f4_Cell *ndad, int nangle, GeneProps newP)
[193]115{
[196]116        name = nname;
117        type = T_UNDIFF4;
118        dadlink = ndad;
119        org = nO;
120        genot = ngeno;
121        gcur = ngcur;
122        active = 1;
[760]123        repeat.clear();
[196]124        //genoRange.clear(); -- implicit
125        // preserve geno range of parent cell
126        if (NULL != ndad)
127                genoRange.add(ndad->genoRange);
[193]128
[196]129        anglepos = nangle;
130        commacount = 0;
131        childcount = 0;
132        P = newP;
133        rolling = 0;
134        xrot = 0;
135        zrot = 0;
136        //OM = Orient_1;
137        ctrl = 0;
138        inertia = 0.8;
139        force = 0.04;
140        sigmo = 2;
141        nolink = 0;
[193]142
[196]143        // adjust firstend and OM if there is a stick dad
144        if (ndad != NULL)
145        {
146                // make sure it is a stick (and not a stick f4_Cell!)
[671]147                if (T_STICK4 == ndad->type)
148                {
[196]149                        //firstend = ndad->lastend;
150                        //OM = ndad->OM;
151                        ndad->childcount++;
152                }
153                if (T_NEURON4 == ndad->type)
154                {
155                        inertia = ndad->inertia;
156                        force = ndad->force;
157                        sigmo = ndad->sigmo;
158                }
159        }
160        // adjust lastend
161        //lastend = firstend + ((Orient)OM * (Pt3D(1,0,0) * P.len));
162        mz = 1;
[193]163}
164
165
166f4_Cell::~f4_Cell()
167{
[196]168        // remove links
169        if (nolink)
170        {
171                int i;
172                for (i = nolink - 1; i >= 0; i--)
173                        delete links[i];
174                nolink = 0;
175        }
[193]176}
177
178
179/* return codes:
[196]180        >1 error at pos
181        0  halt development for a cycle
182        -1  development finished OK
183        */
[193]184int f4_Cell::onestep()
185{
[196]186        if (gcur == NULL)
187        {
188                active = 0;
189                return 0;  // stop
190        }
191        while (NULL != gcur)
192        {
193                //DB( printf("  %d (%d) executing '%c' %d\n", name, type, gcur->name, gcur->pos); )
194                // currently this is the last one processed
195                // the current genotype code is processed
[760]196                //genoRange.add(gcur->pos,gcur->pos+gcur->name.length()-1);
197                bool neuclasshandler = false; // if set to true, then there is a set of characters that can be assigned to a neuron class type
198                // old semantics, one-character
199                if (gcur->name.length() == 1)
[196]200                {
[760]201                        genoRange.add(gcur->pos, gcur->pos);
202                        char name = gcur->name[0];
203                        switch (name)
[671]204                        {
[760]205                        case '<':
206                        {
207                                // cell division!
208                                //DB( printf("  div! %d\n", name); )
[193]209
[760]210                                // error: sticks cannot divide
211                                if (T_STICK4 == type)
[671]212                                {
[760]213                                        // cannot fix
214                                        org->setError(gcur->pos);
215                                        return 1;  // stop
[196]216                                }
[193]217
[760]218                                // undiff divides
219                                if (T_UNDIFF4 == type)
220                                {
221                                        // commacount is set only when daughter turns into X
222                                        // daughter cell
223                                        // adjust new len
224                                        GeneProps newP = P;
225                                        newP.propagateAlong(false);
[774]226                                        f4_Cell *tmp = new f4_Cell(org, org->nc, genot, gcur->child2, this, commacount, newP);
[760]227                                        tmp->repeat = repeat;
228                                        repeat.clear();
229                                        org->addCell(tmp);
230                                }
231                                // a neuron divides: create a new, duplicate links
232                                if (T_NEURON4 == type) {
233                                        // daughter cell
234                                        f4_Cell *tmp = new f4_Cell(org, org->nc, genot, gcur->child2,
235                                                // has the same dadlink
236                                                this->dadlink, commacount, P);
237                                        tmp->repeat = repeat;
238                                        repeat.clear();
239                                        // it is a neuron from start
240                                        tmp->type = T_NEURON4;
241                                        // it has the same type as the parent neuron
242                                        tmp->neuclass = neuclass;
243                                        // duplicate links
[774]244                                        f4_CellLink *ll;
[760]245                                        for (int i = 0; i < nolink; i++)
[196]246                                        {
[760]247                                                ll = links[i];
248                                                tmp->addlink(ll->from, ll->w, ll->t);
[196]249                                        }
[760]250                                        org->addCell(tmp);
251                                }
252                                // adjustments for this cell
253                                gcur = gcur->child;
254                                // halt development
255                                return 0;
256                        }
257                        case '>':
258                        {
259                                // finish
260                                // see if there is a repet count
261                                if (repeat.top > 0)
262                                { // there is a repeat counter
263                                        if (!repeat.first()->isNull())
264                                        { // repeat counter is not null
265                                                repeat.first()->dec();
266                                                if (repeat.first()->count > 0)
267                                                {
268                                                        // return to repeat
269                                                        gcur = repeat.first()->node->child;
270                                                }
271                                                else
272                                                {
273                                                        // continue
274                                                        gcur = repeat.first()->node->child2;
275                                                        repeat.pop();
276                                                }
277                                                break;
278                                        }
[671]279                                        else
280                                        {
[196]281                                                repeat.pop();
282                                        }
283                                }
[671]284                                else
285                                {
[760]286                                        // error: still undiff
287                                        if (T_UNDIFF4 == type)
288                                        {
289                                                // fix it: insert an 'X'
290                                                f4_node *insertnode = new f4_node("X", NULL, gcur->pos);
291                                                if (org->setRepairInsert(gcur->pos, gcur, insertnode)) // not in repair mode, release
292                                                        delete insertnode;
293                                                return 1;
294                                        }
295                                        repeat.clear();
296                                        active = 0;  // stop
297                                        // eat up rest
298                                        gcur = NULL;
299                                        return 0;
[196]300                                }
301                        }
[853]302                        [[fallthrough]];
[760]303                        case '#':
[671]304                        {
[760]305                                // repetition marker
306                                if (repeat.top >= repeat_stack::stackSize)
[196]307                                {
[760]308                                        // repeat pointer stack is full, cannot remember this one.
309                                        // fix: delete it
310                                        org->setRepairRemove(gcur->pos, gcur);
311                                        return 1;  // stop
[196]312                                }
[760]313                                repeat.push(repeat_ptr(gcur, gcur->i1));
314                                gcur = gcur->child;
315                                break;
[196]316                        }
[760]317                        case ',':
[196]318                        {
[760]319                                commacount++;
320                                gcur = gcur->child;
321                                break;
[196]322                        }
[760]323                        case 'r':  case 'R':
[671]324                        {
[760]325                                // error: if neuron
326                                if (T_NEURON4 == type)
327                                {
328                                        // fix: delete it
329                                        org->setRepairRemove(gcur->pos, gcur);
330                                        return 1;  // stop
331                                }
332                                switch (name)
333                                {
334                                case 'r':   rolling_dec(&rolling); break;
335                                case 'R':   rolling_inc(&rolling); break;
336                                }
337                                gcur = gcur->child;
338                                break;
[196]339                        }
[760]340                        case 'l':  case 'L':
341                        case 'c':  case 'C':
342                        case 'q':  case 'Q':
343                        case 'a':  case 'A':
344                        case 'i':  case 'I':
345                        case 's':  case 'S':
346                        case 'm':  case 'M':
347                        case 'f':  case 'F':
348                        case 'w':  case 'W':
349                        case 'e':  case 'E':
350                        case 'd':  case 'D':
351                        case 'g':  case 'G':
352                        case 'b':  case 'B':
353                        case 'h':  case 'H':
[671]354                        {
[760]355                                // error: if neuron
356                                if (T_NEURON4 == type)
357                                {
358                                        // fix: delete it
359                                        org->setRepairRemove(gcur->pos, gcur);
360                                        return 1;  // stop
361                                }
362                                P.executeModifier(name);
363                                gcur = gcur->child;
364                                break;
[196]365                        }
[760]366                        case 'X':
[671]367                        {
[760]368                                // turn undiff. cell into a stick
369                                // error: already differentiated
370                                if (T_UNDIFF4 != type)
371                                {
372                                        // fix: delete this node
373                                        org->setRepairRemove(gcur->pos, gcur);
374                                        return 1;  // stop
375                                }
376                                type = T_STICK4;
377                                // fix dad commacount and own anglepos
378                                if (NULL != dadlink)
379                                {
380                                        dadlink->commacount++;
381                                        anglepos = dadlink->commacount;
382                                }
383                                // change of type halts developments, see comment at 'N'
384                                gcur = gcur->child;
385                                return 0;
[196]386                        }
[760]387                        case 'N':
[671]388                        {
[760]389                                // turn undiff. cell into a neuron
390                                // error: already differentiated
391                                if (T_UNDIFF4 != type)
392                                {
393                                        // fix: delete this node
394                                        org->setRepairRemove(gcur->pos, gcur);
395                                        return 1;  // stop
396                                }
397                                // error: if no previous
398                                if (NULL == dadlink)
399                                {
400                                        // fix: delete it
401                                        org->setRepairRemove(gcur->pos, gcur);
402                                        return 1;  // stop
403                                }
404                                string temp1 = "N";
405                                char *temp = (char*)temp1.c_str();
406                                neuclass = GenoOperators::parseNeuroClass(temp);
407                                type = T_NEURON4;
408                                // change of type also halts development, to give other
409                                // cells a chance for adjustment.  Namely, it is important
410                                // to wait for other cells to turn N before adding links
411                                gcur = gcur->child;
412                                return 0;
[196]413                        }
[760]414                        case '@':
415                        case '|':
[671]416                        {
[760]417                                // neuron rotating / bending
418                                int j = 1;
419                                if ('@' == name) j = 1; // rot
420                                else
421                                        if ('|' == name) j = 2; // bend
[193]422
[760]423                                // if undiff, then this is a new muscle. Thanks to f4_processrec @ and | case we can skip repairing
424                                if (T_UNDIFF4 == type)
425                                {
426                                        neuclasshandler = true;
427                                        break;
428                                }
[193]429
[760]430                                // error: not a neuron (stick)
431                                if (T_NEURON4 != type)
432                                {
433                                        // fix: delete it
434                                        org->setRepairRemove(gcur->pos, gcur);
435                                        return 1;  // stop
436                                }
437                                // error: already has control
438                                if (ctrl != 0)
439                                {
440                                        // fix: delete it
441                                        org->setRepairRemove(gcur->pos, gcur);
442                                        return 1;  // stop
443                                }
444                                // make neuron ctrl = 1 or 2
445                                ctrl = j;
446                                gcur = gcur->child;
447                                break;
[196]448                        }
[760]449                        case '[':
[671]450                        {
[760]451                                // link to neuron
452                                // error: not a neuron
453                                if (T_NEURON4 != type)
454                                {
455                                        // fix: delete it
456                                        org->setRepairRemove(gcur->pos, gcur);
457                                        return 1;  // stop
458                                }
459                                // input (sensor or %d)
460                                int t = gcur->i1;
461                                int relfrom = gcur->l1;
462                                float w = gcur->f1;
463                                f4_Cell *tneu = NULL;
[767]464                                if (t < 0) // wrong sensor
[760]465                                {
[767]466                                        string buf = "wrong sensor in link '";
467                                        buf.append(gcur->s1);
468                                        buf.append("'");
469                                        logMessage("f4_Cell", "onestep", LOG_ERROR, buf.c_str());
470                                        org->setRepairRemove(gcur->pos, gcur);
471                                        return 1;
472                                }
473                                else if (t > 0) // sensors
474                                {
[760]475                                        char *temp = (char*)gcur->s1.c_str();
476                                        NeuroClass *sensortest = GenoOperators::parseNeuroClass(temp);
477                                        if (sensortest == NULL || sensortest->getPreferredInputs() != 0)
478                                        {
479                                                // error: unknown code
480                                                string buf = "wrong sensor in link '";
481                                                buf.append(gcur->s1);
482                                                buf.append("'");
[767]483                                                logMessage("f4_Cell", "onestep", LOG_ERROR, buf.c_str());
[760]484                                                org->setRepairRemove(gcur->pos, gcur);
485                                                return 1;
486                                        }
487                                }
488                                else {
489                                        // input from other neuron
490                                        // find neuron at relative i
491                                        // find own index
492                                        int j = 0, k = 0;
493                                        for (int i = 0; i < org->nc; i++)
494                                        {
495                                                if (org->C[i]->type == T_NEURON4) k++;
496                                                if (org->C[i] == this) { j = k - 1; break; }
497                                        }
498                                        // find index of incoming
499                                        j = j + relfrom;
500                                        if (j < 0) goto wait_link;
501                                        if (j >= org->nc) goto wait_link;
502                                        // find that neuron
503                                        k = 0;
504                                        int i;
505                                        for (i = 0; i < org->nc; i++)
506                                        {
507                                                if (org->C[i]->type == T_NEURON4) k++;
508                                                if (j == (k - 1)) break;
509                                        }
510                                        if (i >= org->nc) goto wait_link;
511                                        tneu = org->C[i];
512                                }
513                                // add link
514                                // error: could not add link (too many?)
515                                if (addlink(tneu, w, gcur->s1))
516                                {
517                                        // cannot fix
518                                        org->setError(gcur->pos);
519                                        return 1;  // stop
520                                }
521                                gcur = gcur->child;
522                                break;
[196]523                        }
[853]524                wait_link:
[671]525                        {
[760]526                                // wait for other neurons to develop
527                                // if there are others still active
528                                active = 0;
529                                int j = 0;
530                                for (int i = 0; i < org->nc; i++)
531                                {
532                                        if (org->C[i]->active) j++;
533                                }
534                                if (j > 0)
535                                        return 0;  // there is other active, halt, try again
536                                // no more actives, cannot add link, ignore, but treat not as an error
537                                gcur = gcur->child;
[196]538                        }
[853]539                        break;
[760]540                        case ':':
[671]541                        {
[760]542                                // neuron parameter
543                                // error: not a neuron
544                                if (T_NEURON4 != type)
[671]545                                {
[760]546                                        // fix: delete it
547                                        org->setRepairRemove(gcur->pos, gcur);
548                                        return 1;  // stop
[196]549                                }
[829]550                                int j = gcur->l1;
[760]551                                switch ((char)gcur->i1)
[671]552                                {
[760]553                                case '!':
554                                        if (j)
555                                                force += (1.0 - force) * 0.2;
556                                        else
557                                                force -= force * 0.2;
558                                        break;
559                                case '=':
560                                        if (j)
561                                                inertia += (1.0 - inertia) * 0.2;
562                                        else
563                                                inertia -= inertia * 0.2;
564                                        break;
565                                case '/':
566                                        if (j)
567                                                sigmo *= 1.4;
568                                        else
569                                                sigmo /= 1.4;
570                                        break;
571                                default:
572                                        org->setRepairRemove(gcur->pos, gcur);
573                                        return 1;  // stop
[196]574                                }
[760]575                                gcur = gcur->child;
576                                break;
[196]577                        }
[760]578                        case ' ':
[671]579                        {
[760]580                                // space has no effect, should not occur
581                                // fix: delete it
582                                org->setRepairRemove(gcur->pos, gcur);
583                                gcur = gcur->child;
584                                break;
[196]585                        }
[760]586                        default:
[671]587                        {
[760]588                                // because there are one-character neuron classes, default move control to neuclasshandler
589                                neuclasshandler = true;
[196]590                        }
[760]591                        }
592                }
593                else
594                {
595                        // if many characters, then it needs to be parsed below
596                        neuclasshandler = true;
597                }
[193]598
[760]599                if (neuclasshandler)
600                {
601                        genoRange.add(gcur->pos, gcur->pos + gcur->name.length() + 2 - 1); // +2 for N:
602                        if (T_UNDIFF4 != type)
[671]603                        {
[760]604                                // fix: delete this node
[196]605                                org->setRepairRemove(gcur->pos, gcur);
606                                return 1;  // stop
607                        }
[760]608                        // error: if no previous
609                        if (NULL == dadlink)
[671]610                        {
[760]611                                // fix: delete it
[196]612                                org->setRepairRemove(gcur->pos, gcur);
613                                return 1;  // stop
614                        }
[760]615                        // multiple characters are neuron types. Need to check if exists
616                        char *temp = (char*)gcur->name.c_str();
617                        neuclass = GenoOperators::parseNeuroClass(temp);
618                        if (neuclass == NULL)
619                        {
620                                // error: unknown code
621                                string buf = "unknown code '";
622                                buf.append(gcur->name);
623                                buf.append("'");
624                                logMessage("f4_Cell", "onestep", 2, buf.c_str());
625                                org->setRepairRemove(gcur->pos, gcur);
626                                return 1;
627                        }
628                        type = T_NEURON4; //they belong to neurons
[196]629                        gcur = gcur->child;
[760]630                        return 0; //stop
[196]631                }
632        }
633        active = 0;  // done
634        return 0;
[193]635}
636
637
[774]638int f4_Cell::addlink(f4_Cell *nfrom, double nw, string nt)
[193]639{
[760]640        // if incoming neuron does not produce output, return error
641        if (nfrom != NULL && nfrom->neuclass->getPreferredOutput() == 0) return -1;
642        if (neuclass->getPreferredInputs() != -1 && nolink >= neuclass->getPreferredInputs()) return -1;
[196]643        if (nolink >= MAXINPUTS - 1) return -1; // full!
644        links[nolink] = new f4_CellLink(nfrom, nw, nt);
645        nolink++;
646        return 0;
[193]647}
648
649
650void f4_Cell::adjustRec()
651{
[196]652        //f4_OrientMat rot;
[671]653        int i;
[193]654
[196]655        if (recProcessedFlag)
656                // already processed
657                return;
[193]658
[196]659        // mark it processed
660        recProcessedFlag = 1;
[193]661
[196]662        // make sure its parent is processed first
663        if (NULL != dadlink)
664                dadlink->adjustRec();
[193]665
[196]666        // count children
667        childcount = 0;
668        for (i = 0; i < org->nc; i++)
669        {
670                if (org->C[i]->dadlink == this)
671                        if (org->C[i]->type == T_STICK4)
672                                childcount++;
673        }
[193]674
[196]675        if (type == T_STICK4)
676        {
677                if (NULL == dadlink)
678                {
679                        //firstend = Pt3D_0;
680                        // rotation due to rolling
681                        xrot = rolling;
682                        mz = 1;
683                }
[671]684                else
685                {
[196]686                        //firstend = dadlink->lastend;
[760]687                        GeneProps Pdad = dadlink->P;
688                        GeneProps Padj = Pdad;
689                        Padj.propagateAlong(false);
[193]690
[196]691                        //rot = Orient_1;
[193]692
[196]693                        // rotation due to rolling
694                        xrot = rolling +
695                                // rotation due to twist
696                                Pdad.twist;
697                        if (dadlink->commacount <= 1)
698                        {
699                                // rotation due to curvedness
[671]700                                zrot = Padj.curvedness;
[196]701                        }
[671]702                        else
703                        {
704                                zrot = Padj.curvedness + (anglepos * 1.0 / (dadlink->commacount + 1) - 0.5) * M_PI * 2.0;
[196]705                        }
[193]706
[196]707                        //rot = rot * f4_OrientMat(yOz, xrot);
708                        //rot = rot * f4_OrientMat(xOy, zrot);
709                        // rotation relative to parent stick
710                        //OM = rot * OM;
[193]711
[196]712                        // rotation in world coordinates
713                        //OM =  ((f4_OrientMat)dadlink->OM) * OM;
714                        mz = dadlink->mz / dadlink->childcount;
715                }
716                //Pt3D lastoffset = (Orient)OM * (Pt3D(1,0,0)*P.len);
717                //lastend = firstend + lastoffset;
718        }
[193]719}
720
721
722
[774]723f4_CellLink::f4_CellLink(f4_Cell *nfrom, double nw, string nt)
[193]724{
[196]725        from = nfrom;
726        w = nw;
727        t = nt;
[193]728}
729
730
731
[774]732f4_Cells::f4_Cells(f4_node *genome, int nrepair)
[193]733{
[196]734        // create ancestor cell
735        repair = nrepair;
736        error = 0;
737        errorpos = -1;
738        repair_remove = NULL;
739        repair_parent = NULL;
740        repair_insert = NULL;
741        tmpcel = NULL;
742        f4rootnode = NULL;
[760]743        C[0] = new f4_Cell(this, 0, genome, genome, NULL, 0, GeneProps::standard_values);
[196]744        nc = 1;
[193]745}
746
747
748f4_Cells::f4_Cells(SString & genome, int nrepair)
749{
[196]750        int res;
751        repair = nrepair;
752        error = 0;
753        errorpos = -1;
754        repair_remove = NULL;
755        repair_parent = NULL;
756        repair_insert = NULL;
757        tmpcel = NULL;
758        f4rootnode = NULL;
[193]759
[196]760        // transform geno from string to nodes
761        f4rootnode = new f4_node();
[348]762        res = f4_processrec(genome.c_str(), (unsigned)0, f4rootnode);
[196]763        if ((res < 0) || (1 != f4rootnode->childCount()))
764        {
765                error = GENOPER_OPFAIL;
766                errorpos = -1;
767        }
[193]768
[196]769        // create ancestor cell
[760]770        C[0] = new f4_Cell(this, 0, f4rootnode->child, f4rootnode->child, NULL, 0, GeneProps::standard_values);
[196]771        nc = 1;
[193]772}
773
774f4_Cells::~f4_Cells()
775{
[196]776        // release cells
777        int i;
778        if (nc)
779        {
780                for (i = nc - 1; i >= 0; i--)
781                        delete C[i];
782                nc = 0;
783        }
784        if (f4rootnode)
785                delete f4rootnode;
[193]786}
787
788
789int f4_Cells::onestep()
790{
[196]791        int i, ret, oldnc, ret2;
792        oldnc = nc;
793        ret = 0;
[671]794        for (i = 0; i < oldnc; i++)
795        {
[196]796                ret2 = C[i]->onestep();
[671]797                if (ret2 > 0)
798                {
[196]799                        // error
800                        C[i]->active = 0;  // stop
801                        return 0;
802                }
803                // if still active
804                if (C[i]->active)
805                        ret = 1;
806        }
807        return ret;
[193]808}
809
810
811int f4_Cells::simulate()
812{
[196]813        int i;
814        error = GENOPER_OK;
[193]815
[196]816        for (i = 0; i < nc; i++)  C[i]->active = 1;
[193]817
[196]818        // execute onestep() in a cycle
819        while (onestep());
[193]820
[196]821        if (GENOPER_OK != error) return error;
[193]822
[196]823        // fix neuron attachements
824        for (i = 0; i < nc; i++)
[671]825        {
826                if (C[i]->type == T_NEURON4)
827                {
828                        while (T_NEURON4 == C[i]->dadlink->type)
829                        {
[196]830                                C[i]->dadlink = C[i]->dadlink->dadlink;
831                        }
832                }
[671]833        }
[193]834
[196]835        // there should be no undiff. cells
836        // make undifferentiated cells sticks
837        for (i = 0; i < nc; i++)
[671]838        {
839                if (C[i]->type == T_UNDIFF4)
840                {
[196]841                        C[i]->type = T_STICK4;
842                        //seterror();
843                }
[671]844        }
[193]845
[196]846        // recursive adjust
847        // reset recursive traverse flags
848        for (i = 0; i < nc; i++)
849                C[i]->recProcessedFlag = 0;
850        // process every cell
851        for (i = 0; i < nc; i++)
852                C[i]->adjustRec();
[193]853
[196]854        //DB( printf("Cell simulation done, %d cells. \n", nc); )
[193]855
[196]856        return error;
[193]857}
858
859
[774]860void f4_Cells::addCell(f4_Cell *newcell)
[193]861{
[671]862        if (nc >= MAX4CELLS - 1)
863        {
[196]864                delete newcell;
865                return;
866        }
867        C[nc] = newcell;
868        nc++;
[193]869}
870
871
872void f4_Cells::setError(int nerrpos)
873{
[196]874        error = GENOPER_OPFAIL;
875        errorpos = nerrpos;
[193]876}
877
[774]878void f4_Cells::setRepairRemove(int nerrpos, f4_node *rem)
[193]879{
[671]880        if (!repair)
881        {
[196]882                // not in repair mode, treat as repairable error
883                error = GENOPER_REPAIR;
884                errorpos = nerrpos;
885        }
[671]886        else
887        {
[196]888                error = GENOPER_REPAIR;
889                errorpos = nerrpos;
890                repair_remove = rem;
891        }
[193]892}
893
[774]894int f4_Cells::setRepairInsert(int nerrpos, f4_node *parent, f4_node *insert)
[193]895{
[671]896        if (!repair)
897        {
[196]898                // not in repair mode, treat as repairable error
899                error = GENOPER_REPAIR;
900                errorpos = nerrpos;
901                return -1;
902        }
[671]903        else
904        {
[196]905                error = GENOPER_REPAIR;
906                errorpos = nerrpos;
907                repair_parent = parent;
908                repair_insert = insert;
909                return 0;
910        }
[193]911}
912
[774]913void f4_Cells::repairGeno(f4_node *geno, int whichchild)
[193]914{
[196]915        // assemble repaired geno, if the case
916        if (!repair) return;
917        if ((NULL == repair_remove) && (NULL == repair_insert)) return;
918        // traverse genotype tree, remove / insert node
[774]919        f4_node *g2;
[196]920        if (1 == whichchild) g2 = geno->child;
921        else             g2 = geno->child2;
922        if (NULL == g2)
923                return;
[671]924        if (g2 == repair_remove)
925        {
[774]926                f4_node *oldgeno;
[196]927                geno->removeChild(g2);
[671]928                if (g2->child)
929                {
[196]930                        // add g2->child as child to geno
931                        if (1 == whichchild) geno->child = g2->child;
932                        else             geno->child2 = g2->child;
933                        g2->child->parent = geno;
934                }
935                oldgeno = g2;
936                oldgeno->child = NULL;
937                delete oldgeno;
938                if (NULL == geno->child) return;
939                // check this new
940                repairGeno(geno, whichchild);
941                return;
942        }
[671]943        if (g2 == repair_parent)
944        {
[196]945                geno->removeChild(g2);
946                geno->addChild(repair_insert);
947                repair_insert->parent = geno;
948                repair_insert->child = g2;
949                repair_insert->child2 = NULL;
950                g2->parent = repair_insert;
951        }
952        // recurse
953        if (g2->child)  repairGeno(g2, 1);
954        if (g2->child2) repairGeno(g2, 2);
[193]955}
956
957
958void f4_Cells::toF1Geno(SString &out)
959{
[196]960        if (tmpcel) delete tmpcel;
[760]961        tmpcel = new f4_Cell(-1, NULL, 0, GeneProps::standard_values);
[196]962        out = "";
963        toF1GenoRec(0, out);
964        delete tmpcel;
[193]965}
966
967
968void f4_Cells::toF1GenoRec(int curc, SString &out)
969{
[196]970        int i, j, ccount;
[774]971        f4_Cell *thisti;
972        f4_Cell *thneu;
[196]973        char buf[200];
[193]974
[196]975        if (curc >= nc) return;
[193]976
[196]977        if (T_STICK4 != C[curc]->type) return;
[193]978
[196]979        thisti = C[curc];
980        if (NULL != thisti->dadlink)
981                *tmpcel = *(thisti->dadlink);
[193]982
[196]983        // adjust length, curvedness, etc.
[760]984        tmpcel->P.propagateAlong(false);
[671]985        while (tmpcel->P.length > thisti->P.length)
[196]986        {
987                tmpcel->P.executeModifier('l');
988                out += "l";
989        }
[671]990        while (tmpcel->P.length < thisti->P.length)
[196]991        {
992                tmpcel->P.executeModifier('L');
993                out += "L";
994        }
[671]995        while (tmpcel->P.curvedness > thisti->P.curvedness)
[196]996        {
997                tmpcel->P.executeModifier('c');
998                out += "c";
999        }
[671]1000        while (tmpcel->P.curvedness < thisti->P.curvedness)
[196]1001        {
1002                tmpcel->P.executeModifier('C');
1003                out += "C";
1004        }
[671]1005        while (thisti->rolling > 0.0f)
1006        {
[196]1007                rolling_dec(&(thisti->rolling));
1008                out += "R";
1009        }
[671]1010        while (thisti->rolling < 0.0f)
1011        {
[196]1012                rolling_inc(&(thisti->rolling));
1013                out += "r";
1014        }
[193]1015
[196]1016        // output X for this stick
1017        out += "X";
[193]1018
[196]1019        // neurons attached to it
1020        for (i = 0; i < nc; i++)
[671]1021        {
1022                if (C[i]->type == T_NEURON4)
1023                {
1024                        if (C[i]->dadlink == thisti)
1025                        {
[196]1026                                thneu = C[i];
1027                                out += "[";
1028                                // ctrl
1029                                if (1 == thneu->ctrl) out += "@";
1030                                if (2 == thneu->ctrl) out += "|";
1031                                // links
1032                                for (j = 0; j < thneu->nolink; j++)
1033                                {
1034                                        if (j) out += ",";
1035                                        if (NULL == thneu->links[j]->from)
1036                                        {
[760]1037                                                // sensors
1038                                                out += thneu->links[j]->t.c_str();
[196]1039                                        }
[671]1040                                        else
1041                                        {
[196]1042                                                sprintf(buf, "%d", thneu->links[j]->from->name - thneu->name);
1043                                                out += buf;
1044                                        }
1045                                        out += ":";
[671]1046                                        // connection weight
[196]1047                                        sprintf(buf, "%g", thneu->links[j]->w);
1048                                        out += buf;
1049                                }
1050                                out += "]";
1051                        }
1052                }
[671]1053        }
[193]1054
[196]1055        // sticks connected to it
1056        if (thisti->commacount >= 2)
1057                out += "(";
[193]1058
[196]1059        ccount = 1;
1060        for (i = 0; i < nc; i++)
[671]1061        {
[196]1062                if (C[i]->type == T_STICK4)
[671]1063                {
1064                        if (C[i]->dadlink == thisti)
1065                        {
1066                                while (ccount < (C[i])->anglepos)
1067                                {
[196]1068                                        ccount++;
1069                                        out += ",";
1070                                }
1071                                toF1GenoRec(i, out);
1072                        }
[671]1073                }
1074        }
1075
1076        while (ccount < thisti->commacount)
1077        {
[196]1078                ccount++;
1079                out += ",";
1080        }
[193]1081
[196]1082        if (thisti->commacount >= 2)
1083                out += ")";
[193]1084}
1085
1086
1087
[671]1088// to organize an f4 genotype in a tree structure
[193]1089
1090f4_node::f4_node()
1091{
[760]1092        name = "?";
[196]1093        parent = NULL;
1094        child = NULL;
1095        child2 = NULL;
1096        pos = -1;
[760]1097        l1 = 0;
1098        i1 = 0;
1099        f1 = 0.0f;
[193]1100}
1101
[760]1102f4_node::f4_node(string nname, f4_node *nparent, int npos)
1103{
1104        name = nname;
1105        parent = nparent;
1106        child = NULL;
1107        child2 = NULL;
1108        pos = npos;
1109        if (parent) parent->addChild(this);
1110        l1 = 0;
1111        i1 = 0;
1112        f1 = 0.0f;
1113}
1114
[774]1115f4_node::f4_node(char nname, f4_node *nparent, int npos)
[193]1116{
[196]1117        name = nname;
1118        parent = nparent;
1119        child = NULL;
1120        child2 = NULL;
1121        pos = npos;
1122        if (parent) parent->addChild(this);
[760]1123        l1 = 0;
1124        i1 = 0;
1125        f1 = 0.0f;
[193]1126}
1127
1128f4_node::~f4_node()
1129{
[196]1130        // (destroy() copied here for efficiency)
1131        // children are destroyed (recursively) through the destructor
1132        if (NULL != child2)  delete child2;
1133        if (NULL != child)   delete child;
[193]1134}
1135
[774]1136int f4_node::addChild(f4_node *nchi)
[193]1137{
[671]1138        if (NULL == child)
1139        {
[196]1140                child = nchi;
1141                return 0;
1142        }
[671]1143        if (NULL == child2)
1144        {
[196]1145                child2 = nchi;
1146                return 0;
1147        }
1148        return -1;
[193]1149}
1150
[774]1151int f4_node::removeChild(f4_node *nchi)
[193]1152{
[671]1153        if (nchi == child2)
1154        {
[196]1155                child2 = NULL;
1156                return 0;
1157        }
[671]1158        if (nchi == child)
1159        {
[196]1160                child = NULL;
1161                return 0;
1162        }
1163        return -1;
[193]1164}
1165
1166int f4_node::childCount()
1167{
[671]1168        if (NULL != child)
1169        {
[196]1170                if (NULL != child2) return 2;
1171                else return 1;
1172        }
[671]1173        else
1174        {
[196]1175                if (NULL != child2) return 1;
1176                else return 0;
1177        }
[193]1178}
1179
1180int f4_node::count()
1181{
[196]1182        int c = 1;
1183        if (NULL != child)  c += child->count();
1184        if (NULL != child2) c += child2->count();
1185        return c;
[193]1186}
1187
[774]1188f4_node* f4_node::ordNode(int n)
[193]1189{
[196]1190        int n1;
1191        if (0 == n) return this;
1192        n--;
[671]1193        if (NULL != child)
1194        {
[196]1195                n1 = child->count();
1196                if (n < n1) return child->ordNode(n);
1197                n -= n1;
1198        }
[671]1199        if (NULL != child2)
1200        {
[196]1201                n1 = child2->count();
1202                if (n < n1) return child2->ordNode(n);
1203                n -= n1;
1204        }
1205        return NULL;
[193]1206}
1207
[774]1208f4_node* f4_node::randomNode()
[193]1209{
[196]1210        int n = count();
1211        // pick a random node, between 0 and n-1
[896]1212        return ordNode(rndUint(n));
[193]1213}
1214
[774]1215f4_node* f4_node::randomNodeWithSize(int mn, int mx)
[193]1216{
[196]1217        // try random nodes, and accept if size in range
1218        // limit to maxlim tries
1219        int i, n, maxlim;
[774]1220        f4_node *nod = NULL;
[196]1221        maxlim = count();
[671]1222        for (i = 0; i < maxlim; i++)
1223        {
[196]1224                nod = randomNode();
1225                n = nod->count();
[770]1226                if ((n >= mn) && (n <= mx)) return nod;
[196]1227        }
1228        // failed, doesn't matter
1229        return nod;
[193]1230}
1231
[760]1232void f4_node::sprint(SString& out)
[193]1233{
[767]1234        char buf2[20];
[196]1235        // special case: repetition code
[760]1236        if (name == "#")
[196]1237        {
1238                out += "#";
[671]1239                if (i1 != 1)
1240                {
[767]1241                        sprintf(buf2, "%d", i1);
1242                        out += buf2;
[196]1243                }
1244        }
1245        else {
1246                // special case: neuron link
[760]1247                if (name == "[")
[671]1248                {
[196]1249                        out += "[";
[671]1250                        if (i1 > 0)
1251                        {
[196]1252                                // sensor input
[760]1253                                out += s1.c_str();
[196]1254                        }
[671]1255                        else
1256                        {
[830]1257                                sprintf(buf2, "%d", l1);
[767]1258                                out += buf2;
[196]1259                        }
[767]1260                        sprintf(buf2, ":%g]", f1);
1261                        out += buf2;
[196]1262                }
[760]1263                else if (name == ":")
[671]1264                {
[767]1265                        sprintf(buf2, ":%c%c:", l1 ? '+' : '-', (char)i1);
1266                        out += buf2;
[196]1267                }
[760]1268                else if (name == "@" || name == "|")
1269                {
1270                        if (parent->name == "N")
1271                        {
[767]1272                                out += name.c_str();
[760]1273                        }
1274                        else
1275                        {
1276                                out += "N:";
[767]1277                                out += name.c_str();
[760]1278                        }
1279                }
[671]1280                else
1281                {
[760]1282                        char *temp = (char*)name.c_str();
[774]1283                        NeuroClass *nc = GenoOperators::parseNeuroClass(temp);
[760]1284                        if (nc != NULL)
1285                        {
1286                                out += "N:";
1287                        }
[767]1288                        out += name.c_str();
[196]1289                }
1290        }
1291        if (NULL != child)     child->sprint(out);
1292        // if two children, make sure last char is a '>'
1293        if (2 == childCount())
1294                if (0 == out[0]) out += ">"; else
[973]1295                        if ('>' != out[out.length() - 1]) out += ">";
[196]1296        if (NULL != child2)    child2->sprint(out);
1297        // make sure last char is a '>'
1298        if (0 == out[0]) out += ">"; else
[973]1299                if ('>' != out[out.length() - 1]) out += ">";
[193]1300}
1301
1302void f4_node::sprintAdj(char *& buf)
1303{
[196]1304        unsigned int len;
1305        // build in a SString, with initial size
[955]1306        SString out;
1307        out.reserve(int(strlen(buf)) + 2000);
[193]1308
[196]1309        sprint(out);
[193]1310
[196]1311        // very last '>' can be omitted
[973]1312        len = out.length();
[196]1313        if (len > 1)
1314                if ('>' == out[len - 1]) { (out.directWrite())[len - 1] = 0; out.endWrite(); };
1315        // copy back to string
1316        // if new is longer, reallocate buf
[671]1317        if (len + 1 > strlen(buf))
1318        {
[196]1319                buf = (char*)realloc(buf, len + 1);
1320        }
[348]1321        strcpy(buf, out.c_str());
[193]1322}
1323
[774]1324f4_node* f4_node::duplicate()
[193]1325{
[774]1326        f4_node *copy;
[196]1327        copy = new f4_node(*this);
1328        copy->parent = NULL;  // set later
1329        copy->child = NULL;
1330        copy->child2 = NULL;
[671]1331        if (NULL != child)
1332        {
[196]1333                copy->child = child->duplicate();
1334                copy->child->parent = copy;
1335        }
[671]1336        if (NULL != child2)
1337        {
[196]1338                copy->child2 = child2->duplicate();
1339                copy->child2->parent = copy;
1340        }
1341        return copy;
[193]1342}
1343
1344
1345void f4_node::destroy()
1346{
[196]1347        // children are destroyed (recursively) through the destructor
1348        if (NULL != child2)  delete child2;
1349        if (NULL != child)   delete child;
[193]1350}
1351
1352// scan genotype string and build tree
1353// return >1 for error (errorpos)
[774]1354int f4_processrec(const char* genot, unsigned pos0, f4_node *parent)
[193]1355{
[760]1356        int i, j, res, t;
[896]1357        char tc1, tc2, tc3; // tc3 is only to ensure that neuron parameter definition is completed
[247]1358        int relfrom;
[196]1359        double w;
1360        unsigned gpos, oldpos;
[774]1361        f4_node *node1, *par;
[760]1362        unsigned beginindex;
1363        string neutype = "";
[193]1364
[196]1365        gpos = pos0;
1366        par = parent;
1367        if (gpos >= strlen(genot)) return 1;
[671]1368        while (gpos < strlen(genot))
1369        {
[760]1370                neutype = "";
1371                // first switch across cell dividers and old semantics
[671]1372                switch (genot[gpos])
1373                {
[196]1374                case '<':
[760]1375                {
[196]1376                        // find out genotype start for child
1377                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
[193]1378
[760]1379                        node1 = new f4_node("<", par, gpos);
[196]1380                        par = node1;
1381                        res = f4_processrec(genot, gpos + 1, par);
1382                        if (res) return res;
[671]1383                        if (gpos + j + 2 < strlen(genot))
1384                        {
[196]1385                                res = f4_processrec(genot, gpos + j + 2, par);
1386                                if (res) return res;
1387                        }
[671]1388                        else // ran out
1389                        {
[760]1390                                node1 = new f4_node(">", par, strlen(genot) - 1);
[196]1391                                par = node1;
1392                        }
1393                        gpos++;
1394                        return 0;  // OK
[760]1395                }
[196]1396                case '>':
[760]1397                {
1398                        node1 = new f4_node(">", par, gpos);
[196]1399                        par = node1;
1400                        gpos = strlen(genot);
1401                        return 0;  // OK
[760]1402                }
[196]1403                case '#':
[760]1404                {
[196]1405                        // repetition marker, 1 by default
[767]1406                        ExtValue val;
[774]1407                        const char* end = val.parseNumber(genot + gpos + 1, ExtPType::TInt);
[767]1408                        if (end == NULL) i = 1;
1409                        else i = val.getInt();
[196]1410                        // find out genotype start for continuation
1411                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), '>');
1412                        // skip number
1413                        oldpos = gpos;
[767]1414                        gpos += end - (genot + gpos);
1415                        //gpos++;
1416                        //while ((genot[gpos] >= '0') && (genot[gpos] <= '9')) gpos++;node1 = new f4_node("#", par, oldpos);
[760]1417                        node1 = new f4_node("#", par, oldpos);
[196]1418                        node1->i1 = i;
1419                        par = node1;
1420                        res = f4_processrec(genot, gpos, node1);
1421                        if (res) return res;
[671]1422                        if (oldpos + j + 2 < strlen(genot))
1423                        {
[196]1424                                res = f4_processrec(genot, oldpos + j + 2, node1);
1425                                if (res) return res;
1426                        }
[671]1427                        else // ran out
1428                        {
[760]1429                                node1 = new f4_node(">", par, strlen(genot) - 1);
[196]1430                        }
1431                        return 0;  // OK
[760]1432                }
1433                case ' ':
1434                case '\n':
1435                case '\r':
1436                case '\t':
1437                {
1438                        // whitespace: ignore
1439                        gpos++;
1440                        break;
1441                }
[196]1442                case 'l':  case 'L':
1443                case 'c':  case 'C':
1444                case 'q':  case 'Q':
1445                case 'r':  case 'R':
[760]1446                case 'X':  case ',':
[196]1447                case 'a':  case 'A':
1448                case 's':  case 'S':
1449                case 'm':  case 'M':
1450                case 'i':  case 'I':
1451                case 'f':  case 'F':
1452                case 'w':  case 'W':
1453                case 'e':  case 'E':
[760]1454                {
[196]1455                        node1 = new f4_node(genot[gpos], par, gpos);
1456                        par = node1;
1457                        gpos++;
1458                        break;
[760]1459                }
1460                case '@':  case '|':
1461                {
1462                        // in order to prevent the presence of "free muscles", we need to ensure that a muscle is written as N@/N| or N:@/N:|
1463                        if (par != NULL && par->name == "N")
1464                        {
1465                                node1 = new f4_node(genot[gpos], par, gpos);
1466                                par = node1;
1467                                gpos++;
1468                        }
1469                        else
1470                        {
1471                                return gpos + 1;
1472                        }
1473                        break;
1474                }
[193]1475
[760]1476                case 'N':
1477                {
1478                        // if there is no colon after N, then there is no class definition
1479                        if (gpos + 1 >= strlen(genot) || genot[gpos + 1] != ':')
1480                        {
1481                                node1 = new f4_node(genot[gpos], par, gpos);
1482                                par = node1;
1483                                gpos++;
1484                                break;
1485                        }
1486                        // if there is a colon determining neuron parameter, then let the switch case colon handle this
1487                        else if (sscanf(genot + gpos + 1, ":%c%c%[:]", &tc1, &tc2, &tc3) == 3)
1488                        {
1489                                node1 = new f4_node(genot[gpos], par, gpos);
1490                                par = node1;
1491                                gpos++;
1492                                break;
1493                        }
1494                        int forgenorange = gpos;
1495                        gpos += 2; //skipping "N:"
1496                        beginindex = gpos;
[774]1497                        char* end = (char*)genot + beginindex;
[760]1498                        GenoOperators::parseNeuroClass(end);
1499                        gpos += end - genot - beginindex;
1500                        neutype = string(genot + beginindex, genot + gpos);
1501                        node1 = new f4_node(neutype, par, forgenorange);
[196]1502                        par = node1;
1503                        break;
[760]1504                }
[196]1505                case ':':
[760]1506                {
[196]1507                        // neuron parameter  +! -! += -= +/ or -/
[760]1508                        if (sscanf(genot + gpos, ":%c%c%[:]", &tc1, &tc2, &tc3) != 3)
[196]1509                                // error: incorrect format
1510                                return gpos + 1 + 1;
1511                        if ('+' == tc1) j = 1;
1512                        else if ('-' == tc1) j = 0;
1513                        else return gpos + 1 + 1;
[671]1514                        switch (tc2)
1515                        {
[196]1516                        case '!':  case '=':  case '/':  break;
1517                        default:
1518                                return gpos + 1 + 1;
1519                        }
[760]1520                        node1 = new f4_node(":", par, gpos);
[196]1521                        node1->l1 = j;
1522                        node1->i1 = (int)tc2;
1523                        par = node1;
1524                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ':');
1525                        gpos += j + 2;
1526                        break;
[760]1527                }
1528                case '[':
1529                {
1530                        const char *end = parseConnection(genot + gpos, relfrom, w);
1531                        if (end == NULL)
1532                        {
1533                                end = parseConnectionWithNeuron(genot + gpos, neutype, w);
1534                                if (end == NULL) t = -1;
[767]1535                                else t = 1;
[760]1536                        }
1537                        else
1538                        {
1539                                t = 0;
1540                        }
1541                        node1 = new f4_node("[", par, gpos);
1542                        node1->s1 = neutype;
1543                        node1->i1 = t;
1544                        node1->l1 = relfrom;
1545                        node1->f1 = w;
1546                        par = node1;
1547                        j = scanrec(genot + gpos + 1, strlen(genot + gpos + 1), ']');
1548                        gpos += j + 2;
[196]1549                        break;
[760]1550                }
[196]1551                default:
[760]1552                {
[196]1553                        //DB( printf("unknown character '%c' ! \n", genot[gpos]); )
1554                        //add it, build will give the error or repair
1555                        node1 = new f4_node(genot[gpos], par, gpos);
1556                        par = node1;
1557                        gpos++;
1558                        break;
1559                }
[760]1560                }
[196]1561        }
[760]1562
[196]1563        // should end with a '>'
1564        if (par)
[671]1565        {
[760]1566                if (par->name != ">")
[671]1567                {
[196]1568                        node1 = new f4_node('>', par, strlen(genot) - 1);
1569                        par = node1;
1570                }
[671]1571        }
1572
[760]1573        return 0;
[193]1574}
1575
[760]1576const char* parseConnection(const char *fragm, int& relfrom, double &weight)
1577{
1578        const char *parser = fragm;
1579        if (*parser != '[') return NULL;
1580        parser++;
1581        ExtValue val;
1582        parser = val.parseNumber(parser, ExtPType::TInt);
1583        if (parser == NULL) return NULL;
1584        relfrom = val.getInt();
1585        if (*parser != ':') return NULL;
1586        parser++;
1587        parser = val.parseNumber(parser, ExtPType::TDouble);
1588        if (parser == NULL) return NULL;
1589        weight = val.getDouble();
1590        if (*parser != ']') return NULL;
1591        parser++;
1592        return parser;
1593}
[193]1594
[760]1595const char* parseConnectionWithNeuron(const char *fragm, string &neutype, double &weight)
1596{
1597        const char *parser = fragm;
1598        if (*parser != '[') return NULL;
1599        parser++;
[774]1600        char* p = (char*)parser;
[760]1601        if (GenoOperators::parseNeuroClass(p) == NULL) return NULL;
1602        neutype = string(parser, (const char *)p);
1603        parser = p;
1604        if (*parser != ':') return NULL;
1605        parser++;
1606        ExtValue val;
1607        parser = val.parseNumber(parser, ExtPType::TDouble);
1608        if (parser == NULL) return NULL;
1609        weight = val.getDouble();
1610        if (*parser != ']') return NULL;
1611        parser++;
1612        return parser;
1613}
1614
[774]1615f4_node* f4_processtree(const char* geno)
[193]1616{
[774]1617        f4_node *root;
[196]1618        int res;
1619        root = new f4_node();
1620        res = f4_processrec(geno, 0, root);
1621        if (res) return NULL;
1622        //DB( printf("test f4  "); )
1623        DB(
[671]1624                if (root->child)
1625                {
[853]1626                        char* buf = (char*)malloc(300);
1627                        DB(printf("(%d) ", root->child->count());)
1628                                buf[0] = 0;
1629                        root->child->sprintAdj(buf);
1630                        DB(printf("%s\n", buf);)
1631                                free(buf);
[196]1632                }
1633        )
1634                return root->child;
[193]1635}
Note: See TracBrowser for help on using the repository browser.