Week 1: Self-Avoiding Walk through RGB space

For this week’s assignment, I decided to create a self-avoiding walk within an RGB space.

Whenever a dot tries to walk to a spot that has already been visited before, it stops the program. This can be restarted on click.

In the draw function, I made the RGB space using map() and assigning each dot to a random RGB value.

I tried to simplify the code as much as possible. In the snippet below, it checks if a spot in the grid has been visited before, if not, it pushes a new dot.

for (let option of allOptions) {
  let newX = x + option.dx;
  let newY = y + option.dy;
  if (newX >= 0 && newX < cols && newY >= 0 && newY < rows && !grid[newX][newY]) {
    options.push(option);
  }
}

 

 

Week 1 Sketch

Concept

The concept behind this code revolves around generating a dynamic and visually engaging animation using Bézier curves. Bézier curves, often used in computer graphics to model smooth curves, provide an ideal foundation for creating a path that an animated object can follow. In this program, a “walker” moves along a Bézier curve defined by a set of fluctuating control points. The movement along the curve is complemented by changing colors, creating a lively and evolving visual pattern. This approach allows for the exploration of procedural animation techniques, where randomness and mathematical functions are used to produce aesthetically pleasing, unpredictable outcomes.

Reflections for the Future

Looking forward, there are several enhancements and extensions that could be made to this project. One possible improvement is to introduce user interactivity, allowing viewers to influence the motion, control points, or colors in real-time. Another idea is to experiment with more complex curve types, such as cubic or quadratic Bézier curves, to see how they impact the animation’s aesthetics. Furthermore, adding sound that reacts to the movement or colors could create a multisensory experience, deepening the engagement with the artwork.

Self-Avoiding Walker navigating through RGB space

The two components I decided to choose were to make a self-avoiding walker and have it navigate through an RGB space. The program is below:

The code for my program can be found on my GitHub here. EDIT: I really quickly added a reset function so you don’t need to constantly refresh the page to restart the walker.

Essentially, the program creates an invisible grid for the walker to travel on and then checks what adjacent points have been unvisited. It will then randomly choose one of the valid directions and travels there. The points are colored and are made so the RGB values are mapped based on the current coordinates of the walker. Red is mapped to x, and green is mapped to y. Blue is simply given a random value from 0-255 since the space is only two-dimensional. The program will continue until the walker gets stuck, meaning there are no unvisited nodes adjacent to it that can be visited. The code is a heavily modified version of the barebones walker we used in class.

Originally, it was going to be much closer to what the original walker code was like, but I opted to use the grid because I thought it would be much easier to track the coordinates that have been visited. Also, the original walker is small and hard to see, so I decided to use a more visually appealing and visible pathing. When I first tried to tackle the checking adjacent points problem, the code I had was using the original random 1-4 picker, and keeping the walker in a while loop if the chosen coordinate was within an array of coordinates to avoid. However, this was really inefficient, since the walker would have to iterate through an array of coordinates that go progressively larger over time every time it tried to move, and it made the program slow down if the program was able to go long enough.  After doing some research into other walker programs, I realized there was a much easier way to do the checking. This is how I came to develop the grid instead. Each coordinate in the array is given a value of false, which is then changed to true if the walker chooses that coordinate. You can then have a simple function that will return the boolean value of the coordinates adjacent to the walker.

//checks to make sure the point is unvisited and in bounds
function isValid(i, j) {
  if (i < 0 || i >= cols || j < 0 || j >= rows) {
    return false;
  }
  return !grid[i][j];
}

 

If there are visited nodes adjacent to the walker, it will not add it to the array of options it will randomly choose from to make its next move.

//all adjacent points on grid
let allOptions = [
  { dx: 1, dy: 0 },
  { dx: -1, dy: 0 },
  { dx: 0, dy: 1 },
  { dx: 0, dy: -1 },
];

...

let options = [];
    for (let option of allOptions) {
      let newX = this.x + option.dx;
      let newY = this.y + option.dy;
      if (isValid(newX, newY)) {
        options.push(option);
      }
    }
    //chose a random direction to move in
    if (options.length > 0) {
      let step = random(options);
...

    } else {
      //ends program if theres nowhere to go
      console.log(`I'm stuck!`);
      this.stuck = true;
    }

Honestly, there was a lot more I wanted to do with this program that I did not get to achieve. The main issue stemmed from the fact that during the development process of my program. I made a mistake debugging a loop, which caused the IDE to get stuck and crash the page. In a stroke of genius, I had completely forgotten to save the program I was writing at any point, meaning I had lost all the code I had done, and I was now back to square one. This severely demotivated me for a while and I did not try to tackle the program again until the end of the weekend.

Another aspect of this program I intended to develop was making the walker not get stuck. It annoyed me how quickly the walker usually got itself stuck. It made it hard to see the color changes at times when the walker was occupying about 10% of the grid. Had I given myself more time after my entire program ceased to exist I probably would’ve figured out how to make this work, but unfortunately, I was unable to do so.

Originally, I had also intended to make this program a 3D self-avoiding walker that would navigate through an RGB space, because it meant I could map the z coordinate to blue. I had found some programs that would allow me to do this, but I had a hard time understanding the code and was doing a lot of trial-and-error to really understand what each part of the program was doing and how I could translate it into code of my own. I just decided to go with 2D instead because it was easier to understand, code, and debug. I think I want to try to tackle this again at some point in the future because the walker looked really nice and it would be a good opportunity to work with processing in three dimensions rather than two.

 

EDIT 9/4: After completing the two-dimensional program, I went back to attempt the three-dimensional walk again, and I managed to do so. The link to it can be found here.

The program is functionally similar to the two-dimensional program, there were extra parts that had to be added in order to make the program work in three dimensions. Also, I added some buttons that could be interacted with so that there are some options for the user to play around with. The main difference is in how the program renders the 3D path, where there is an array storing each coordinate point the walker has visited, and renders lines between each point. This means the program has to iterate through the entire array every time to render it, which does lag the program when the path gets very large. There is also a function that tries to center the camera around the path and will shift when it reaches a new min/max to account for this. You can also use the mouse to move the camera, lmb to rotate, rmb to pan, and scroll to zoom.

 

Response 1

Flake’s introduction to “The Computational Beauty of Nature” really got me thinking about how we approach understanding the world around us. I’ve always been drawn to the reductionist approach, dissecting things down to their smallest parts to see how they work. But Flake’s argument for considering interactions and the emergent properties of complex systems is really compelling. The ant colony example is a perfect illustration – a single ant is pretty simple, but a whole colony exhibits incredibly sophisticated behaviors you wouldn’t predict just by studying individual ants.

I’m left with a lot of questions though. Flake mentions the “frugal” nature of the rules governing interactions – is there a way to quantify this frugality? And how exactly do we go about describing these interactions in a computational way? The idea of “nature’s program” is intriguing, but I wonder how far that metaphor can be stretched. What I found most interesting was the connection between computation and natural phenomena like fractals and chaos. It’s mind-blowing to think that simple iterative processes can generate such intricate and seemingly unpredictable patterns. I’m definitely looking forward to diving deeper into these topics in the following chapters.

Reading 1

It’s fascinating to contemplate that simple agents, like ants or even molecules, can come together to create complex behaviors that we see in larger systems. This reading emphasized that we can’t always predict how a group will behave just by knowing about the individual parts. It’s like trying to understand a sports team by only looking at the skills of each player rather than how they fit/work together.

I am particularly intrigued by the idea that nature often uses simple rules to create complexity. The role of computers in studying these interactions also excites me, as it opens up new ways to explore and understand complex systems, and places technologists on the frontlines of the quest to understand nature.

Gaussian Random Walk in RGB Space

The program generates a random walk where each step’s size is determined by a Gaussian distribution, causing the walker to move in smooth, less erratic paths. As the walker traverses the canvas, its position influences the RGB values used to create colors. The resulting display features a vibrant color trail that evolves with the walker’s movement.

function drawTrail() {
  for (let i = 0; i < colors.length; i++) {
    stroke(colors[i]);
    point(width / 2 + randomGaussian() * 80, height / 2 + randomGaussian() * 80);
  }
}

The above code draws points on the graph deviating from the center using gaussian distribution for each random color, leading to higher intensity closer to the middle of the canvas.

Full code

 

Sketch – Week1

Concept

I wanted to create a self-avoiding walk and when the walk ended there would be a morphing shape displayed.

Embedded Sketch

Code Highlight

function displayShape() {
  background(50);

  // Rotate the shape around the y-axis
  rotateY(frameCount * 0.05);

  // Draw shape using the curve function
  fill(167, 250, 250);
  curve(-500, 500, 0, 0, 20, 20, 20, 20, 0, 500, 500, 0);
}

Future Improvements

The self-avoiding walk was time-consuming to figure out, and it was my first time using curve(). I had difficulty implementing it into my code as I haven’t worked with “WEBGL”, and thus had to modify my code accordingly. In the future, I want to try to add text to the displayShape screen as well, as I couldn’t figure out how to add it with “WEBGL” interfering.

Reading Reflection – Week1

For this week, I read the introduction of the book Computational Beauty of Nature. The text was centered around reductionism, which is the theory of reducing complex things into basic parts or components. The author points to flaws in reductionism, particularly in observing nature in his example of ants. According to the author, if ants were studied individually as opposed to studied collectively as a colony, scientists would lack a crucial understanding of the complexities of ants and their colonies due to the intricate societies ants form. Through analogies like this one, the author argues that many systems and structures are connected. Thus, the author argues for understanding the interactions between agents being one of the three ways of analysis, with the other two being reductionism and a more holistic perspective. From here, the book is introduced as a way of learning about computer systems and structures. 

I am intrigued by the introduction of the book and I look forward to reading more. I did not know about the reductionism theory, and it made me question if this theory can be applied to computers and technology more successfully than it can be applied to nature. As computers are built through smaller parts and components coming together, shouldn’t they be easily dissected and analyzed from their parts and components? Computers are meant to be predictable, while nature is not. 

Week #1 – Reading Reflection

This reading made me think about how our systems are composed and the relation between them. The introduction gives an example with ants and how a singular ant is a rather simple entity with a set of simple tasks. Nevertheless, if put together a multitude of ants, the number of tasks and its complexity increases. Similar examples can be found even in even more complex things, such as computers. A singular computer is capable of doing an almost infinite set of tasks if properly handled, the same can not be said for a set of computers since the difficulty of handling them increases.

The reading also made me realize that in our life everything is part from a sequential process of parallelism, iterations, and adaptation. For example, in my life I had to do multiple things at once in order to get something, I had to continue fighting for what I wanted continuously and adapted into new environments. This sequential process will be cycled over and over again; nothing to be afraid of, it’s part of life.

And lastly, this reading made me reflect on how we can interconnect between different languages (using the different sciences as an example from the book). For example, something that only artists could do now is able to be imitated and understood by people who lack the advanced knowledge. In other words, if I want to paint the Mona Lisa, the computer could tell me the exact steps that were taken in order to reproduce such a piece. This is thanks to this “translation” process.

Assignment 1 – Chromatic Trails of Chance

Concept

For my first assignment, I decided to keep it simple while adhering to the given requirements. From the first list, I chose to implement the Lévy flight walk along with the concept of changing color based on the ellipse’s position on the screen. This type of random walk features steps distributed according to a power-law, resulting in occasional long jumps interspersed with shorter steps.

Highlight I’m proud of
function draw() {
  // Update position based on Levy Flight
  angle = random(TWO_PI); // Random angle
  stepSize = pow(random(), -1.5) * 5; // Levy Flight step size with power-law distribution
  x += cos(angle) * stepSize;
  y += sin(angle) * stepSize;
  
  // Ensure the position is within bounds
  x = constrain(x, 0, width);
  y = constrain(y, 0, height);
  
  // Store current position for trailing effect
  trail.push([x, y]);
  
  // Limit the number of points in the trail for performance
  if (trail.length > 100) {
    trail.shift(); // Remove oldest point
  }

From the code above I allowed for my canvas to leave a trail of where the previous pattern came across. Then slowly it would remove the oldest trail by limiting the number of points.

Embedded sketch

Reflection and ideas for future work or improvements

It would be nice to add more user input by allowing users to control aspects of the Levy Flight, such as step size or angle, using mouse or keyboard inputs. Maybe also experiment with different types of random walks or combine multiple patterns for complex behaviors.