Programming, Topic: Procedural Content

All posts

Recent posts

Runelang: The Parser (Part 1)

I’m still here! And less sick now.

Last time(s), we described and lexed) Runelang! This time around, let’s take the lexed tokens and go one step further and parse them!

So, how do we go about this? With a recursive descent parser!

  • Start with a list/stream of tokens
  • Using the first k (in a LL(k) parser) elements of the list, identify which sort of object we are parsing (a group / identifier / literal / expression / etc)
  • Call a parsing function for that object type (parseGroup etc) that will:
    • Recursively parse the given object type (this may in turn call more parse functions)
    • Advance the token stream ‘consuming’ any tokens used in this group so the new ‘first’ element is the next object

read more...


Runelang: The Lexer

Let’s LEX!

So this is actually one of the easier parts of a programming language. In this case, we need to turn the raw text of a program into a sequence of tokens / lexemes that will be easier to parse. In this case, we want to:

  • Remove all whitespace and comments
  • Store the row and column with the token to make debugging easier

So let’s do it!

read more...


Runelang: Language Specification

Previously, I wrote a post about making a DSL in Ruby that could render magic circles/runes. It worked pretty well. I could turn things like this:

rune do
    scale 0.9 do 
        circle
        polygon 7
        star 14, 3
        star 7, 2
        children 7, scale: 1/8r, offset: 1 do |i|
            circle
            invert do
                text (0x2641 + i).chr Encoding::UTF_8
            end
        end
    end
    scale 0.15 do
        translate x: -2 do circle; moon 0.45 end
        circle
        translate x: 2 do circle; moon 0.55 end
    end
end

Into this:

But… I decided to completely rewrite it. Now it’s an entirely separate language:

Output

Source

Log (most recent messages first):

    read more...


    Neural Network Cellular Automata

    Okay. A random post on the /r/cellular_automata subreddit inspired me.

    Let’s generate a cellular automata where each pixel updates based on a neural network given as input:

    • The x/y coordinates (scaled to the range 0-1)
    • An optional random value (to make it more dynamic)
    • A variety of neighboring data, such as:
      • The number of neighbors that are ‘active’ (> 50% white), ranges 0-8 scaled to 0-1. This should allow Conway’s Game of Life
      • The RGB values of all neighbors (allows a superset of the above)
      • Gradients, subtract color value of the left from the right so that you get edges and side to side movement

    Let’s do it!

    read more...


    A quick ruby DSL for creating L-Systems

    L-Systems are pretty awesome. With only a bare few rules, you can turn something like this:

    LSystem.new("Barnsley Fern") do
        start "+++X"
    
        rule "X", "F+[[X]-X]-F[-FX]+X" 
        rule "F", "FF"
    
        terminal "F" do forward end
        terminal "[" do push end
        terminal "]" do pop end
        terminal "-" do rotate -25 end
        terminal "+" do rotate +25 end
    end
    

    Into this:

    read more...


    A DSL for rendering magic circles and runes

    Let’s make magic circles/runes!

    Turn this:

    rune do
        scale 0.9 do 
            circle
            polygon 7
            star 14, 3
            star 7, 2
            children 7, scale: 1/8r, offset: 1 do |i|
                circle
                invert do
                    text (0x2641 + i).chr Encoding::UTF_8
                end
            end
        end
        scale 0.15 do
            translate x: -2 do circle; moon 0.45 end
            circle
            translate x: 2 do circle; moon 0.55 end
        end
    end
    

    Into this:

    read more...


    Genuary: Triple Nested Loops

    The fine people of /r/generative / Genuary2021 have a series of challenges for generative works for the month of January. I don’t think I’m going to do all of them, but pick and choose. For example, the very first prompt is:

    // TRIPLE NESTED LOOP

    My goal was to draw a grid of circles across the X/Y the image and nest them for the third dimension. To make it a little more interesting, I added a few different color modes. seededRandom is my personal favorite, that was interesting to get working.

    read more...


    Pictogenesis: Stack Transpiling

    Much like transpiling register machines, now we have a chance to transpile stack machines. Unfortunately, it doesn’t actually speed up the code nearly so much (the stack is just not as effective of a memory structure in this case), but it’s still an interesting bit of code.

    In this case, we turn something like this:

    invsub
    polT
    writeG
    id
    neg
    zero?
    sin
    invsub
    ZERO
    inv
    

    Into this:

    function(X, Y) {
      this.x = X;
      this.y = Y;
    
      this.stack = [];
      this.r = undefined;
      this.g = undefined;
      this.b = undefined;
    
      this.stack.push(X);
      this.stack.push(Y);
    
      var arg0 = 0;
      var arg1 = 0;
      var arg2 = 0;
      var result = 0;
    
      // invsub
      arg0 = this.stack.pop() || 0;
      result = 1 - arg0;
      result = result % 1.0;
      this.stack.push(result);
    
      // polT
      arg0 = this.stack.pop() || 0;
      arg1 = this.stack.pop() || 0;
      result = Math.atan2(arg0, arg1);
      result = result % 1.0;
      this.stack.push(result);
    
      // writeG
      arg0 = this.stack.pop() || 0;
      this.g = arg0;
    
      // id
      arg0 = this.stack.pop() || 0;
      result = arg0;
      result = result % 1.0;
      this.stack.push(result);
    
      // neg
      arg0 = this.stack.pop() || 0;
      result = -arg0;
      result = result % 1.0;
      this.stack.push(result);
    
      // zero?
      arg0 = this.stack.pop() || 0;
      arg1 = this.stack.pop() || 0;
      arg2 = this.stack.pop() || 0;
      result = arg0 === 0 ? arg1 : arg2;
      result = result % 1.0;
      this.stack.push(result);
    
      // sin
      arg0 = this.stack.pop() || 0;
      result = Math.sin(arg0);
      result = result % 1.0;
      this.stack.push(result);
    
      // invsub
      arg0 = this.stack.pop() || 0;
      result = 1 - arg0;
      result = result % 1.0;
      this.stack.push(result);
    
      // ZERO
      result = 0;
      result = result % 1.0;
      this.stack.push(result);
    
      // inv
      arg0 = this.stack.pop() || 0;
      result = 1 / arg0;
      result = result % 1.0;
      this.stack.push(result);
    
    
      return [
        this.r === undefined ? this.stack.pop() || 0 : this.r,
        this.g === undefined ? this.stack.pop() || 0 : this.g,
        this.b === undefined ? this.stack.pop() || 0 : this.b,
      ];
    }
    

    read more...


    Pictogenesis: Stack Machine

    Okay, enough with register machines. Let’s make something new. This time, a stack based machine!

    Rather than keeping it’s memory in a series of memory cells, there will be a single stack of values. All functions can pop values from the top of the stack or push them back on. I will add the ability to read the X/Y value and directly write R/G/B, but you can’t write to the former or read from the latter, so you can’t use them as registers. Let’s see what that looks like!

    read more...


    Pictogenesis: Transpiling

    Okay. That is slow… Let’s make it faster!

    So the main problem we have is that we’re interpreting the code. For every single pixel, for every line of code, we’re doing a few housekeeping things and making at least one function call. For a 400x400 image with just 10 lines of code, that’s 1.6M function calls. Like I said, slow.

    So let’s make it faster!

    My first idea? Transpile it to Javascript!

    read more...