Skip to content

Instantly share code, notes, and snippets.

@sampersand
Created October 17, 2015 07:58
Show Gist options
  • Save sampersand/34bb3009264f6c495506 to your computer and use it in GitHub Desktop.
Save sampersand/34bb3009264f6c495506 to your computer and use it in GitHub Desktop.
import java.util.Random;
public class FireSim {
public static final int EMPTY = 0;
public static final int BURNING_STATE_1 = 1;
public static final int BURNING_STATE_2 = 2;
public static final int TREE = 3;
public static final int SAPLING = 4;
public static final int LIGHTNING = 5;
public static final int INFLAMMABLE = 6; // small large
public static final int SMOKE_STATE_1 = 7;
public static final int SMOKE_STATE_2 = 8;
public static final int FIREFIGHTER = 9;
public static final int HOUSE = 11;
public static final String[] typeChars = {" ", "🔥", "💥", "🌲", "🌱", "⚡️","🌳","💭","💭","🚒","🚒","🏡"};
public static Random RAND = new Random();
private int[][] earth;
private double entropyFire;
private double entropyGrow;
private double entropyLightning;
private double entropyWither = 0.2D;
private double entropyInflammable = 0.0001D;
private double windDir;
private double windStr;
private int saplingTreeReqToGrow = 1;
private int treeReqToNotWither = 2;
private int convFromRoman(String inp){
char[] numerals = {'I','V','X','L','C','D','M'};
int[] decivals = {1,5,10,50,100,500,1000};
int ret = 0;
return ret;
}
public static void main(String[] args) {
// System.out.println(convFromRoman("MCMXLIII"));
// Y | X | FIRE| GROW| LIGHT| WIND DIR | WIND STR
// FireSim earth = new FireSim(30, 58, 0.75D,0.02D,0.0002D);
// FireSim earth = new FireSim(30, 117, 0.25, 0.02D, 0.002D, Math.PI/4*0, 0.4);
FireSim earth = new FireSim(30, 115, 0.75D,0.02D,0.0002D); //neither wins
earth.seed();
earth.dispEarth();
while(earth.update(100))
earth.dispEarth();
earth.dispEarth();
}
public FireSim() {
this(10);
}
public FireSim(int xy) {
this(xy, xy);
}
public FireSim(int x, int y) {
this(x, y, 0.2D);
}
public FireSim(int x, int y, double burnprob) {
this(x, y, burnprob, 0);
}
public FireSim(int x, int y, double burnprob, double growprob) {
this(x, y, burnprob, growprob, 0);
}
public FireSim(int x, int y, double burnprob, double growprob, double lightprob) {
this(x, y, burnprob, growprob, lightprob, 0);
}
public FireSim(int x, int y, double burnprob, double growprob, double lightprob, double winddir) {
this(x, y, burnprob, growprob, lightprob, lightprob, 0);
}
public FireSim(int xL, int yL, double burnprob, double growprob, double lightprob, double winddir, double windpow) {
earth = new int[xL + 2][yL + 2];
for(int x = 1; x < earth.length -1; x++) {
for(int y = 1; y < earth[0].length -1; y++) {
earth[x][y] = TREE;
}
}
entropyFire = burnprob;
entropyGrow = growprob;
entropyLightning = lightprob;
windDir = winddir;
windStr = windpow;
}
public void setMisc(double probwither, int mintreecount, double probinflam){
entropyWither = probwither;
entropyInflammable = probinflam;
saplingTreeReqToGrow = mintreecount;
}
public void seed() {
for(int x = 0; x < FireSim.RAND.nextInt(4) + 1; x++)
earth[FireSim.RAND.nextInt(earth.length - 1) + 1]
[FireSim.RAND.nextInt(earth[0].length - 1) + 1] = LIGHTNING; // FIREFIGHTER;
}
public boolean update() {
return update(200);
}
public boolean update(int delay) {
try {
Thread.sleep(delay);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
int[][] ret = new int[earth.length][earth[0].length];
for(int x = 1; x < earth.length -1; x++) {
for(int y = 1; y < earth[0].length -1; y++) {
ret[x][y] = earth[x][y];
}
}
ret = applySpread(ret);
boolean same = true;
for(int x = 1; x < earth.length -1; x++) {
for(int y = 1; y < earth[0].length -1; y++) {
same = earth[x][y] == ret[x][y];
if(!same)
break;
}
}
if(same) {
earth = ret;
for(int[] x : earth)
for(int y : x)
if(y != EMPTY && y != INFLAMMABLE)
return true;
return false;
}
earth = ret;
return true;
}
public void dispEarth() {
final String ANSI_CLS = "\u001b[2J";
final String ANSI_HOME = "\u001b[H";
System.out.print(ANSI_CLS + ANSI_HOME);
System.out.flush();
for(int x = 1; x < earth[0].length; x++) System.out.print("-");
System.out.println();
for(int x = 1; x < earth.length - 1; x++) {
for(int y = 1; y < earth[0].length - 1; y++) {
System.out.print(typeChars[reduce(earth[x][y])]);
}
System.out.println();
}
for(int x = 1; x < earth[0].length; x++) System.out.print("-");
System.out.println();
}
private int reduce(int pos){
return pos >= typeChars.length ? typeChars.length-1 : pos;
}
private int updatePatch(int[][] dirs) {
int site = dirs[1][1];
int[] count = new int[typeChars.length];
for(int[] row : dirs) for (int pos : row)
count[reduce(pos)]++;
count[reduce(site)]-=1; //the for loop counts the center one, which is not desired.
switch(site){
case EMPTY:
if(FireSim.RAND.nextDouble() <= entropyGrow && count[TREE] >= saplingTreeReqToGrow)
if(FireSim.RAND.nextDouble() <= entropyInflammable)
return INFLAMMABLE;
else
return SAPLING;
return EMPTY;
case SMOKE_STATE_2:
return SMOKE_STATE_1;
case SMOKE_STATE_1:
return EMPTY;
case LIGHTNING:
return BURNING_STATE_2;
case BURNING_STATE_2:
return BURNING_STATE_1;
case BURNING_STATE_1:
// if(count[FIREFIGHTER] == 1 && count[BURNING_STATE_1]+count[BURNING_STATE_2]<=2)
// return FIREFIGHTER;
return SMOKE_STATE_2;
case FIREFIGHTER:
if(count[BURNING_STATE_1]+count[BURNING_STATE_2] > 5)
return EMPTY;
if(count[FIREFIGHTER] > 1)
return EMPTY;
return FIREFIGHTER;
case INFLAMMABLE:
return FireSim.RAND.nextDouble() <= entropyFire * entropyLightning ? LIGHTNING : INFLAMMABLE;
case SAPLING:
if(FireSim.RAND.nextDouble() <= entropyGrow)
return TREE;
if(count[TREE] < treeReqToNotWither)
return FireSim.RAND.nextDouble() <= entropyWither ? EMPTY : SAPLING;
return SAPLING;
case HOUSE:
case TREE:
if (count[TREE] < treeReqToNotWither) //withering
if (FireSim.RAND.nextDouble() <= entropyWither)
return EMPTY;
if (FireSim.RAND.nextDouble() <= entropyFire * entropyLightning)
return LIGHTNING;
//burning
double burnChance = 0D;
for(int x = 0; x < dirs[0].length; x++) //2 is dirs row
for(int y = 0; y < dirs.length; y++) //2 is dirs hight
if(dirs[x][y] == BURNING_STATE_1 || dirs[x][y] == BURNING_STATE_2){
burnChance +=.2D;
//lazy
// double ang = Math.PI/4;
// if(x == 0) ang *= 3 - y;
// if(x == 1) ang *= y == 0 ? 4 : 0;
// if(x == 2) ang *= 5 + y;
// System.out.print(
// Math.abs(Math.sin((windDir-ang)/2))+
// "|"+ ang/Math.PI+
// "|"+ windDir/Math.PI+
// "|"+x+"|"+y+"|"+dirs[x][y]+"|");
// for(int[] X : dirs) for(int Y : X) System.out.print(Y+",");
// System.out.println();
// burnChance += windStr
// burnChance += windStr * Math.abs(Math.sin((windDir-ang)/2));
// burnChance += windStr * (Math.cos(windDir) - Math.cos(ang) +
// Math.sin(windDir) - Math.sin(ang));
}
if(FireSim.RAND.nextDouble() > 1 - Math.abs(burnChance) * entropyFire)
return BURNING_STATE_2;
else
return site;
default:
return EMPTY;
}
}
private int[][] applySpread(int[][] pearth) {
for(int x = 1; x < pearth.length - 1; x++)
for(int y = 1; y < pearth[0].length - 1; y++)
// pearth[x][y] = updatePatchOld(earth[x][y], earth[x][y + 1], earth[x][y - 1],
// earth[x + 1][y], earth[x - 1][y]);
pearth[x][y] = updatePatch(new int[][]{
{earth[x-1][y+1], earth[x][y+1], earth[x+1][y+1]},
{earth[x-1][y] , earth[x][y] , earth[x+1][y]},
{earth[x-1][y-1], earth[x][y-1], earth[x+1][y-1]}});
return pearth;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment