In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Peak

Peak

Created in under 48 hours by John Nesky for Ludum Dare 14.  Requires Flash 10.

http://www.ludumdare.com/compo/tag/peak/

Compile with:
mxmlc -target-player=10.0.0 Peak.as
Get Adobe Flash player
by shaktool 20 Apr 2009
/**
 * Copyright shaktool ( http://wonderfl.net/user/shaktool )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tSoU
 */


/*

Peak

Created in under 48 hours by John Nesky for Ludum Dare 14.  Requires Flash 10.

http://www.ludumdare.com/compo/tag/peak/

Compile with:
mxmlc -target-player=10.0.0 Peak.as

*/


package {
  import flash.display.*;
  import flash.events.*;
  import flash.filters.*;
  import flash.geom.*;
  import flash.text.*;
  import flash.utils.*;
  
  [SWF(width=400, height=465, frameRate=15, backgroundColor=0x000000)]
  public class Peak extends Sprite {
    public static const STATIC_WIDTH: int = 200;
    public static const STATIC_HEIGHT: int = 200;
    public static const STATIC_EMPTY: int = -1;
    public static const STATIC_WATER: int = -2;
    public static const STATIC_SOURCE: int = 255;
    private const WIDTH: int = STATIC_WIDTH;
    private const HEIGHT: int = STATIC_HEIGHT;
    private const W_TIMES_H: int = WIDTH*HEIGHT;
    private const EMPTY: int = STATIC_EMPTY;
    private const WATER: int = STATIC_WATER;
    private const SOURCE: int = STATIC_SOURCE;
    private const SPECIES: int = 3;
    private const PLANT: int = 0;
    private const COORD_BURST: int = W_TIMES_H;
    private const HEAT_BURST: int = 1;
    private const LOOK_AHEAD: int = 7;
    private const SPAWN_COUNT: int = 10;
    private const GROW_TIME: int = 200;
    private const STARVE_TIME: int = 60;
    private const SPAWN_TIME: int = 3;
    private const UP: Point = new Point(0,-1);
    private const DOWN: Point = new Point(0,1);
    private const LEFT: Point = new Point(-1,0);
    private const RIGHT: Point = new Point(1,0);
    private const DIRECTIONS: Array = [UP, DOWN, LEFT, RIGHT];
    private const COLORS: Array = [
                                   0xff00ff00,
                                   0xffff0000,
                                   0xffffff00,
                                   0xff00ffff,
                                   0xffff00ff,
                                   0xff0000ff,
                                   0xffffffff,
                                   0xff999999,
                                   0xffcccccc,
                                   0xff666666,
                                   ];
    
    private var lifeMap: BitmapData = new BitmapData(WIDTH, HEIGHT, false , 0);
    //private var heatMap: BitmapData = new BitmapData(WIDTH, HEIGHT, false, 0);
    private var heightMap:BitmapData = new BitmapData(WIDTH,HEIGHT,false,0);
    private var tempMap:BitmapData = new BitmapData(WIDTH,HEIGHT,true,0);
    private var waterVec: Vector.<int> = new Vector.<int>(WIDTH * HEIGHT, true);
    public var lifeVec: Vector.<int>;
    public var allLife: Vector.<Life> = new Vector.<Life>(SPECIES, true);
    public var coords: Vector.<Point> = new Vector.<Point>(WIDTH * HEIGHT, true);
    private var frames: int;
    private var instructions: TextField;
    private var statusText: TextField;
    private var frameText: TextField;
    private var whiteFormat: TextFormat;
    private var redFormat: TextFormat;
    private var greenFormat: TextFormat;
    private var yellowFormat: TextFormat;
    
    public function Peak() {
      stage.align = StageAlign.BOTTOM;
      stage.scaleMode = StageScaleMode.NO_SCALE;
      //generate(null)
      stage.addEventListener(MouseEvent.CLICK, generate);
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
      stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
      stage.focus = stage;
      //onEnterFrame(null);
      
      /*var onScreenHeatMap: Bitmap = new Bitmap(heatMap);
      onScreenHeatMap.scaleX = 2;
      onScreenHeatMap.scaleY = 2;
      addChild(onScreenHeatMap);*/
      var screen: Bitmap = new Bitmap(lifeMap);
      screen.scaleX = 2;
      screen.scaleY = 2;
      //screen.x = stage.width / 2 - WIDTH;
      //screen.y = stage.height - HEIGHT * 2
      screen.y = 60;
      addChild(screen);
      
      
      whiteFormat = new TextFormat();
      whiteFormat.font="_sans";
      whiteFormat.align = TextFormatAlign.CENTER;
      whiteFormat.color = 0xffffffff;
      whiteFormat.size=12;
      
      redFormat = new TextFormat();
      redFormat.font="_sans";
      redFormat.align = TextFormatAlign.CENTER;
      redFormat.color = 0xffff0000;
      redFormat.size=12;
      
      greenFormat = new TextFormat();
      greenFormat.font="_sans";
      greenFormat.align = TextFormatAlign.CENTER;
      greenFormat.color = 0xff00ff00;
      greenFormat.size=12;
      
      yellowFormat = new TextFormat();
      yellowFormat.font="_sans";
      yellowFormat.align = TextFormatAlign.CENTER;
      yellowFormat.color = 0xffffff00;
      yellowFormat.size=12;
      
      instructions = new TextField();
      instructions.width = 0;
      instructions.x = stage.width / 2;
      instructions.y = 0;
      instructions.autoSize = TextFieldAutoSize.CENTER;
      
      addChild(instructions);
      drawInstructions("hunt.");
    }
    
    public function drawInstructions(yellowText: String): void {
      instructions.text = "";
      instructions.defaultTextFormat = whiteFormat;
      instructions.replaceSelectedText("You are a species of ");
      instructions.defaultTextFormat = redFormat;
      instructions.replaceSelectedText("red dots.");
      instructions.defaultTextFormat = whiteFormat;
      instructions.replaceSelectedText("\nPress 1 to ");
      instructions.defaultTextFormat = greenFormat;
      instructions.replaceSelectedText("harvest");
      instructions.defaultTextFormat = whiteFormat;
      instructions.replaceSelectedText(". Press 2 to ");
      instructions.defaultTextFormat = yellowFormat;
      instructions.replaceSelectedText(yellowText);
      instructions.defaultTextFormat = whiteFormat;
      instructions.replaceSelectedText(" Click to restart.");
    }
    
    public function generate(event: MouseEvent): void {
      var i: int;
      var j: int;
      var k: int;
      var palette: Array = new Array(256);
      var threshold: int;
      
      drawInstructions("hunt.");
      
      heightMap.perlinNoise(50,50,10,Math.random()*int.MAX_VALUE,true,true, 4, false);
      
      // solarize and copy into heightmap:
      threshold = 100;
      for (i = 0; i < 128; i++) {
        if (i < threshold) k = 0; else k = (i - threshold) * 255 / (127 - threshold);
        k = (k << 16) | (k << 8) | (k << 0);
      	palette[i] = k;
      	palette[255 - i] = k;
      }
      heightMap.paletteMap(heightMap, new Rectangle(0,0,WIDTH,HEIGHT), new Point(0,0), null, null, palette, null);
      
      // remove islands:
      var blackPalette: Array = new Array(256);
      for (i = 0; i < 256; i++) {
        blackPalette[i] = 0;
      }
      
      for (i = 0; i < 256; i++) {
        if (i == 0) palette[i] = 0; else palette[i] = 0xff;
      }
      tempMap.paletteMap(heightMap, new Rectangle(0,0,WIDTH,HEIGHT), new Point(0,0), blackPalette, blackPalette, palette, null);
      
      var color1: int = 0;
      var color2: int = 0;
      i = j = 0
      do {
      	i++;
      	if (i == heightMap.width) {
      	  i = 0;
      	  j++;
      	}
      	color1 = heightMap.getPixel(i,j);
      } while (color1 < (253 << 16))
      tempMap.floodFill(i,j,0xffffffff);
      
      for (i=0; i < heightMap.width; i++) {
        color1 = tempMap.getPixel(i,0);
        color2 = tempMap.getPixel(i,tempMap.height-1);
      	if (color1 == 0xff && color2 == 0xffffff) {
          tempMap.floodFill(i,0,0xffffffff);
      	} else if (color1 == 0xffffff && color2 == 0xff) {
          tempMap.floodFill(i,tempMap.height-1,0xffffffff);
      	}
      }
      for (i=0; i < heightMap.height; i++) {
        color1 = tempMap.getPixel(0,i);
        color2 = tempMap.getPixel(tempMap.width-1,i);
      	if (color1 == 0xff && color2 == 0xffffff) {
          tempMap.floodFill(0,i,0xffffffff);
      	} else if (color1 == 0xffffff && color2 == 0xff) {
          tempMap.floodFill(tempMap.width-1,i,0xffffffff);
      	}
      }
      
      
      palette[255] = 0x0;
      palette[0] = 0xff000066;
      
      tempMap.paletteMap(tempMap, new Rectangle(0,0,tempMap.width,tempMap.height), new Point(0,0), blackPalette, palette, blackPalette, blackPalette);
      
      //heightMap.copyPixels(tempMap, new Rectangle(0,0,tempMap.width,tempMap.height), new Point(0,0));
      lifeMap.fillRect(new Rectangle(0,0,WIDTH,HEIGHT), 0);
      lifeMap.copyPixels(tempMap, new Rectangle(0,0,tempMap.width,tempMap.height), new Point(0,0));
      
      for (j = 0; j < HEIGHT; j++) {
        for (i = 0; i < WIDTH; i++) {
          k = tempMap.getPixel32(i,j);
          if (k == 0) waterVec[i+j*WIDTH] = 0; else waterVec[i+j*WIDTH] = WATER;
        }
      }
      
      lifeVec = waterVec.concat();
      
      
      
      
      lifeMap.lock();
      
      for (j = 0; j < HEIGHT; j++) {
        for (i = 0; i < WIDTH; i++) {
          if (lifeVec[i + j*HEIGHT] == 0) lifeVec[i + j*HEIGHT] = EMPTY;
        }
      }
      
      allLife[PLANT] = new Life(PLANT, lifeVec, COLORS[PLANT], lifeMap, waterVec, GROW_TIME, 0);
      for (i = PLANT+1; i < SPECIES; i++) {
        allLife[i] = new Life(i, lifeVec, COLORS[i], lifeMap, waterVec, SPAWN_TIME, STARVE_TIME);
      }
      for (i = PLANT+1; i < SPECIES; i++) {
        //allLife[i].target = (i == SPECIES-1) ? allLife[0] : allLife[i+1];
        allLife[i].target = allLife[PLANT];
        
        while (allLife[i].count < SPAWN_COUNT) {
          allLife[i].spawn(Math.random()*WIDTH/3 + WIDTH/3, Math.random()*HEIGHT/3 + i*HEIGHT/3);
        }
      }
      
      while (allLife[PLANT].count < 1000) {
        allLife[PLANT].spawn(Math.random()*WIDTH, Math.random()*HEIGHT);
      }
      
      lifeMap.unlock();
      
      // generate all coords
      k = 0;
      for (j = 0; j < HEIGHT; j++) {
        for (i = 0; i < WIDTH; i++) {
          coords[k] = new Point(i,j);
          k++;
        }
      }
      // random sort coords
      var localRandom: Function = Math.random;
      for (i = 0; i < W_TIMES_H; i++) {
        j = localRandom() * W_TIMES_H;
        var temp: Point = coords[i];
        coords[i] = coords[j];
        coords[j] = temp;
      }
      
      if (frameText != null) removeChild(frameText);
      if (statusText != null) removeChild(statusText);
      
      frameText = new TextField();
      frameText.width = 0;
      frameText.x = stage.width / 2;
      frameText.y = 42;
      frameText.autoSize = TextFieldAutoSize.CENTER;
      frameText.defaultTextFormat = whiteFormat;
      addChild(frameText);
      
      statusText = new TextField();
      statusText.width = 0;
      statusText.x = stage.width / 2;
      statusText.y = 28;
      statusText.autoSize = TextFieldAutoSize.CENTER;
      addChild(statusText);
      
      setStatusText();
      
      frames = 0;
      yellowAlive = true;
    }
    
    private function setStatusText(): void {
      statusText.text = "";
      if (allLife[1].count <= 0) return;
      if (allLife[1].target == allLife[0]) {
        statusText.defaultTextFormat = greenFormat;
        statusText.replaceSelectedText("You are harvesting.");
      } else {
        statusText.defaultTextFormat = yellowFormat;
        if (allLife[2].count > 0) {
          statusText.replaceSelectedText("You are hunting.");
        } else {
          statusText.replaceSelectedText("You are wandering?");
        }
      }
    }
    
    private function wrapX(val: int): int {
      if (val < 0) val += WIDTH;
      else if (val >= WIDTH) val -= WIDTH;
      return val;
    }
    
    private function wrapY(val: int): int {
      if (val < 0) val += HEIGHT;
      else if (val >= HEIGHT) val -= HEIGHT;
      return val;
    }
    
    private function onKeyDown(event: KeyboardEvent): void {
      if (event.charCode == '1'.charCodeAt(0)) {
        allLife[1].target = allLife[0];
      } else if (event.charCode == '2'.charCodeAt(0)) {
        allLife[1].target = allLife[2];
      }
      setStatusText();
    }
    
    private var coordIndex: int = 0;
    private var yellowAlive: Boolean;
    private function onEnterFrame(event: Event): void {
      var i: int;
      var j: int;
      
      if (frameText == null) return;
      
      lifeMap.lock();
      
      for (i = 0; i < SPECIES; i++) {
      	for (j = 0; j < HEAT_BURST; j++) {
	        if (allLife[i].count > 0 && i != 1) allLife[i].updateHeat();
      	}
      }
      
      if (allLife[1].count > 0) {
        frames++;
        frameText.text = "You have been around for " + frames + " years";
      } else {
      	frameText.text = "You are extinct after " + frames + " years";
        setStatusText();
      }
      
      if (yellowAlive && allLife[2].count <= 0) {
      	yellowAlive = false;
      	drawInstructions("wander?");
        setStatusText();
      }
      
      var dest: Point = new Point();
      var dir: Point;
      
      for (i = 0; i < COORD_BURST; i++) {
        var coord: Point = coords[coordIndex];
        coordIndex++;
        if (coordIndex == W_TIMES_H) coordIndex = 0;
        
        var id: int = lifeVec[coord.x + coord.y * WIDTH];
        if (id > EMPTY) {
          var species: Life = allLife[id];
          if (id == PLANT) {
            species.spawnTimer--;
            if (species.spawnTimer <= 0) {
              dir = DIRECTIONS[int(Math.random() * DIRECTIONS.length)];
              dest.x = wrapX(coord.x + dir.x);
              dest.y = wrapY(coord.y + dir.y);
              if (lifeVec[dest.x + dest.y * WIDTH] == EMPTY) {
                species.spawn(dest.x, dest.y);
                species.spawnTimer = species.maxSpawnTime;
              }
            }
          } else {
            
            species.starveTimer--;
            if (species.starveTimer <= 0) {
              species.kill(coord.x, coord.y);
              species.starveTimer = species.maxStarveTime;
              continue;
            }
            
            if (species.id == 2 && Math.random() > 0.85) continue;
            
            if (species.target.count > 0) {
              var heat: Vector.<int> = species.target.heat;
              var chosenDirs: Array = [];
              var viableDirs: Array;
              dest.x = coord.x;
              dest.y = coord.y;
              
              for (j = 0; j < LOOK_AHEAD; j++) {
                var minHeat: int = int.MIN_VALUE;
                for each (dir in DIRECTIONS) {
                  var newHeat: int = heat[(wrapX(coord.x + dir.x)) + (wrapY(coord.y + dir.y)) * WIDTH];
                  if (newHeat > minHeat) {
                    minHeat = newHeat;
                    viableDirs = [dir];
                  } else if (newHeat == minHeat) {
                    viableDirs[viableDirs.length] = dir;
                  }
                }
                
                dir = viableDirs[int(Math.random() * viableDirs.length)];
                chosenDirs[chosenDirs.length] = dir;
                dest.x = wrapX(dest.x + dir.x);
                dest.y = wrapY(dest.y + dir.y);
                if (heat[dest.x + dest.y * WIDTH] == SOURCE) break;
              }
              
              dir = chosenDirs[int(Math.random() * chosenDirs.length)];
            } else {
              dir = DIRECTIONS[int(Math.random() * DIRECTIONS.length)];
            }
            
            dest.x = wrapX(coord.x + dir.x);
            dest.y = wrapY(coord.y + dir.y);
            id = lifeVec[(dest.x) + (dest.y) * WIDTH];
            if (id == EMPTY) {
              species.spawn(dest.x, dest.y);
              species.kill(coord.x, coord.y);
            } else if (id == WATER) {
              // do nothing?
            } else if (id == species.target.id || id == PLANT) {
              var target: Life = allLife[id];
              target.kill(dest.x, dest.y);
              species.spawn(dest.x, dest.y);
              
              species.spawnTimer--;
              if (species.spawnTimer <= 0) {
                species.spawnTimer = species.maxSpawnTime;
              } else {
                species.kill(coord.x, coord.y);
              }
            }
          }
        }
      }
      
      lifeMap.unlock();
      /*
      var bytes: ByteArray = new ByteArray();
      var asdf: Vector.<int> = allLife[0].heat;
      for (i = 0; i < W_TIMES_H; i++) {
      	bytes.writeInt(asdf[i]);
      }
      bytes.position = 0;
      heatMap.setPixels(new Rectangle(0,0,WIDTH, HEIGHT), bytes);
      */
    }
  }
}

import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.*;

class Life {
  private static var _flip: Vector.<int> = new Vector.<int>(Peak.STATIC_WIDTH * Peak.STATIC_HEIGHT, true);
  
  private const WIDTH: int = Peak.STATIC_WIDTH;
  private const HEIGHT: int = Peak.STATIC_HEIGHT;
  private const EMPTY: int = Peak.STATIC_EMPTY;
  private const WATER: int = Peak.STATIC_WATER;
  private const SOURCE: int = Peak.STATIC_SOURCE;
  
  public var count: int = 0;
  public var color: uint;
  public var id: int;
  public var target: Life = null;
  public var heat: Vector.<int>;
  public var spawnTimer: int;
  public var starveTimer: int;
  public var maxSpawnTime: int;
  public var maxStarveTime: int;
  private var lifeMap: BitmapData;
  private var lifeVec: Vector.<int>;
  private var waterVec: Vector.<int>;
  
  public function Life(id: int, lifeVec: Vector.<int>, color: uint, lifeMap: BitmapData, waterVec: Vector.<int>, maxSpawnTime: int, maxStarveTime: int) {
    this.id = id;
    this.lifeVec = lifeVec;
    this.color = color;
    this.lifeMap = lifeMap;
    this.heat = waterVec.concat();
    this.spawnTimer = this.maxSpawnTime = maxSpawnTime;
    this.starveTimer = this.maxStarveTime = maxStarveTime;
  }
  
  public function spawn(x: int, y: int): void {
    var dest: int = x + y*WIDTH;
    if (lifeVec[dest] != EMPTY) return;
    heat[dest] = SOURCE;
    lifeVec[dest] = id;
    lifeMap.setPixel32(x,y,color);
    count++;
  }
  
  public function kill(x: int, y: int): void {
    var dest: int = x + y*WIDTH;
    heat[dest] = SOURCE-1;
    lifeVec[dest] = EMPTY;
    lifeMap.setPixel32(x,y,0);
    count--;
  }
  
  public function updateHeat(): void {
    var i: int;
    var j: int;
    var k: int;
    
    var sample: int = heat[0 + (HEIGHT-1) * WIDTH];
    var prevSample: int;
    
    var localRandom: Function = Math.random;
    
    if (localRandom() > 0.5) {
      for (j = 0; j < HEIGHT; j++) {
        k = j * WIDTH;
        if (localRandom() > 0.5) {
          for (i = 0; i < WIDTH; i++) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
          j++;
          k = j * WIDTH;
          for (i = WIDTH-1; i >= 0; i--) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
        } else {
          for (i = WIDTH-1; i >= 0; i--) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
          j++;
          k = j * WIDTH;
          for (i = 0; i < WIDTH; i++) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
        }
      }
      
      for (i = 0; i < WIDTH; i++) {
        if (localRandom() > 0.5) {
          for (j = 0; j < HEIGHT; j++) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
          i++;
          for (j = HEIGHT-1; j >= 0; j--) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
        } else {
          for (j = HEIGHT-1; j >= 0; j--) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
          i++;
          for (j = 0; j < HEIGHT; j++) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
        }
      }
    } else {
      for (i = 0; i < WIDTH; i++) {
        if (localRandom() > 0.5) {
          for (j = 0; j < HEIGHT; j++) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
          i++;
          for (j = HEIGHT-1; j >= 0; j--) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
        } else {
          for (j = HEIGHT-1; j >= 0; j--) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
          i++;
          for (j = 0; j < HEIGHT; j++) {
            prevSample = sample;
            k = i + j * WIDTH;
            sample = heat[k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[k] = sample;
          }
        }
      }
      
      for (j = 0; j < HEIGHT; j++) {
        k = j * WIDTH;
        if (localRandom() > 0.5) {
          for (i = 0; i < WIDTH; i++) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
          j++;
          k = j * WIDTH;
          for (i = WIDTH-1; i >= 0; i--) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
        } else {
          for (i = WIDTH-1; i >= 0; i--) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
          j++;
          k = j * WIDTH;
          for (i = 0; i < WIDTH; i++) {
            prevSample = sample;
            sample = heat[i + k];
            if (sample == SOURCE || sample == WATER) continue;
            if (prevSample > sample) sample = prevSample - 1; else sample-=4;
            if (sample < 0) sample = 0;
            heat[i + k] = sample;
          }
        }
      }
    }
  }
}