Final Project – 3D Procedural Creature Generator

https://editor.p5js.org/oae233/full/lk6Id6oVL

Concept / Idea

In my midterm, I recreated the visual components of the body using & coding logic and used them as the “paint” to create my artwork, in an attempt to explore the concept of the body. For my final I wanted to focus on the aspect of recreating bodies in 3D space, trying to replicate the biological logic behind how they are assembled. I broke down different parts of the body that are shared among a variety of creatures and thought about how to recreate them, with varying attributes that produce both familiar and wildly new forms.

I hope that my project can leave users with a sense of connectedness with different life forms no matter how physically different we might be.

Implementation:

For this project, I implemented my knowledge gained from the course about using randomness, noise, oscillation/waves, class handling, and trigonometry logic.

I start by generating points in 3D space and then draw lines to connect them. this creates the skeleton or base of my creature. Then I use points on these lines to place different 3D primitives, orienting them based on the lines’ direction.

I only implemented this idea to the spine (which creates the main body) and arms and legs.

Some code I want to highlight:

ThreeD(i) {
    // push();
    // this.radius2 = this.radius1/(i+1);
    this.length = p5.Vector.sub(this.startPoint, this.endPoint);
    this.nextlength = p5.Vector.sub(this.nextstartPoint, this.nextendPoint);

    this.distance = p5.Vector.dist(this.startPoint, this.endPoint);
    this.division = this.distance / 2;
    this.lengthStep = p5.Vector.div(this.length, this.division);
    this.facing = this.length.heading();
    this.nextfacing = this.nextlength.heading();

    this.anglediff = this.facing - this.nextfacing;

    this.anglediff /= this.division;
    // this.counter+=0.5;

    for (let w = 0; w <= this.division; w++) {
      this.sinwav = map(i, 0, this.bodyparts, 0, 90);
      this.counter += 0.04;
      // this.radius2 = this.radius1/this.counter;
      this.radius2 =
        (this.radius1 / this.counter) *
          this.Rmax *
          cos(this.shift + this.sinwav * this.stretch) +
        this.Rmin;
      this.radius2 = constrain(this.radius2, 2, 100);
      push();
      noStroke();
      translate(
        this.startPoint.x - this.lengthStep.x * w,
        this.startPoint.y - this.lengthStep.y * w,
        this.startPoint.z - this.lengthStep.z * w
      );
      rotate(90);
      rotate(this.facing);
      cylinder(this.radius2, 5);
      pop();
      if (w > this.division - 1) {
        for (let z = 0; z < this.division; z++) {
          push();
          // print(z);
          noStroke();
          translate(
            this.startPoint.x - this.lengthStep.x * w,
            this.startPoint.y - this.lengthStep.y * w,
            this.startPoint.z - this.lengthStep.z * w
          );
          rotate(90);

          rotate(this.facing - this.anglediff * z);
          cylinder(this.radius2, 5);
          pop();
        }
      }
    }
  }
}

This is the function that turns the line skeletons into 3D shapes. As u can see I use the length of the line (this.distance) to distribute the shapes at constant density across all lines.

I also modulate the radius using various waves to create variation.

Happy Accidents:

Tip: use your mouse to move around this shape!

 

IM Showcase:

Future work:

For future work I’d love to complete the project, adding support for heads, and individual facial features like mouth and eyes, that can generate vastly different forms from beaks and simple eyes, to toothful jaws and compound eyes. This was what I had hoped to do in the beginning but unfortunately I was unable to complete it on time.

Cellular Automata – Week #10

https://editor.p5js.org/oae233/sketches/raawVHP82

Concept / Idea

For this assignment, I really struggled to come up with a concept. I also would get stuck for a long time just playing around with the Game of Life demos online ahahah. I found some of them very interesting (like the Gosper glider gun & the concept of gliders in general) I thought about doing something related to gliders, which are basically a setup of cells that forms a loop and moves across the canvas diagonally, but eventually, I felt that visually it wasn’t what I wanted to do. I ended up just loading the Game of Life code from the P5JS website (https://p5js.org/examples/simulate-game-of-life.html) into a sketch of mine and playing around with it. Eventually, I came across some settings I liked.

The initial setup draws this beautiful erupting pattern that eventually descends into chaos. I played around with the rules to create a version that never reaches stability / is in constant motion (I basically added a rule that a dead cell also comes alive it has 4 neighbors) and then added another rule that turns cells with 7 neighbors into a 3rd color. I like the idea of playing with 3 colors In most of my sketches. Finally, the faded background and blur canvas filter help bring the effect together.

For interactivity, I added the ability for users to change the 3 colors of the main sketch, a button to reset the animation, and a slider to control the frame rate.

Some code I want to highlight:

   

if      ((board[x][y] == 1) && (neighbors <  2)) next[x][y] = 0;           // Loneliness

      else if ((board[x][y] == 1) && (neighbors >  3)) next[x][y] = 0; 

       else if ((board[x][y] == 2) && (neighbors >  3)) next[x][y] = 0;

       else if ((board[x][y] == 2) && (neighbors < 2)) next[x][y] = 0;

      

      // Overpopulation

      else if ((board[x][y] == 0) && (neighbors == 3)) next[x][y] = 1; 

      else if ((board[x][y] == 0) && (neighbors == 4)) next[x][y] = 1;    

      

      else if ((board[x][y] == 0) && (neighbors == 7)) next[x][y] = 2;

 

These are all the rules I used

Future work:

I want to add more interactivity to the project, maybe have a couple of different patterns people can choose from or have users be able to draw on the canvas as well.

Physics Playground – Matter.js – Week #9

https://editor.p5js.org/oae233/sketches/Ci6eLCTM_

Concept / Idea

For this assignment, I wanted to create something like an interactive playground where users can play around with objects and manipulate them to create/build interesting compositions.

I have 3 types of shapes, triangles that float upwards, circles that fall downwards, and squares that are gravity-neutral. Users can move the shapes around, using their forces to hold them together in interesting places. You can generate any one of these shapes at any time, and either expand them or contract them. The force acting on them changes proportionally to the change in size/ mass.

 

if (this.body.position.x > (zone1.x - 40) && this.body.position.y > (zone1.y - 40) && this.body.position.x < (zone1.x + 40) && this.body.position.y < (zone1.y + 40)&& mouseX > (zone1.x - 40) && mouseY > (zone1.y - 40) && mouseX < (zone1.x + 40) && mouseY < (zone1.y + 40)){

      Body.scale(this.body,1.01,1.01);

      this.r*=1.01;

    } else if (this.body.position.x > (zone2.x - 40) && this.body.position.y > (zone2.y - 40) && this.body.position.x < (zone2.x + 40) && this.body.position.y < (zone2.y + 40)&& mouseX > (zone2.x - 40) && mouseY > (zone2.y - 40) && mouseX < (zone2.x + 40) && mouseY < (zone2.y + 40)){

      Body.scale(this.body,0.99,0.99);

      this.r*=0.99

    }

  }

 

This is how I check if the mouse & and object are in the designated active area and then scale the object accordingly.

Future work:

I’d love to add more features, like giving the user the ability to switch an object’s gravity / force acting upon it. I’m thinking this could be done as two baskets, one upside down and one upright, and when u put an object in it and click the mouse it flips the sign of the force acting on the object.

School of fish – Week 8

https://editor.p5js.org/oae233/sketches/0fc6TGzO4

Concept / Idea

For this assignment, I had already done bird flocking for a previous assignment so I wanted to do something slightly different this time, but still try to capture the essence of watching some of the flocking behaviours in real life. I wanted to recreate the vibe of an underwater camera capturing the motion of fish flocking behavior, and how they reflect light as they move through water.

Implementation:

I wanted the fish to be 3d so I used a for loop that draws boxes consecutively with varying sizes using a sin wave, then used another sin wave to move these boxes from left to right, and another one with a longer wavelength for up and down movement, this gives me the movement of the fish swimming.

For the effect of depth in the water (fish further away from the camera are more blue and faded while closer fish are whiter and clearer) I drew planes at 5 percent opacity each and placed them spread out along the Z-axis. I’ve found that this successfully mimics the effect I was looking for.

Some code I want to highlight:

    

for (let i = -10; i < 10; i++){

      let x = map(i,-10,10,0,PI);

      let y = map(i,-10,10,0,TWO_PI);

      this.z += 0.01;

      this.changeInDir = p5.Vector.sub(this.initDir,this.vel);

      this.changeInDir.normalize();

      push();

      this.changeInDir.mult(45);

      

      angleMode(DEGREES);

      rotateX(this.changeInDir.y);

      rotateY(-this.changeInDir.x*2);

      rotateZ(this.changeInDir.z);

      angleMode(RADIANS);

      translate(2*cos(y+this.z*3),5*cos(x+this.z/5),i*3);

       strokeWeight(0.2);

      fill(130);

        specularMaterial(250);

      box(10*sin(x),20*sin(x),3);

      pop();

    }

This code block is from the render() function of the boids/fish. You can see that I’m using the change in direction to rotate the fish’s body to face the direction it’s swimming in. It was challenging for me to figure this out exactly, especially in 3 dimensions. This setup I’ve found works best through some trial and error. It is not perfect though.

Future work:

I’d love to fix the issues with the fish rotating abruptly at some point. I’d also love to add more complex geometry to the fish body, add some variations between them, and increase the number of fish.

Body Soup – Midterm Assignment

Concept / Idea:

For this assignment, I was inspired by the human body, which I think is one of nature’s greatest wonders. More specifically not by its physical ability, but by its visual potential. What I mean by its visual potential is the ability of the body to grab & maintain attention, visually communicate thought & emotion, and finally visually evoke feelings in others.

With the body there’s this dichotomy, on one side there is this element of commonality or basic core structure, a “skeleton, but on the other side, there’s nuance, subtleties, and little differences that produce individual uniqueness out of extreme diversity. This reminds me a lot of generative art & object-oriented programming & I really wanted to bring both together.

The human body has always been a popular subject in art throughout history, religious, official, and personal & I thought I’d extend that tradition by tackling it in this new medium I’m learning (p5.js)

Logic:

I started out looking at the skeleton of things, trying to come up with what the cookie cutter of a body or face would be like. I divided the body into two different categories, “the headless body” and “the face” because I think each of these has a unique separate visual quality that I wanted to tackle.

The headless body:


This sketch is running in WEBGL, and uses multiple planes placed in the same x & y coordinates but different z coordinates. Initially, the logic behind this was to have planes at different opacities and sizes overlayed / stacked to look like a body.

Scaling up:

Some code I want to highlight:

class Cluster {
  constructor(size,leader) {
    this.mouse = leader;
    this.pos = createVector();
    this.humansList = [new Human(this.mouse)];
    this.size = 10;
    this.type = random(5);
    if (this.type < 1) {
      for (let i = 0; i < this.size; i++) {
        this.humansList.push(new Human(this.humansList[i].handRight));
        this.humansList.push(new Human(this.humansList[i].footRight));
      }
    } else if (this.type < 2) {
      for (let i = 0; i < this.size; i++) {
        this.humansList.push(new Human(this.humansList[i].handRight));
      }
    } else if (this.type < 3) {
      for (let i = 0; i < this.size; i++) {
        this.humansList.push(new Human(this.humansList[i].handRight));
        this.humansList.push(new Human(this.humansList[i].footRight));
        this.humansList.push(new Human(this.humansList[i].hipLeft));
      }
    } else if (this.type < 4) {
      for (let i = 0; i < this.size; i++) {
        this.humansList.push(new Human(this.mouse));
      }
    } else if (this.type < 5) {
      for (let i = 0; i < this.size; i++) {
        if (i < this.size / 2) {
          this.humansList.push(new Human(this.humansList[i].handRight));
          this.humansList.push(new Human(this.humansList[i].handLeft));
        } else {
          this.humansList.push(new Human(this.humansList[i].waist));
          this.humansList.push(new Human(this.humansList[i].shoulderRight));
        }
      }
    }
  }

  render() {
    for (let i = 0; i < this.size; i++) {
      this.humansList[i].render();
    }
  }
}

This code changes how different skeletons are connected to each other based on a random number to create variations that add up and can be seen in a cluster’s shape/movement.

XY Plotter result:

https://drive.google.com/file/d/1gGS_PLDxK66WoZ4x9QCe_aWjSFaERHGQ/view

https://drive.google.com/file/d/14HSQoOd8wGrcDyLQdTE86XtFZQxG5-bO/view

The Face:

Some code I want to highlight:

class Eye {
  constructor() {
    this.pos = createVector(0, 0);
    this.eyeheight = 2 * random(0.6, 1.4);
    this.eyewidth = 10 * random(0.6, 1.2);
    this.r = this.eyeheight;
    this.eyetilt = createVector(random(-0.3, 0.4), random(-0.3, 0.4));
    this.eyeslope = random(1, 1.5);
  }
  render() {
    let multiplier = 10;
    push();
    translate(this.pos.x, this.pos.y);

    fill(255);
    beginShape();

    for (let i = 0; i <= 10; i++) {
      let w = map(i, 0, 10, PI, 0);
      let x = map(i, 0, 10, this.eyewidth / 2, -this.eyewidth / 2);
      let y = this.eyeheight * -sin(w);
      y -= this.eyeheight * sin(w * this.eyeslope) * this.eyetilt.x;

      vertex(x * multiplier, y * multiplier);
    }
    for (let i = 0; i <= 10; i++) {
      let w = map(i, 0, 10, 0, PI);
      let x = map(i, 0, 10, -this.eyewidth / 2, this.eyewidth / 2);
      let y = this.eyeheight * sin(w);
      y -= this.eyeheight * sin(w * this.eyeslope) * this.eyetilt.y;

      vertex(x * multiplier, y * multiplier);
    }

    for (let i = 0; i <= 1; i++) {
      let w = map(i, 0, 10, PI, 0);
      let x = map(i, 0, 10, this.eyewidth / 2, -this.eyewidth / 2);
      let y = this.eyeheight * -sin(w);
      y -= this.eyeheight * sin(w * this.eyeslope) * this.eyetilt.x;

      vertex(x * multiplier, y * multiplier);
    }

    endShape();
    fill(0);
    ellipse(0, 0, this.eyeheight * 15);
    pop();
  }
}

I used different sine waves with phases & amplitudes that change at random and added them together to get different shapes of eyelids.

Scaling up:

 

Putting them together:

https://youtu.be/Q_Og8rGYwWs

Week #4 Coding Assignment – Oscillation

(I couldn’t post this on time because I couldn’t log in to WordPress, thanks for understanding).

https://editor.p5js.org/oae233/sketches/dF00ekRNz

Concept / Idea

So for my original concept, I wanted to draw a circle with the beginShape() function, which I knew how to do, but then I wanted each point on the circle to oscillate between being at the center of the circle and being at the edge, and I wanted each point to be on a different phase/period. I also planned to introduce some random movement to the vertex separately so that the shape can transform and morph.

What I ended up with is basically a collection of semi-failed attempts at what i just described. Every time I would encounter something I found visually interesting, I’d play around with it until I was satisfied with it, then give the original plan another go.

Ultimately I wasn’t able to achieve what I wanted but I ended up with something that I felt was quite rewarding, a record of the process that continuously created appealing visuals.

Some Code:

beginShape();

  for (let x = 0; x <= TWO_PI; x += PI / 30) {

    vertex(R * cos(x), R * sin(x));

  }

  endShape();

 

This is the base code for every shape in my sketch. This code draws a circle with the radius of “R”. Using the “t” variable in a sine/cosine function [eg: sin(t/50], I am able to vary different attributes of the circle.

Future work:

For the future of this project, I’d like to add to a successful implementation of my original idea of the morphing shape. I also think it would be great to make a class out of the code block above, and just feed different values to different instances of that class to create all the varying shapes.

Week #3 Coding Assignment – Movers & Attractors

https://editor.p5js.org/oae233/sketches/PY1m1F8nQ

Concept / Idea

Originally, I wanted to use invisible attractors with a minimum distance between the attractor & the movers to create the shape of a human skeleton. I would then have this object as a class and have different skeletons attract and repel each other at various points. After I implemented the minimum distance function, I realised that I quite liked the effect it creates with movers, especially when connected to some user input, like the mouse position, it felt like catching the movers in a net and then you’re able to fling them back into an orbit. The lines drawn from the movers to the attractor and the trail effect add interesting visual details.

Functions

So I only added two functions from the ones that were in the original example.

distCheck():

 this function continuously checks if the ditsance between a mover and the attractor is less than that movers minimum distance (defined as distLimit), and if it is, it sets the velocity and acceleration of that mover to 0, causing it to stop

wind():

 this function calls the applyForce function to apply wind with a random direction & magnitude (between certain specified values) only when the mouse is pressed. The purpose of this function is to “shake things up a bit” when the user wants to. Because of the randomness of the wind, the movers stuck to the attractor break free while going at different directions, which makes them more likely to go into interesting orbits instead of just uniformly moving away from the attractor. Other movers lose thier orbit and stick to the attractor instead.

Some code I want to highlight:

I thought I’d highlight the two functions I mentioned above just to show how they would work.

 // "that" , opposed to this, is the attractor, it is passed through to this function in the sketch.js file draw() function 
  distCheck(that) {
    let dist = p5.Vector.dist(this.pos, that.pos);
    if ( dist < this.distLimit){
      this.vel.set(0);
      this.acc.set(0);     
        }  
  }

  wind(){
    if (mouseIsPressed){
    let windy = createVector(random(-10,20),random(-10,5));
    this.applyForce(windy);
    }
  }
}

 

Future work:

I think it would be really interesting to implement my initial idea and create a skeleton using attractors with distance limits between them and their movers and watch how such a structure might react under different forces acting upon it. I also think more could be done in this example to make it look more visually developed or complex, maybe making the shapes of the movers more dynamic instead of a static circle.

Week #2 Coding Assignment, Cairo Skyline

https://editor.p5js.org/oae233/sketches/JMRwbzGgE

Concept

For this assignment I wanted to simulate the movement of a flock of pigeons and the way they fly in unison, mainly inspired by the Cairo skyline and its pigeon towers. I found a lot of information about how exactly to do this online, one beneficial resource was Craig Reynolds’s blog on the topic, and I found a tutorial by Daniel Schiffman on how exactly to implement this. The tutorial made a 2D flocking simulation, I applied the same principles to 3D, added some stylistic choices, and adjusted values so that the most reminiscent of the pigeon flock movement.

Some Code I’m Proud Of

class pigeonTower {
  constructor() {
    // Define the size and corners of the pigeon tower
    this.size = createVector(200, 100);
    this.tlcorner = createVector(-this.size.x / 2, -this.size.y / 2);
    this.blcorner = createVector(-this.size.x / 2, this.size.y / 2);
    this.trcorner = createVector(this.size.x / 2, -this.size.y / 2);
    this.brcorner = createVector(this.size.x / 2, this.size.y / 2);
    this.maincolor = [38, 141, 0];// Main color for the tower
    this.secondarycolor = [190, 180, 80]; // Secondary color for the tower
  }
  render() {
    push();
    translate(width / 2, height / 2);
    stroke(0);
    strokeWeight(1);
    // Draw the main body of the tower
    fill(this.maincolor);
    rect(-this.size.x / 2, -this.size.y / 2, this.size.x, this.size.y);
    
    fill(this.secondarycolor);
    triangle(
      this.tlcorner.x,
      this.tlcorner.y,
      this.blcorner.x,
      this.blcorner.y,
      -30,
      0
    );
    triangle(
      this.trcorner.x,
      this.trcorner.y,
      this.brcorner.x,
      this.brcorner.y,
      30,
      0
    );
    push();
    rotate(0.785);
    rect(-22.5, -22.5, 45, 45);
    pop();
    fill(19, 71, 0);
    rect(this.blcorner.x, this.blcorner.y, 10, 200);
    rect(this.brcorner.x, this.brcorner.y, -10, 200);
    push();
    rotate(-1);
    rect(this.blcorner.x, this.blcorner.y - 98, 10, 220);
    rotate(2);
    rect(this.brcorner.x, this.brcorner.y - 98, -10, 220);
    pop();
    push();
    fill(0, 110, 149);
    triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 30);
    triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
    translate(40, 0);
    triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 35);
    triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
    translate(-80, 0);
    triangle(-20, this.blcorner.y, 20, this.brcorner.y, 0, 35);
    triangle(-20, -this.blcorner.y, 20, -this.brcorner.y, 0, -30);
    pop();
    fill(50, 170, 150);

    pop();
  }
}

In this part, I hard-coded the drawing of the pigeon tower. I know hard coding isn’t as exciting as drawing something adaptable or dynamic, but I genuinely enjoy drawing things with code using simple shapes, and making this pigeon tower was nice. I actually coded it on my phone on a bus ride because I was curious to see if p5.js works on Safari / mobile browsers, and it does!

Reflection & ideas for future work

I really really wanted to figure out some way to make the pigeons look more like pigeons in flight, I had a couple of different ideas on how I might do that. I also wished that the program could handle more pigeons and that I could’ve implemented the rule of pigeons not being directly behind eachother so that their line of sight is not blocked. However, right now my code only spawns about 200 pigeons and it barely gives me the effect I want, so optimising the code is first on the list of improvements that I’d love to make. I’m pretty sure the most computing-intensive thing is calculating the distances between each boid so I might have to think of a smarter way to do that.

Week #1 – Random Walkers “with a purpose”

https://editor.p5js.org/oae233/sketches/k9Xd8e1gW

Concept

So for this assignment, my working title was Random Walker “with a purpose”. Watching my random walkers wander around the screen until i refresh my code made me aware of how each walker has a little life span, which it spends doing nothing but aimlessly wandering around, so I thought I’d give it a purpose. My idea was to have my walkers start out in a random position, with a random color on a canvas. The canvas is divided into 3 areas, each area assigned one of the primary digital colors RGB. The movers move around randomly but are also able to check their surroundings, compare the colors they see to their own colours, and move toward the colors most similar to them. Finally, I wanted the movers at any point to have an equal chance at either affecting their environment (changing the color of their surroundings) or being affected by it (changing colors based on their surroundings). In this setup, you get to watch the walkers move around the canvas transforming it into an abstract landscape with varying colors. I also used points that move around randomly in a confined space to create the walkers themselves, so that they look like they’re constantly on the move, and I also think it gives them more personality

Some Code I’m Proud Of

shapeGen() {
    // Generate shapes based on noise values
    this.prepareNoise();
    for (let i = 0; i < this.vrtcsListLength / 2; i++) {
      this.vrtcsX[i] += this.mv[i];
      this.vrtcsX[i] = constrain(this.vrtcsX[i], -5, 5);
    }
    for (let i = 0; i < this.vrtcsListLength / 2; i++) {
      this.vrtcsY[i] += this.mv[i + this.vrtcsListLength / 2];
      this.vrtcsY[i] = constrain(this.vrtcsY[i], -5, 5);
    }
  }

I’m proud of the shapegen() function because of how simple it is, yet it gives so much life to the creatures. I’m also proud of the checksurroundings() function because it took me a lot of time and effort to get right as I explain in the reflections section.

Reflection & ideas for future work 

When it came to coding the part where the movers check the pixels surrounding them, I was initially using nested for loops to do this and copying the pixel data to an array, then sorting that array using the built-in sort function. This was causing my program to become very very slow even with just two movers. I spent a really long time on this issue, trying out different solutions, and eventually, with some suggestions from chatGPT as well, I was able to fix the issue. Instead of the nested for loops and going through all the pixels in the surrounding area I used one for loop to generate only 100 random pixels from the area. Also since sorting is famously very computing intensive I switched to a function that just checks for the smallest value in a list by going through it and updating a variable called “smallestIndex” whenever it finds a number. chatGPT pointed out that it was redundant to copy pixel data to a list when I could just access the pixel array directly after loading the pixels.

My project does not work if you set the pixel density to 2, In a future version I’d love to fix that because I think the smoother motion makes it more enjoyable to watch the walkers, especially at their size. I’d also love to have the walkers be able to see each one another so maybe walkers with similar colours can come together and create more concentrated areas of colour on the canvas.

https://editor.p5js.org/oae233/sketches/k9Xd8e1gW: Week #1 – Random Walkers “with a purpose”

Reading Response Week 1 – Omar ElGamal

For this reading, it covers some things that I am generally interested in like the emergence of properties in complex systems, and parallels between evolution and other seemingly unrelated processes. I liked the author’s use of examples to illustrate his point, like the simple concept of a deer evading prey to explain more complex phenomena of natural selection, and in general, I found that thinking of evolution in computational terms (describing it as a parallel system that has “fault tolerance” and reproduction being described as iteration and recursion) provides a helpful analogy.

From an IM & coding perspective, I think it’s an attractive idea that nature’s patterns are recurring, repeating, and simple, and definitely agree with this in some ways. Testing this idea by trying to mimic or simulate different natural phenomena using a set of small & simple rules sounds really fun and I believe the book as a whole can be very helpful in this regard. I’ve dreamt a lot of trying to make my own version of cellular automata and incorporating an evolutionary network but still keeping it relatively simple, just to see how far I can push it in terms of interesting emergent behaviors that might manifest.

On a slightly more unrelated point, the adaptation section piqued my interest the most, especially the bit about learning, evolution, and cultural adaptation being the same process on different time scales. I’ve watched a couple of lectures from developmental biologist Michael Levin (A really interesting one is Intelligence Beyond the Brain on Youtube), and in it, he proposes this idea that intelligence is more or less the same across different physical scales and that all intelligence is collective intelligence (since everything is made of parts). He talks about the similarities between types of intelligences that we often think of as vastly different or even completely overlook. Like how cells came together as separate individual intelligent agents and gave rise to multicellular intelligence able to solve more complex problems (emergence), and then how these multicellular intelligences can be organs (that can themselves be considered intelligent) that come together to make organisms that are able to solve & work towards more even complex goals (although at the most basic level, they seem to me more or less the same goals of reproduction, food prosperity, etc.. just on larger scales). Sometimes I like to theorise that any group of intelligent agents is eventually bound to come together and give rise to something more complex, and I think that humans are just going through their evolutional journey of figuring out how to connect, communicate and work together seamlessly (almost like cells do), to give rise to an agent that’s on a different plane of intelligence, capable of much more than we are able to imagine. I think we would need a real technological revolution in communication, but sometimes I feel like it’s almost inevitable. In the lecture I mentioned earlier Michael Levin points out how cells don’t know that they are part of a human they’re just doing their thing, and I think that even if they had some sort of awareness that they are part of a system or working within a larger group, the problems and aspects of human life are simply incomprehensible to a single cell because they exist on a different scale. So, maybe we already are part of an intelligent agent and we just don’t know it, an agent that exists in a realm beyond our comprehension or understanding.