def produce(self): pos = 0 current = self._lstring new = LString([]) skip = 0 self._lastInterpreted = None if self._reseed: self._nextSeed = self._seed self._reseed = False random.seed(self._nextSeed) self._nextSeed = random.randint(0, pow(2, 31)) while pos < len(current): m = current[pos] if m == CUT: skip = 1 if skip == 1 and isinstance(m, RB): skip = 0 elif skip > 0: if isinstance(m, LB): skip = skip + 1 elif isinstance(m, RB): skip = skip - 1 continue found = False for formals, production in self._productions: actuals = formals.match(current, pos, self._consider, self._ignore) if actuals <> None: # We found a matching production and need to apply it found = True p = production.produce(actuals, self._data) if p == None: # Viewed as a bug in the production implementation raise LException( "Production %s return NoneType object" % production) else: # We have a proper production if type(p) == TupleType: new.extend(flatten(p)) elif type(p) == ListType: new.extend(flatten([p])) elif p == EPSILON: # Empty production so we just toss it pass else: new.append(p) break if not found: # We found no matching production and need to apply the identity production instead new.append(current[pos]) pos = pos + 1 self._lstring = new self._currentDepth += 1 return self._lstring
def declare(self, production): if not isinstance(production, Production): raise LException("LSystem.declare(): %s is not an LProduction" % production) formals = production.context() if not formals.encoded(): formals.encode() self._productions.append((formals, production))
def _interpret(lstring, data, turtle): new = LString([]) for m in lstring: d = m.interpret(data) if d == None: raise LException( "NoneType object returned as a result of %s.interpret()" % m) elif type(d) == TupleType: new.extend(_interpret(LString(flatten(d)), data, turtle)) elif type(d) == ListType: new.extend(_interpret(LString(flatten([d])), data, turtle)) elif d == EPSILON: continue elif isinstance(d, PrimitiveModule): d.accept(turtle) new.append(d) elif isinstance(d, BaseModule): new.extend(_interpret(LString([d]), data, turtle)) else: raise LException( "Unknown object %s returned during %s.decompose()" % (d, m)) return new
def _decompose(lstring, data): new = LString([]) skip = 0 for m in lstring: if m == CUT and skip == 0: skip = 1 if skip == 1 and isinstance(m, RB): skip = 0 elif skip > 0: if isinstance(m, LB): skip = skip + 1 elif isinstance(m, RB): skip = skip - 1 continue d = m.decompose(data) if d == None: raise LException( "NoneType object returned as a result of %s.decompose()" % m) elif type(d) == TupleType: new.extend(_decompose(LString(flatten(d)), data)) elif type(d) == ListType: new.extend(_decompose(LString(flatten([d])), data)) elif d == EPSILON: continue elif isinstance(d, BaseModule): if d == m: # Fixed point new.append(d) else: new.extend(_decompose(LString([d]))) else: raise LException( "Unknown object %s returned during %s.decompose()" % (d, m)) return new
def accept(self, v): # PrimitiveLModules has to override this raise LException("Abstract method")
def level(self, module): if self.inPoly: raise LException("p() not allowed inside a polygon") self.state.level()
def pitch(self, module): if self.inPoly: raise LException("p() not allowed inside a polygon") self.state.pitch(module.angle)
def roll(self, module): if self.inPoly: raise LException("r() not allowed inside a polygon") self.state.roll(module.angle)
def yaw(self, module): if self.inPoly: raise LException("y() not allowed inside a polygon") self.state.yaw(module.angle)
def forward(self, module): if self.inPoly: raise LException("F() not allowed inside a polygon") # Order is important: Need start position in module but end position for subsequent calculations self.saveStateInModule(module) self.state.move(module.length)