The Stride Part Three

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Code Breakdown

Figure 8 Track

We draw the track as a polyline (sampled points) and orient all glyphs by rotating to the tangent (rotate(p.ang)).

// Parametric curve + tangent
x = a * sin(t),  y = (b/2) * sin(2t)

function infinityPoint(tau, a, b) {
  const x = a * sin(tau);
  const y = (b * 0.5) * sin(2 * tau);
  const dx = a * cos(tau);
  const dy = b * cos(2 * tau);
  const ang = atan2(dy, dx); // tangent angle
  return { x, y, ang };
}

4-Behaviors

Seasons = Turtle feeding cycles

Fin Strokes = Distance Measuring

Breath = Religious Timing/Calendar

Blink = Day/Night Cycle

// Parametric curve + tangent
x = a * sin(t),  y = (b/2) * sin(2t)

function infinityPoint(tau, a, b) {
  const x = a * sin(tau);
  const y = (b * 0.5) * sin(2 * tau);
  const dx = a * cos(tau);
  const dy = b * cos(2 * tau);
  const ang = atan2(dy, dx); // tangent angle
  return { x, y, ang };
}

Visual Language

Track Color Season color slowly shifts via four stops using seasonalHue() and wrap-aware lerpHue()

const seasonHue = seasonalHue(seasonCyc); // amber → green → violet → cyan
stroke(seasonHue, …); drawInfinityPolyline(...);


Track Color:
Season color slowly shifts via four stops using seasonalHue() and wrap-aware lerpHue()

const seasonHue = seasonalHue(seasonCyc); // amber → green → violet → cyan
stroke(seasonHue, …); drawInfinityPolyline(...);

An image of MF DOOM's iconic mask is divided into a grid of tiles. When a button is pressed, random hidden tiles are revealed, and newly revealed tiles briefly glow in response to the sound.

revealed[r][c] = true;

Reflection

This project sits somewhere between an instrument, a game, and a piece of interactive visual art.

It asks a simple question:

What if making music wasn’t about building something new — but revealing something that already exists?

By tying sound, touch, and imagery together, the machine transforms rhythm into progress.

Sometimes, the beat isn’t the point. Sometimes, the beat is the key.

The Stride Part Three

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

The Stride Part Three

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Process

Physical Interface

At the heart of the system is a custom-built controller powered by an Arduino ESP32 Feather housed in a cardboard enclosure.

The interface includes:

  • Four physical buttons
    • Each button triggers a different sound sample and reveals tiles from a specific region of the image.
  • One slide potentiometer
    • The slider controls pitch, shifting the musical mood from low and heavy to sharp and elevated. It also acts as a modifier, changing how the sounds feel without changing how they’re played.

Breadboard with inputs

Full view + Slide Potentiometer

DOOMBOX Exterior Housing

Arduino IDE: Reading the Interface

On the hardware side, the ESP32 reads four buttons and a B10K slide potentiometer. Each loop, it sends their values as a single line of comma-separated data over USB serial.

#define B1 13
#define B2 12
#define B3 27
#define B4 33
#define POT_PIN 32

void loop() {
  Serial.print(digitalRead(B1));
  Serial.print(',');
  Serial.print(digitalRead(B2));
  Serial.print(',');
  Serial.print(digitalRead(B3));
  Serial.print(',');
  Serial.print(digitalRead(B4));
  Serial.print(',');
  Serial.println(analogRead(POT_PIN));
}

Processing: Sound Playback and Pitch Control

In Processing, serial data is parsed and mapped to musical behavior. Each button triggers a drum sample, while the slider controls pitch by adjusting playback rate.

pitchRate = map(potRaw, 0, 4095, 0.5, 2.0);
pitchRate = constrain(pitchRate, 0.5, 2.0);

drums[i].rate(pitchRate);
drums[i].play();

Processing: Image Reveal

An image of MF DOOM's iconic mask is divided into a grid of tiles. When a button is pressed, random hidden tiles are revealed, and newly revealed tiles briefly glow in response to the sound.

revealed[r][c] = true;

Processing: Image Reveal

On the hardware side, the ESP32 reads four buttons and a B10K slide potentiometer. Each loop, it sends their values as a single line of comma-separated data over USB serial.

#define B1 13
#define B2 12
#define B3 27
#define B4 33
#define POT_PIN 32

void loop() {
  Serial.print(digitalRead(B1));
  Serial.print(',');
  Serial.print(digitalRead(B2));
  Serial.print(',');
  Serial.print(digitalRead(B3));
  Serial.print(',');
  Serial.print(digitalRead(B4));
  Serial.print(',');
  Serial.println(analogRead(POT_PIN));
}

Reflection

This project sits somewhere between an instrument, a game, and a piece of interactive visual art.

It asks a simple question:

What if making music wasn’t about building something new — but revealing something that already exists?

By tying sound, touch, and imagery together, the machine transforms rhythm into progress.

Sometimes, the beat isn’t the point. Sometimes, the beat is the key.

Logic be Dammed:
Representing Forces and Nature in Code

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Code Breakdown

Classes

  • Hydro – tile grids for water, target, age, barren; column arrays for velCol, noiseCol
    • Builds trunk + branches with Perlin noise and stochastic jitter.
    • Spawns new estuaries on a timer; widens old undammed channels; applies right-side desiccation and water-adjacent recovery.
  • Forest – 2D fields for willow and aspen (0–1). Growth moves toward a cap reduced by barren; blocked under lodges; harvest() does a ring search for richest patch.
  • DamSpans – spans are {row, cL, cR, integrity} across a gap bounded by land. Integrity decays with time and high flow; collapsed spans are removed.
  • Colony, Beaver – array of agents; mortality filter; metrics; per-beaver FSM with vector steering.
  • Lodge – simple sprite; count tied to population

Making the world

Why this order: environment first, then resources, then structures that shape flow, then agents reacting to the current state.

Creates subsystems and enforces the following update order (water → resources → structures → agents).

class World {
  constructor(hud){
    this.hud=hud;
    this.hydro=new Hydro(hud);
    this.forest=new Forest(hud,this.hydro);
    this.dams=new DamSpans(hud,this.hydro);
    this.colony=new Colony(hud,this.hydro,this.dams,this.forest);
    this.lodges=[]; this.updateLodges(true);
  }
  update(){
    this.hydro.update();                     // rivers grow/branch/widen/dry
    this.forest.update(this.lodges,this.hydro); // growth capped by barren
    this.dams.update(this.hydro);            // span decay vs flow
    this.colony.update(this.dams,this.hydro);    // FSM + mortality
    if (this.colony.prunedThisTick){ this.updateLodges(); this.colony.prunedThisTick=false; }
    this.forest.blockUnderLodges(this.lodges,this.hydro);
  }
}

Rivers

The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Beavers “feel” water via noiseCol[c] (stress driver).

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Forests & Barren Tiles

Willows (for building dams) and Aspen (food for the beavers) grow on land toward a cap that shrinks with barren; growth is blocked under lodges and zeroed on water.The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Resulting effects: near water → fertile patches; dry right side → patchy, low-cap growth.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Dams & Bank-to-Bank Spans

Dam Spans exist only across contiguous water segments bounded by land; integrity increases with work and decays with flow.

This prevents the beavers from spam building, and makes dams visually & mechanically legible.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Agents & Interaction: Beavers, Vectors, HUD

Beavers are need-driven agents with vector steering.

Input from the right-side menu allows the user to shape conditions.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Input & HUD

  • Keys: G generate new river; SPACE pause.
  • Mouse: Left = plant Willow, Shift+Left = plant Aspen; toggle Spawn Mode then Right-click to add a random beaver.
  • Sliders (stacked under descriptions; buttons below sliders—no overlap):
    1. River Creation Speed → reveal rate of Hydro.target
    2. Food Spawn Rate (Aspen) → forest growth term
    3. Building Material Spawn Rate (Willow) → forest growth term
    4. Dam Building Speed → per-action span integrity

This closes the system loop: environment drives needs; agents act; structures reshape the environment; HUD lets you adjust parameters and watch new equilibria emerge.

Logic be Dammed:
Representing Forces and Nature in Code

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Code Breakdown

Classes

  • Hydro – tile grids for water, target, age, barren; column arrays for velCol, noiseCol
    • Builds trunk + branches with Perlin noise and stochastic jitter.
    • Spawns new estuaries on a timer; widens old undammed channels; applies right-side desiccation and water-adjacent recovery.
  • Forest – 2D fields for willow and aspen (0–1). Growth moves toward a cap reduced by barren; blocked under lodges; harvest() does a ring search for richest patch.
  • DamSpans – spans are {row, cL, cR, integrity} across a gap bounded by land. Integrity decays with time and high flow; collapsed spans are removed.
  • Colony, Beaver – array of agents; mortality filter; metrics; per-beaver FSM with vector steering.
  • Lodge – simple sprite; count tied to population

Making the world

Why this order: environment first, then resources, then structures that shape flow, then agents reacting to the current state.

Creates subsystems and enforces the following update order (water → resources → structures → agents).

class World {
  constructor(hud){
    this.hud=hud;
    this.hydro=new Hydro(hud);
    this.forest=new Forest(hud,this.hydro);
    this.dams=new DamSpans(hud,this.hydro);
    this.colony=new Colony(hud,this.hydro,this.dams,this.forest);
    this.lodges=[]; this.updateLodges(true);
  }
  update(){
    this.hydro.update();                     // rivers grow/branch/widen/dry
    this.forest.update(this.lodges,this.hydro); // growth capped by barren
    this.dams.update(this.hydro);            // span decay vs flow
    this.colony.update(this.dams,this.hydro);    // FSM + mortality
    if (this.colony.prunedThisTick){ this.updateLodges(); this.colony.prunedThisTick=false; }
    this.forest.blockUnderLodges(this.lodges,this.hydro);
  }
}

Rivers

The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Beavers “feel” water via noiseCol[c] (stress driver).

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Forests & Barren Tiles

Willows (for building dams) and Aspen (food for the beavers) grow on land toward a cap that shrinks with barren; growth is blocked under lodges and zeroed on water.The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Resulting effects: near water → fertile patches; dry right side → patchy, low-cap growth.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Dams & Bank-to-Bank Spans

Dam Spans exist only across contiguous water segments bounded by land; integrity increases with work and decays with flow.

This prevents the beavers from spam building, and makes dams visually & mechanically legible.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Agents & Interaction: Beavers, Vectors, HUD

Beavers are need-driven agents with vector steering.

Input from the right-side menu allows the user to shape conditions.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Input & HUD

  • Keys: G generate new river; SPACE pause.
  • Mouse: Left = plant Willow, Shift+Left = plant Aspen; toggle Spawn Mode then Right-click to add a random beaver.
  • Sliders (stacked under descriptions; buttons below sliders—no overlap):
    1. River Creation Speed → reveal rate of Hydro.target
    2. Food Spawn Rate (Aspen) → forest growth term
    3. Building Material Spawn Rate (Willow) → forest growth term
    4. Dam Building Speed → per-action span integrity

This closes the system loop: environment drives needs; agents act; structures reshape the environment; HUD lets you adjust parameters and watch new equilibria emerge.

Logic be Dammed:
Representing Forces and Nature in Code

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Code Breakdown

Classes

  • Hydro – tile grids for water, target, age, barren; column arrays for velCol, noiseCol
    • Builds trunk + branches with Perlin noise and stochastic jitter.
    • Spawns new estuaries on a timer; widens old undammed channels; applies right-side desiccation and water-adjacent recovery.
  • Forest – 2D fields for willow and aspen (0–1). Growth moves toward a cap reduced by barren; blocked under lodges; harvest() does a ring search for richest patch.
  • DamSpans – spans are {row, cL, cR, integrity} across a gap bounded by land. Integrity decays with time and high flow; collapsed spans are removed.
  • Colony, Beaver – array of agents; mortality filter; metrics; per-beaver FSM with vector steering.
  • Lodge – simple sprite; count tied to population

Making the world

Why this order: environment first, then resources, then structures that shape flow, then agents reacting to the current state.

Creates subsystems and enforces the following update order (water → resources → structures → agents).

class World {
  constructor(hud){
    this.hud=hud;
    this.hydro=new Hydro(hud);
    this.forest=new Forest(hud,this.hydro);
    this.dams=new DamSpans(hud,this.hydro);
    this.colony=new Colony(hud,this.hydro,this.dams,this.forest);
    this.lodges=[]; this.updateLodges(true);
  }
  update(){
    this.hydro.update();                     // rivers grow/branch/widen/dry
    this.forest.update(this.lodges,this.hydro); // growth capped by barren
    this.dams.update(this.hydro);            // span decay vs flow
    this.colony.update(this.dams,this.hydro);    // FSM + mortality
    if (this.colony.prunedThisTick){ this.updateLodges(); this.colony.prunedThisTick=false; }
    this.forest.blockUnderLodges(this.lodges,this.hydro);
  }
}

Rivers

The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Beavers “feel” water via noiseCol[c] (stress driver).

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Forests & Barren Tiles

Willows (for building dams) and Aspen (food for the beavers) grow on land toward a cap that shrinks with barren; growth is blocked under lodges and zeroed on water.The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Resulting effects: near water → fertile patches; dry right side → patchy, low-cap growth.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Dams & Bank-to-Bank Spans

Dam Spans exist only across contiguous water segments bounded by land; integrity increases with work and decays with flow.

This prevents the beavers from spam building, and makes dams visually & mechanically legible.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Agents & Interaction: Beavers, Vectors, HUD

Beavers are need-driven agents with vector steering.

Input from the right-side menu allows the user to shape conditions.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Input & HUD

  • Keys: G generate new river; SPACE pause.
  • Mouse: Left = plant Willow, Shift+Left = plant Aspen; toggle Spawn Mode then Right-click to add a random beaver.
  • Sliders (stacked under descriptions; buttons below sliders—no overlap):
    1. River Creation Speed → reveal rate of Hydro.target
    2. Food Spawn Rate (Aspen) → forest growth term
    3. Building Material Spawn Rate (Willow) → forest growth term
    4. Dam Building Speed → per-action span integrity

This closes the system loop: environment drives needs; agents act; structures reshape the environment; HUD lets you adjust parameters and watch new equilibria emerge.

Logic be Dammed:
Representing Forces and Nature in Code

The Stride - Storytelling Midterm

Marcus Thomas

Dec 21, 2024

In 2124, biohacking is common, but the Olympics remain a symbol of pure human achievement, where athletes compete solely on natural abilities, with no enhancements allowed. Mia, a 30-year-old track athlete with hemophilia, had spent years honing her natural speed and technique. Despite her condition, her relentless dedication and strategic approach allowed her to perform at an elite level, earning her a chance to trial for the Olympics. However, training was always a precarious balance—Mia’s hemophilia meant longer recovery times, frequent pain, and the constant risk of internal bleeding that she might not immediately notice.

To compete safely, she was granted an exception to use the VitaGuard—a regulated implant embedded in her upper arm. The VitaGuard uses Near-Infrared (NIR) technology to continuously monitor her blood flow, deploying nano-needles to administer clotting factors only when necessary, ensuring safety without providing any performance advantage. The implant is strictly regulated, using genomic sequencing to recognize Mia’s specific biomarkers, ensuring it only activates when her clotting factor levels drop. Its introduction at the Olympics sparks controversy: a symbol of inclusivity for some, and for others, a step toward blurring the line between fairness and enhancement. Society understands that the VitaGuard doesn't cheat—people do. In the right hands, it's a lifeline; in the wrong hands, it's a vessel for corruption.

As the games approach, Mia feels the pressure mounting. Despite the VitaGuard, she knows she won’t be able to match the natural athleticism of her childhood rival, Lena. One day, Mia is contacted by Dr. Adrian Keller, CEO of Helix Solutions, a biohacking corporation known for pushing the limits of human enhancement. Dr. Keller presents her with a vial of Accelra, a performance-enhancing fluid that can bypass the VitaGuard’s restrictions, masking itself as a clotting agent. “With this, you’ll not just compete, Mia—you’ll dominate,” he says, sliding the vial across the table. “If you don’t take it, we’ll offer it to Lena. The choice is yours.”

Mia hesitates, her voice trembling. “But that’s cheating.” “Is it, though?” Dr. Keller leans in. “You’ve been at a disadvantage your whole life. Isn’t this just leveling the playing field?” Mia wrestles with Dr. Keller’s offer, but ultimately agrees, convincing herself that Accelra will allow her to compete as an equal. Helix secretly modifies her VitaGuard to administer the fluid. Almost immediately, her performance soars. The VitaGuard, now altered, delivers Accelra during her races, boosting her stamina and speed. She wins her qualifying heats, breaking records and drawing worldwide admiration. “You did it, Mia,” Lena says after a race, hugging her. “I always knew you could.” Mia forces a smile, but guilt churns within her. The VitaGuard, once her saving grace, now feels like a symbol of deception, its purpose distorted by Helix.

The night before the final race, Mia stands alone in front of a mirror, staring at the VitaGuard embedded in her arm. The device glows softly; a lifeline that had once protected her is now a shackle.“What does it mean to be normal?” she whispers. “Am I still myself, or just a product of this device?” As the final race approaches, she feels trapped. With Accelra running through her veins she can’t turn back. Without her VitaGuard she can’t beat Lena. She can’t outrun her condition. Her dream would be impossible. But using it means betraying everything she once stood for. Mia uses Accelra one last time, and she wins gold, securing her place as a champion. But standing on the podium, surrounded by applause, she feels empty. The VitaGuard had shifted from being a survival tool to something that distorted her very identity. The world sees her as a trailblazer, an inspiration, but inside, Mia knows she is living a lie. Her victory is hollow, and the guilt consumes her, even as the world celebrates her success.

Desperate to rid herself of the shame, Mia seeks out Dr. Keller. She wants reassurance, but instead, he offers her a chilling alternative. “You don’t have to feel this way, Mia,” he says calmly. “We can make you better. Let us take you further—beyond human, beyond guilt. Imagine what you could become.” Mia is left at a crossroads, torn between accepting Helix’s offer and reclaiming her sense of self. At that moment, she realizes that the VitaGuard, designed to protect her, has now become her moral prison, trapping her between who she is and what Helix wants her to be. As she stands on the brink of two futures, the line between human and machine begins to blur, leaving her to decide which side she belongs to.

The Stride Storyboard

Code Breakdown

Classes

  • Hydro – tile grids for water, target, age, barren; column arrays for velCol, noiseCol
    • Builds trunk + branches with Perlin noise and stochastic jitter.
    • Spawns new estuaries on a timer; widens old undammed channels; applies right-side desiccation and water-adjacent recovery.
  • Forest – 2D fields for willow and aspen (0–1). Growth moves toward a cap reduced by barren; blocked under lodges; harvest() does a ring search for richest patch.
  • DamSpans – spans are {row, cL, cR, integrity} across a gap bounded by land. Integrity decays with time and high flow; collapsed spans are removed.
  • Colony, Beaver – array of agents; mortality filter; metrics; per-beaver FSM with vector steering.
  • Lodge – simple sprite; count tied to population

Making the world

Why this order: environment first, then resources, then structures that shape flow, then agents reacting to the current state.

Creates subsystems and enforces the following update order (water → resources → structures → agents).

class World {
  constructor(hud){
    this.hud=hud;
    this.hydro=new Hydro(hud);
    this.forest=new Forest(hud,this.hydro);
    this.dams=new DamSpans(hud,this.hydro);
    this.colony=new Colony(hud,this.hydro,this.dams,this.forest);
    this.lodges=[]; this.updateLodges(true);
  }
  update(){
    this.hydro.update();                     // rivers grow/branch/widen/dry
    this.forest.update(this.lodges,this.hydro); // growth capped by barren
    this.dams.update(this.hydro);            // span decay vs flow
    this.colony.update(this.dams,this.hydro);    // FSM + mortality
    if (this.colony.prunedThisTick){ this.updateLodges(); this.colony.prunedThisTick=false; }
    this.forest.blockUnderLodges(this.lodges,this.hydro);
  }
}

Rivers

The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Beavers “feel” water via noiseCol[c] (stress driver).

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Forests & Barren Tiles

Willows (for building dams) and Aspen (food for the beavers) grow on land toward a cap that shrinks with barren; growth is blocked under lodges and zeroed on water.The simulation starts with building a target river tree (trunk + noisy branches), reveals it over time (slider), then keep it alive with estuaries, widening, and right-side desiccation.

Resulting effects: near water → fertile patches; dry right side → patchy, low-cap growth.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Dams & Bank-to-Bank Spans

Dam Spans exist only across contiguous water segments bounded by land; integrity increases with work and decays with flow.

This prevents the beavers from spam building, and makes dams visually & mechanically legible.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Agents & Interaction: Beavers, Vectors, HUD

Beavers are need-driven agents with vector steering.

Input from the right-side menu allows the user to shape conditions.

regen(){
  this.water=grid(false); this.target=grid(false); this.barren=grid(0); this.growth=0;
  const trunk = walkBranch(2, rows*0.5, cols*0.85, 0, true); paintPath(trunk,5);
  for (let i=0;i<10;i++){ const pC=rand(6,cols*0.7), pR=clamp(noise(i*.3)*rows,2,rows-3);
    paintPath(walkBranch(pC,pR,rand(18,48), coin()?-1:+1,false),3);
  }
}
update(){
  // reveal target → water
  this.growth=min(1,(this.growth||0)+(0.002+hud.get("riverSpeed")*0.02));
  for (let c=0;c<floor(cols*this.growth);c++) for (let r=0;r<rows;r++) if (target[c][r]) water[c][r]=true;

  // desiccate far right → barren land
  for (let c=floor(cols*.75); c<cols; c++) if (random()<0.0008)
    for (let r=0;r<rows;r++) if (water[c][r]){ water[c][r]=target[c][r]=false; barren[c][r]=min(1,barren[c][r]+.4); }

  // estuaries & widening (if undammed & old)
  if (++branchTimer>240){ branchTimer=0; /* spawn small branch from wet pivot; paintPath(...,2) */ }
  // …age water; leak to neighbors when age>180 && !damSpans.hasDamNear(c,r,4)

  recalcColumns(); // sets velCol[], noiseCol[] from wet fraction per column
}

Input & HUD

  • Keys: G generate new river; SPACE pause.
  • Mouse: Left = plant Willow, Shift+Left = plant Aspen; toggle Spawn Mode then Right-click to add a random beaver.
  • Sliders (stacked under descriptions; buttons below sliders—no overlap):
    1. River Creation Speed → reveal rate of Hydro.target
    2. Food Spawn Rate (Aspen) → forest growth term
    3. Building Material Spawn Rate (Willow) → forest growth term
    4. Dam Building Speed → per-action span integrity

This closes the system loop: environment drives needs; agents act; structures reshape the environment; HUD lets you adjust parameters and watch new equilibria emerge.