source: cpp/gdk/conv_f1.cpp @ 66

Last change on this file since 66 was 66, checked in by Maciej Komosinski, 13 years ago

set 'eol-style' to 'native'

  • Property svn:eol-style set to native
File size: 11.8 KB
Line 
1// This file is a part of the Framsticks GDK library.
2// Copyright (C) 2002-2011  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "conv_f1.h"
6#include "nonstd.h"
7#include "framsg.h"
8#include "multirange.h"
9#include "multimap.h"
10#include <ctype.h>
11
12//#define v1f1COMPATIBLE
13
14F1Props stdprops={1, 0, 1, 0.4, 0.25, 0.25, 0.25, 0.25, 0.0, 1.0, 1.0, 1 };
15
16class Builder
17{
18public:
19Builder(const char*g,int mapping=0):genbegin(g),usemapping(mapping),energ(0),energ_div(0),invalid(0) {}
20char tmp[222];
21bool invalid;
22Model model;
23const char *genbegin;
24SList neuro_f1_to_f0; // neuro_f1_to_f0(f1_refno) = actual neuro pointer
25Neuro *last_f1_neuro;
26        struct Connection { int n1,n2; double w;
27                Connection(int _n1,int _n2, double _w):n1(_n1),n2(_n2),w(_w) {} };
28SListTempl<Connection> connections;
29int usemapping;
30MultiRange range;
31double lastjoint_muscle_power;
32double energ,energ_div;
33void grow(int part1,const char*g,Pt3D k,F1Props c);
34int growJoint(int part1,int part2,Pt3D &angle,F1Props &c,const char *g);
35int growPart(F1Props &c,const char *g);
36const char *skipNeuro(const char *z);
37const char* growNeuro(const char* t,F1Props &c,int&);
38void growConnection(const char* begin,const char* colon,const char* end,F1Props& props);
39int countBranches(const char*g,SList &out);
40void addClassParam(const SString& newparam);
41void addClassParam(const char* name,double value);
42
43const MultiRange* makeRange(const char*g) {return makeRange(g,g);}
44const MultiRange* makeRange(const char*g,const char*g2);
45Part *getLastPart() {return getLastJoint()->part2;}
46Neuro *getLastNeuro() {return model.getNeuro(model.getNeuroCount()-1);}
47Joint *getLastJoint() {return model.getJoint(model.getJointCount()-1);}
48void addOrRememberInput(int n1,int n2,float w)
49                {
50                //if (!addInput(n1,n2,w,false))
51                connections+=Connection(n1,n2,w);
52                }
53bool addInput(int n1,int n2,float w,bool final)
54                {
55                if ((n1<0) || (n2<0) || (n1>=neuro_f1_to_f0.size()) || (n2>=neuro_f1_to_f0.size()))
56                        {
57                        if (final) FMprintf("GenoConvF1","addInput",FMLV_WARN,
58                                            "illegal neuron connection %d <- %d (ignored)",n1,n2);
59                        return 0;
60                        }
61                Neuro *neuro=(Neuro*)neuro_f1_to_f0(n1);
62                Neuro *input=(Neuro*)neuro_f1_to_f0(n2);
63                neuro->addInput(input,w);
64                return 1;
65                }
66void addPendingInputs()
67                {
68                for(int i=0;i<connections.size();i++)
69                        {
70                        Connection *c=&connections(i);
71                        addInput(c->n1,c->n2,c->w,true);
72                        }
73                }
74};
75
76const MultiRange* Builder::makeRange(const char*g,const char*g2)
77{
78if (!usemapping) return 0;
79range.clear();
80range.add(g-genbegin,g2-genbegin);
81return &range;
82}
83
84void F1Props::wykluczanie()
85{
86double s=ruch+asym+odpor+wchl;
87ruch=ruch/s;
88asym=asym/s;
89odpor=odpor/s;
90wchl=wchl/s;
91}
92
93/** main conversion function - with conversion map support */
94SString GenoConv_F1::convert(SString &i,MultiMap *map)
95{
96const char* g=(const char*)i;
97Builder builder(g,map?1:0);
98builder.model.open();
99builder.grow(-1,g,Pt3D_0,stdprops); // uses Model::singleStepBuild to create model elements
100if (builder.invalid) return SString();
101builder.addPendingInputs();
102builder.model.startenergy=(builder.energ_div>0)?(builder.energ/builder.energ_div):1.0;
103builder.model.close(); // model is ready to use now
104if (map) builder.model.getCurrentToF0Map(*map); // generate f1-to-f0 conversion map
105return builder.model.getF0Geno().getGene();
106}
107
108void Builder::grow(int part1,const char*g,Pt3D k,F1Props c)
109{
110int hasmuscles=0;
111k+=Pt3D(c.rot,0,c.skr);
112while(1)
113{
114switch(*g)
115        {
116        case 0: case ',': case ')': return;
117        case 'R': k.x+=0.7853;  break;
118        case 'r': k.x-=0.7853;  break;
119        case 'Q': c.rot+=(1.58-c.rot)*0.3;      break;
120        case 'q': c.rot+=(-1.58-c.rot)*0.3;     break;
121#ifdef v1f1COMPATIBLE
122        case 'L': c.dlug+=(3.0-c.dlug)*0.3; break;
123#else
124        case 'L': c.dlug+=(2.0-c.dlug)*0.3; break;
125#endif                                       
126        case 'l': c.dlug+=(0.33-c.dlug)*0.3; break;
127        case 'A': c.asym+=(1-c.asym)*0.8;       c.wykluczanie(); break;
128        case 'a': c.asym-=c.asym*0.4;   c.wykluczanie(); break;
129        case 'I': c.wchl+=(1-c.wchl)*0.8;       c.wykluczanie(); break;
130        case 'i': c.wchl-=c.wchl*0.4;   c.wykluczanie(); break;
131        case 'S': c.odpor+=(1-c.odpor)*0.8; c.wykluczanie(); break;
132        case 's': c.odpor-=c.odpor*0.4; c.wykluczanie(); break;
133        case 'M': c.ruch+=(1-c.ruch)*0.8;       c.wykluczanie(); break;
134        case 'm': c.ruch-=c.ruch*0.4;   c.wykluczanie(); break;
135        case 'C': c.skr+=(2.0-c.skr)*0.25;      break;
136        case 'c': c.skr+=(-2.0-c.skr)*0.25;break;
137        case 'F': c.tarcie+=(4-c.tarcie)*0.2;   break;
138        case 'f': c.tarcie-=c.tarcie*0.2;               break;
139        case 'W': c.masa+=(2.0-c.masa)*0.3;     break;
140        case 'w': c.masa+=(0.5-c.masa)*0.3;     break;
141        case 'E': c.energ+=(10.0-c.energ)*0.1;  break;
142        case 'e': c.energ-=c.energ*0.1;         break;
143        case '[': //neuron
144//              setdebug(g-(char*)geny,DEBUGNEURO | !l_neu);
145                if (model.getJointCount())
146                        g=growNeuro(g+1,c,hasmuscles);
147                else
148                        {
149                        FramMessage("GenoConv_F1","grow","Illegal neuron position (ignored)",1);
150                        g=skipNeuro(g+1);
151                        }
152                break;
153        case 'X':
154                {
155                int freshpart=0;
156//setdebug(g-(char*)geny,DEBUGEST | !l_est);
157                if (part1<0) //initial grow
158                        {
159                  if (model.getPartCount()>0)
160                            part1=0;
161                    else
162                            {
163                            part1=growPart(c,g);
164                            freshpart=1;
165                            }
166                  }
167                if (!freshpart)
168                        {
169                        Part *part=model.getPart(part1);
170                        part->density=((part->mass*part->density)+1.0/c.masa)/(part->mass+1.0); // v=m*d
171//                      part->volume+=1.0/c.masa;
172                        part->mass+=1.0;
173                        }
174                energ+=0.9*c.energ+0.1;
175                energ_div+=1.0;
176
177                int part2 = growPart(c,g);
178                growJoint(part1,part2,k,c,g);
179//              est* e = new est(*s,*s2,k,c,zz,this);
180
181                // oslabianie cech wzdluz struktury
182                c.dlug=0.5*c.dlug+0.5*stdprops.dlug;
183                c.skr=0.66*c.skr;
184                c.rot=0.66*c.rot;
185                c.tarcie=0.8*c.tarcie+0.2*stdprops.tarcie;
186
187                c.asym=0.8*c.asym+0.2*stdprops.asym;
188                c.odpor=0.8*c.odpor+0.2*stdprops.odpor;
189                c.ruch=0.8*c.ruch+0.2*stdprops.ruch;
190                c.wchl=0.8*c.wchl+0.2*stdprops.wchl;
191                c.masa+=(stdprops.masa-c.masa)*0.5;
192                c.wykluczanie();
193       
194                if (c.resetrange) c.bendrange=1.0; else c.resetrange=1;
195                grow(part2,g+1,Pt3D_0,c);
196                return;
197                }
198        case '(':
199                {
200                SList ga;
201                int i,ile;
202                ile=countBranches(g+1,ga);
203                c.resetrange=0;
204                c.bendrange=1.0/ile;
205                for (i=0;i<ile;i++)
206                        grow(part1,(char*)ga(i),k+Pt3D(0,0,-3.141+(i+1)*(6.282/(ile+1))),c);
207                return;
208                }
209        case ' ': case '\t': case '\n': case '\r': break;
210        default: invalid=1; return;
211        }
212        g++;
213        }
214}
215
216void Builder::addClassParam(const SString& newparam)
217{
218SString allparams=last_f1_neuro->getClassParams();
219if (allparams.len()) allparams+=',';
220allparams+=newparam;
221last_f1_neuro->setClassParams(allparams);
222}
223void Builder::addClassParam(const char* name,double value)
224{
225SString t;
226sprintf(t.directWrite(30),"%s=%g",name,value);
227t.endWrite();
228addClassParam(t);
229}
230
231
232int Builder::countBranches(const char*g,SList &out)
233{
234int gl=0;
235out+=(void*)g;
236while (gl>=0)
237        {
238        switch(*g)
239                {
240                case 0: gl=-1; break;
241                case '(': case '[': ++gl; break;
242                case ')': case ']': --gl; break;
243                case ',': if (!gl) out+=(void*)(g+1);
244                }
245        g++;
246        }
247return !out;
248}
249
250int Builder::growJoint(int part1,int part2,Pt3D &angle,F1Props &c,const char *g)
251{
252double len=min(2.0,c.dlug);
253sprintf(tmp,"j:p1=%ld,p2=%ld,dx=%lg,rx=%lg,ry=%lg,rz=%lg,stam=%lg",
254        part1,part2,len,angle.x,angle.y,angle.z,c.odpor);
255lastjoint_muscle_power=c.ruch;
256return model.singleStepBuild(tmp,makeRange(g));
257}
258
259int Builder::growPart(F1Props &c,const char *g)
260{
261sprintf(tmp,"p:m=1,dn=%lg,fr=%lg,ing=%lg,as=%lg",
262        1.0/c.masa,c.tarcie,c.wchl,c.asym);
263return model.singleStepBuild(tmp,makeRange(g));
264}
265
266const char *Builder::skipNeuro(const char *z)
267{
268for (;*z;z++) if ((*z==']')||(*z==')')) break;
269return z-1;
270}
271
272const char* Builder::growNeuro(const char* t, F1Props& props,int &hasmuscles)
273{
274const char*neuroend=skipNeuro(t);
275last_f1_neuro=model.addNewNeuro();
276last_f1_neuro->attachToPart(getLastPart());
277const MultiRange *mr=makeRange(t-1,neuroend+1);
278if (mr) last_f1_neuro->setMapping(*mr);
279neuro_f1_to_f0+=last_f1_neuro;
280
281SString clsname;
282bool haveclass=0;
283while(*t && *t<=' ') t++;
284const char* next=(*t)?(t+1):t;
285while(*next && *next<=' ') next++;
286if (*t && *next!=',' && *next!=']') // old style muscles [|rest] or [@rest]
287switch(*t)
288        {
289        case '@': if (t[1]==':') break;
290                haveclass=1;
291//              if (!(hasmuscles&1))
292                {
293                  hasmuscles|=1;
294                  Neuro *muscle=model.addNewNeuro();
295                  sprintf(tmp,"@:p=%lg",lastjoint_muscle_power);
296                  muscle->addInput(last_f1_neuro);
297                  muscle->setDetails(tmp);
298                  muscle->attachToJoint(getLastJoint());
299                  if (usemapping) muscle->setMapping(*makeRange(t));
300                }
301                t++;
302                break;
303        case '|': if (t[1]==':') break;
304                haveclass=1;
305//              if (!(hasmuscles&2))
306                {
307                  hasmuscles|=2;
308                  Neuro *muscle=model.addNewNeuro();
309                  sprintf(tmp,"|:p=%lg,r=%lg",lastjoint_muscle_power,props.bendrange);
310                  muscle->addInput(last_f1_neuro);
311                  muscle->setDetails(tmp);
312                  muscle->attachToJoint(getLastJoint());
313                  if (usemapping) muscle->setMapping(*makeRange(t));
314                }
315                t++;
316                break;
317        }
318while(*t && *t<=' ') t++;
319bool finished=0;
320const char *begin=t;
321const char* colon=0;
322SString classparams;
323while(!finished)
324        {
325        switch (*t)
326                {
327                case ':': colon=t; break;
328                case 0: case ']': case ')': finished=1;
329                        // NO break!
330                case ',':
331                        if ( !haveclass && !colon && t>begin )
332                                {
333                                haveclass=1;
334                                SString clsname(begin,t-begin);
335                                clsname=trim(clsname);
336                                last_f1_neuro->setClassName(clsname);
337                                NeuroClass *cls=last_f1_neuro->getClass();
338                                if (cls)
339                                        {
340                                        if (cls->getPreferredLocation()==2)
341                                                last_f1_neuro->attachToJoint(getLastJoint());
342                                        else if (cls->getPreferredLocation()==1)
343                                                last_f1_neuro->attachToPart(getLastPart());
344                                        }
345                                }
346                        else if (colon && (colon>begin) && (t>colon))
347                                growConnection(begin,colon,t,props);
348                        if (t[0]!=',') t--;
349                        begin=t+1; colon=0;
350                        break;
351                }
352        t++;
353        }
354return t;
355}
356void Builder::growConnection(const char* begin, const char* colon,const char* end,F1Props& props)
357{
358while(*begin && *begin<=' ') begin++;
359int i;
360if (isdigit(begin[0]) || (begin[0]=='-'))
361        {
362        float weight=atof(colon+1);
363        int relative=atoi(begin);
364        int this_refno=neuro_f1_to_f0.size()-1;
365        addOrRememberInput(this_refno,this_refno+relative,weight);
366        }
367else if ((i=last_f1_neuro->extraProperties().findIdn(begin,colon-begin))>=0)
368        {
369        last_f1_neuro->extraProperties().set(i,colon+1);
370        }
371else if (isupper(begin[0]) || strchr("*|@",begin[0]))
372        {
373        SString clsname(begin,colon-begin);
374        trim(clsname);
375        Neuro *receptor=model.addNewNeuro();
376        receptor->setClassName(clsname);
377        NeuroClass *cls=receptor->getClass();
378        if (cls)
379                {
380                if (cls->getPreferredLocation()==2) receptor->attachToJoint(getLastJoint());
381                else if (cls->getPreferredLocation()==1) receptor->attachToPart(getLastPart());
382                }
383        last_f1_neuro->addInput(receptor,atof(colon+1));
384        if (usemapping) receptor->setMapping(*makeRange(begin,end-1));
385        }
386else if ((begin[0]=='>')&&(begin[1]))
387        {
388        Neuro *out=model.addNewNeuro();
389        out->addInput(last_f1_neuro,atof(colon+1));
390        out->setClassName(SString(begin+1,end-colon-1));
391        if (begin[1]=='@')
392                {
393                sprintf(tmp,"p=%lg",lastjoint_muscle_power);
394                out->setClassParams(tmp);
395                }
396        else if (begin[1]=='|')
397                {
398                sprintf(tmp,"p=%lg,r=%lg",lastjoint_muscle_power,props.bendrange);
399                out->setClassParams(tmp);
400                }
401        NeuroClass *cls=out->getClass();
402        if (cls)
403                {
404                if (cls->getPreferredLocation()==2) out->attachToJoint(getLastJoint());
405                else if (cls->getPreferredLocation()==1) out->attachToPart(getLastPart());
406                }
407        if (usemapping) out->setMapping(*makeRange(begin,end-1));
408        }
409else if (*begin=='!') addClassParam("fo",max(0.0,min(1.0,atof(colon+1))));
410else if (*begin=='=') addClassParam("in",max(0.0,min(1.0,atof(colon+1))));
411else if (*begin=='/') addClassParam("si",atof(colon+1));
412/*else if (*begin=='!') last_f1_neuro->force=max(0.0,min(1.0,atof(colon+1)));
413else if (*begin=='=') last_f1_neuro->inertia=max(0.0,min(1.0,atof(colon+1)));
414else if (*begin=='/') last_f1_neuro->sigmo=atof(colon+1);
415*/
416else if (islower(begin[0]))
417        {
418        SString newparam(begin,end-begin);
419        trim(newparam);
420        newparam.directWrite()[colon-begin]='='; // ':' -> '='
421        addClassParam(newparam);
422        }
423}
Note: See TracBrowser for help on using the repository browser.