Finally, extend the Grid class. The constructor needs to call the super's constructor, and pass the subclass you've defined above and your desired 'default' state. There's also an optional 'step' method, which is mostly useful for cellular automata, and enables the play and pause features in the editor (and which can be useful in other contexts as well). This method determines the state of the grid which is to follow immediately from its current state. The 'clone' method from the Hex subclass may be incredibly useful here.
-And that's it. To use your new implementation in the editor, just set the variable =g= to a new instance of your grid, and replace 'basic.js' with the name of your file in 'index.html', then load up the 'index.html' in your browser.
+And that's it. There are only a couple more things to do before you can use your new implementation in the editor. First, set the variable =g= to a new instance of your grid. Then, make a copy of 'basic.html' named as you'd like, and then in that file replace 'basic.js' with the name of the file your implementation is in. With that done, you can load up the new html file in your browser and get to it!
The editor has copying and pasting features, transformation features, saving, loading, importing and exporting features, and can advance and play cellular automata.
\ No newline at end of file
--- /dev/null
+<!doctype html>
+<meta charset="utf-8">
+<html>
+ <head>
+ <script src="grid.js"></script>
+ <script src="cell.js"></script>
+ <script src="play.js"></script>
+ <script src="basic.js"></script>
+ <script>
+ function run() {
+ lc();
+ }
+ </script>
+ <style>
+ span {
+ margin=left: 15px;
+ }
+ input[type=number] {
+ width: 30px;
+ margin-left: 15px;
+ }
+ select {
+ margin-left: 15px;
+ }
+ #es {
+ margin-left: 15px;
+ }
+ </style>
+ <link rel="icon" type="image/png" href="icn.png"/>
+ <title>hexagonal grids</title>
+ </head>
+ <body onload="run()" style="background-color: #f8f8ff;">
+ <div class="ctrl">
+ <span>
+ <input type="button" id="step" value="step"/>
+ <input type="button" id="playpause" value="play"/>
+ <input type="range" id="tempo" value="150" min="20" max="500"/>
+ <input type="button" id="clear" value="clear"/>
+ <input type="button" id="reset" value="reset"/>
+ </span>
+ <span>
+ <input type="number" id="rad" value="9" min="1" max="30" step="1"/>
+ <input type="button" id="rot" value="rotate hex"/>
+ <input type="button" id="flp" value="flip hex"/>
+ <input type="button" id="rfl" value="reflect hex"/>
+ <input type="button" id="copy" value="copy hex"/>
+ <input type="button" id="paste" value="paste hex"/>
+ </span>
+ <span>
+ <input type="number" id="slot" value="1" min="1" max="9" step="1"/>
+ <input type="button" id="save" value="save state"/>
+ <input type="button" id="load" value="load state"/>
+ </span>
+ <span>
+ <input type="button" id="es" value="export state"/>
+ <input type="button" id="is" value="import state"/>
+ </span>
+ <details><summary></summary><span id="outzone"></span></details>
+ </div>
+ <div><canvas width="2000" height="2000" id="c"></canvas></div>
+ </body>
+</html>
<head>
<script src="grid.js"></script>
<script src="cell.js"></script>
- <script src="play.js"></script>
- <script src="basic.js"></script>
+ <script src="minplay.js"></script>
+ <script src="life.js"></script>
<script>
function run() {
lc();
+ setInterval(play, 200);
}
</script>
<style>
+ .d {
+ text-align:center;
+ margin: 0 auto;
+ }
+ .d2 {
+ max-width: 600px;
+ margin: 0 auto;
+ }
span {
margin=left: 15px;
}
<title>hexagonal grids</title>
</head>
<body onload="run()" style="background-color: #f8f8ff;">
- <div class="ctrl">
- <span>
- <input type="button" id="step" value="step"/>
- <input type="button" id="playpause" value="play"/>
- <input type="range" id="tempo" value="150" min="20" max="500"/>
- <input type="button" id="clear" value="clear"/>
- <input type="button" id="reset" value="reset"/>
- </span>
- <span>
- <input type="number" id="rad" value="9" min="1" max="30" step="1"/>
- <input type="button" id="rot" value="rotate hex"/>
- <input type="button" id="flp" value="flip hex"/>
- <input type="button" id="rfl" value="reflect hex"/>
- <input type="button" id="copy" value="copy hex"/>
- <input type="button" id="paste" value="paste hex"/>
- </span>
- <span>
- <input type="number" id="slot" value="1" min="1" max="9" step="1"/>
- <input type="button" id="save" value="save state"/>
- <input type="button" id="load" value="load state"/>
- </span>
- <span>
- <input type="button" id="es" value="export state"/>
- <input type="button" id="is" value="import state"/>
- </span>
- <details><summary></summary><span id="outzone"></span></details>
+ <div class="d2">
+ <div class="d">
+ <div>
+ <p>Here's a nice playground for a few cellular automata on a hexagonal grid:</p>
+ <ul>
+ <li><a href="rps.html">Game of Life</a></li>
+ <li><a href="ww.html">WireWorld</a></li>
+ <li><a href="life.html">Rock-Paper-Scissors Automata</a></li>
+ </ul>
+ <p>In all of these, you'll be brought to a blank canvas, where you can create your own patterns and run them as automata. Clicking in the vast space you're given will add or remove cells from the simulation and change their statuses. You can also change the speed with the slider, and do some advanced editing with the other tools at the top, as well as saving and exporting your arrangements (the export output is hidden by the little triangle until you click it).</p>
+ <p>The Game of Life one is a standard port of the classic. You can even adjust how many neighbors cause cells to survive or spawn.</p>
+ <p>WireWorld is another classic automata. This is the one I've done the most with, and it's fairly straightforward to implement various logic gates here. I've done so, and put a 'demo' menu on this page, so you can see some examples of this. There are some cool ones, take a look!</p>
+ <p>If you'd like to implement your own form of hexagonal-grid automata, check out the <a href="README">README</a> file.</p>
+ <p>Just a note, this is not fast. The primary focus of this was to get something extensible and fun up quickly. I am liable to redesign this with speed in mind, but if I do, it will keep the same extensibility you find in the current version.</p>
+ </div>
+ <input type="button" id="step" value="step" hidden />
+ <input type="range" id="tempo" value="150" min="20" max="500" hidden />
+ <div><canvas width="200" height="200" id="c"></canvas></div>
+ <input type="button" id="refr" value="refresh" />
+ <p>Maybe, one day in the distant future, if we're nice enough, bees will help us compute things. This is the first step towards that.</p>
+ </div>
</div>
- <div><canvas width="2000" height="2000" id="c"></canvas></div>
</body>
</html>
<script src="life.js"></script>
<script>
function run() {
+ initRulue();
lc();
}
</script>
//let PRODUCES = [2];
// alt?
-let SURVIVAL = [3];
-let PRODUCES = [2];
+//let SURVIVAL = [3];
+//let PRODUCES = [2];
+let SURVIVAL = new Set([3]);
+let PRODUCES = new Set([2]);
const LifeState = {
}
let nbrct = nbrs.reduce(reducefn,0);
if(cellcp[i].state == LifeState.ON) {
- if(!SURVIVAL.includes(nbrct)) {
+ if(!SURVIVAL.has(nbrct)) {
this.cells[i].state = LifeState.OFF;
}
}
if(cellcp[i].state == LifeState.OFF) {
- if(PRODUCES.includes(nbrct)) {
+ if(PRODUCES.has(nbrct)) {
this.cells[i].state = LifeState.ON;
}
}
}
}
-
+function randHex(q,r,sz,g,val=0.5) {
+ let h = g.copyHex(q,r,sz);
+ for(let c of h) {
+ g.change(Math.random() > val? LifeState.OFF:LifeState.ON, c.q,c.r);
+ }
+}
function randomize(q,r,g) {
// puts random elements in the grid
for(let i=0;i<q;i++) {
}
}
}
+
+function initRulue() {
+ let toggler = (e) => {
+ let which = parseInt(e.target.name);
+ let toBeChanged = e.target.id[0] == 'b' ? PRODUCES: SURVIVAL;
+ if(e.target.checked) {
+ toBeChanged.add(which);
+ }
+ else {
+ toBeChanged.delete(which);
+ }
+ }
+ let a = ["s1","s2","s3","s4","s5","s6","b1","b2","b3","b4","b5","b6"];
+ for(let i of a) {
+ console.log(i);
+ document.getElementById(i).onclick = toggler;
+ }
+}
--- /dev/null
+
+
+
+var g = null; // must be set elsewhere before using anything in here
+
+//params
+xcenter = 200/2
+ycenter = 200/2
+scale = 5
+
+var ctx = null;
+var c = null;
+
+var timeout = 200;
+var rstgrid = g;
+var intervalID = null;
+
+
+function play() {
+ g.step();
+ drawGrid(g, ctx, xcenter,ycenter,scale);
+}
+function lc() {
+ c = document.getElementById('c');
+ ctx = c.getContext('2d');
+ randHex(5,5,12,g,0.6);
+ drawGrid(g, ctx, xcenter,ycenter,scale);
+ b = document.getElementById('refr');
+ b.onclick = refresh;
+}
+function refresh() {
+ randHex(5,5,12,g,0.5);
+}
}
}
}
+function randHex(q,r,sz,g) {
+ let h = g.copyHex(q,r,sz)
+ for(let c of h) {
+ let rv = Math.floor(Math.random()*3);
+ if(rv<1)
+ g.change(RPSState.ROCK,c.q,c.r);
+ else if(rv<2)
+ g.change(RPSState.PAPER,c.q,c.r);
+ else
+ g.change(RPSState.SCISSORS,c.q,c.r);
+ }
+}