Thursday, 1 December 2016

Hacking JavaScript Games - Cellular Automata - Supporting Notes

Hacking JavaScript Games - Cellular Automata - Supporting Notes


Hacking JavaScript Games - Cellular Automata from Alan Richardson

And there are more notes below:



Hacking JavaScript Games - Cellular Automata - Supporting Notes


We will Hack This Game

Cellular Automata Life Game Suitable for Hacking


Supporting Videos



Challenge - Change Colour in Cellular Automata

The simplest thing we can do to this game of life is to change the colour.
It is also the most visible thing.
Using the game:

Colour in the Game

In the code we have the World function - which is an object class.
And the World object has an entityColour.
If we can change that, then we can change the colour.
I could use any six values from 0-9, A-F to make an HTML colour code
e.g. http://htmlcolorcodes.com

Change colour by debugging

I set a break point on the line where the colour is set in the sources view.
  • Line 153
  • this.entityColour = "#FF0000";
Then:
  • Step over that line so the colour is set.
  • press esc to get the console up.
  • change the colour in the console:
this.entityColour = "#111111";

Change colour from console when runnning game

  • change the colour using the console
  • inspect element and find where World is instantiated with new. i.e. ctrl+F and search for new World.
var world = new World(worldSizes.myWorldWidth, 
                      worldSizes.myWorldHeight);
And I can change that whenever I want:
world.entityColour = "#111111";

Watch The Video

https://youtu.be/gWnvKQOb2yc

Change Colour Automatically

Simple - have a bot to change colour every set time interval - say 1000 milliseconds.
The challenge is that I need to use a hex value to do that. So let's figure that out first.

Random Hex Value

  • I can use 0xFF as a Hex integer value, and it is 255
  • I can use the toString method on a Number to convert a number to a base e.g. base 2 for binary or base 16 for hex:
  • I need to get a 6 character string, even if my hex value is only FF and I can do that by creating a string and using the last 6 characters e.g.
  • And I want my string to be "0" padded at the front so I'll just add "000000" at the front of any string:
  • And I want a Hash # in front
var myNum=3;
"#" + (("000000" + myNum.toString(16)).substr(-6))

Use Game Random Int Code

The game already has a random number generator:
getRandomInt(0, 0xFFFFFF);
Use that
"#" + (("000000" + 
getRandomInt(0, 0xFFFFFF).toString(16)).substr(-6))
And I have a way to generate a random HTML hex colour value.

Randomly set the colour every second

Create a bot to change the colour every 1000 milliseconds.
var colourChangeBot = setInterval(function() {
    world.entityColour = "#" + (("000000" + 
        getRandomInt(0, 0xFFFFFF).toString(16)).substr(-6));
}, 1000);
Stop the bot with:
clearInterval(colourChangeBot);

Make Bot Faster or Slower

Change the value 1000, to make it faster, or slower:
  • 500 - every half second
  • 200 - every 200 milliseconds
Danger Flashing Lights.
Just be careful you don't make it so fast that you have a seizure.

Cycle over all the colours

This is a bit slower:
var currColour = 0;
var colourChangeBot = setInterval(function() {
    world.entityColour = "#" + ("000000" + 
          currColour.toString(16)).substr(-6);
    currColour++;
    if (currColour >= 0xFFFFFF) {
        currColour = 0;
    }
}, 1)

Watch The Video

https://youtu.be/hfE99d4Slck

References



An Invasion Challenge

Control the Invasion

Stop the invasion by calling:
stopInvasion();
Start an invasion with:
startInvasion(100);
Where 100 is the amount of milliseconds before the next lifeform is added.

Create a Glider

addLifeForms.glider(world,10,0);
Which creates a glider at position (10,0)
I could create an invasion of gliders like that
var gliderInvasion = setInterval(function() {
    addLifeForms.glider(world, 10, 0);
}, 1000);

But an invasion should be random

First stop the old invasion:
clearInterval(gliderInvasion)
Then start our new invasion:
var gliderInvasion = setInterval(function() {
    addLifeForms.glider(world, 
       getRandomInt(0, world.xSize - 50), 
       getRandomInt(0, world.ySize - 50));
}, 100);

Watch The Video

https://youtu.be/CeOzcn7pBQY


Change World Size

One of the challenges in the Cellular Automata game is changing the world size.
There is a clue in the game code, because we know that it does some resizing when we change the window size.
 worldSizes.calculateScales();
And...
var world = new World(
            worldSizes.myWorldWidth, 
            worldSizes.myWorldHeight);

Let's Change the World - Make is smaller

worldSizes.myWorldWidth=100; 
worldSizes.myWorldHeight=100;
worldSizes.calculateScales();

Let's Change the World - Make is bigger

worldSizes.myWorldWidth=1000;
worldSizes.myWorldHeight=1000;
worldSizes.calculateScales();
Nope, that didn't work

Let's Change the World - Make is bigger

tell the world that it is bigger
worldSizes.myWorldWidth=1000;
worldSizes.myWorldHeight=1000;
world.xSize=1000; world.ySize=1000;
worldSizes.calculateScales();
That worked - and its a little slower now, because thats 1000 x 1000 grid, which is 1,000,000 (1 million) cells!

Simulate ZX-81

The ZX-81 had a resolution of 64x48, and it was black and white, so let's simulate that.
worldSizes.myWorldWidth=64; worldSizes.myWorldHeight=48;
world.xSize=worldSizes.myWorldWidth; 
world.ySize=worldSizes.myWorldHeight;
world.entityColour="#000000";
worldSizes.calculateScales();
And slow it down:
stopInvasion();
stopGame();
startGame(1000);
startInvasion(3000);

Watch The Video

https://youtu.be/lLnyNP33S_Q


Create A Random World

We first want total control over the game.
  • start game
    • startGame(5)
  • stop game
    • stopGame()
  • stop invasion
    • stopInvasion()

Stop the Game and Clear the world

stopGame();
stopInvasion();
It would be useful to also clear the display.
world.nukeEmAll();
But we'll only see the results if we start & stop the game again:
startGame(5);
stopGame();

Randomly generate stuff

Reset the population:
world.population = [];
I'll add items in a loop, and create 100 of them:
for(var itemLoop=0; itemLoop < 100; itemLoop++){
    world.addToPopulation(new LifeForm().move(0,
    getRandomInt(0, world.xSize), 
    getRandomInt(0, world.ySize)));
}
Start the game, we should see the results:
startGame(5);
100 might not actually be big enough, you might need to create more for a viable world.

Experiment and Watch the Video

Experiment with different loop sizes to see what works for your world - remember its a harsh world out there for these cells so sometimes you need to start with a lot of them.
https://youtu.be/uZv2s5QjPps


History of Game Of Life

John Horton Conway's Game of Life

Programs to download, install and experiment with:


online games of life:

Cellular Automata Life Game Suitable for Playing

Cellular Automata Life Game Suitable for Hacking


Related References:

Good simple Overview
Good set of resources
Wolfram description
History of Computer Game Design - Stanford

Recommended Books

  • Artificial Life - by Stephen Levy
  • The Garden in the Machine by Clause Emmeche

Watch A Video on the History of the Game of Life

https://youtu.be/H1rMF7SnGn8


Other Contributions

Danny Dainton experimented with the Game of life and created a 'text' image.
https://twitter.com/DannyDainton/status/789499155785842688
And he has released thecode for it on github.
https://github.com/DannyDainton/Cellular_Automata_Hacking

Thanks Danny


How to Create Text

I took a different approach to Danny for the text creation:
  • I thought it would be easier to write text to the screen
  • scrape the pixels
  • add the pixels as blocks to the world

First Write the Text

// stop the world and clear the world and screen
stopInvasion();
stopGame();
world.population = [];
clearCanvas();

// plot the text we want

context.font = "14px verdana";
context.strokeStyle="#FF0000";
// kerning hack
// http://stackoverflow.com/questions/8952909/letter-spacing-in-canvas-element
var padding = String.fromCharCode(8202)+String.fromCharCode(8202);
context.strokeText("Thank".split("").join(padding), 0, 15);
context.strokeText("You".split("").join(padding), 0, 30);
context.strokeText("Danny".split("").join(padding), 0, 45);

Then get the pixels and add them to the world

var imageData = context.getImageData(0,0,200,60);

var scale=4; // less than 4 and it will evolve
var imageX=0;var imageY=0;
for (var i=0;i<imageData.data.length;i+=4)
  {
  if(imageData.data[i]!==0 ||
     imageData.data[i+1]!==0 || 
     imageData.data[i+1] !== 0){

    addLifeForms.block(world, imageX*scale,imageY*scale);
   }
 
    imageX++;
  if(imageX>=200){
     imageX=0;
     imageY++;
  }
}
Then startGame(5);





Watch Bonus Video: Making Text With Cellular Automata 



What can you do with it?

Experiment and see what you come up with


No comments:

Post a Comment