-
-
Save PotOfCoffee2Go/657ae23ec2939600941db6c20443fb13 to your computer and use it in GitHub Desktop.
The classes that run the game has been more or less been updated to ES6 - and given the drive and will would integrate into a D3 representation of the automata. Since I do not have that drive or will - just interfaced to observablehq using the simplest methods possible.
ObservableHq runs Javascript class instances using a Web Worker. There are various ways of accessing the DOM, and for the DOM to have access to the class functions (such as 'onclick' functions of the buttons).
I decided to use the browser standard built-in object globalThis (a single line addition to the class constructor) of the 'Game' class which allows global access to the Game's functions. Thus, only the last instantiated (new Game(...)) is the active instance interfacing to the DOM. (btw - multiple instances of 'Game' in other contexts would be a 'layer').
Since there is only one DOM - can only have one active instance of Game - thus globalThis works nicely since it overwrites references to any previous instances, and the Garbage Collector will quietly dispose of them.
To insure the DOM is ready, the code checks for a known HTML element, when the element switches from undefined to defined the DOM is considered ready. Simple but relatively effective.
Due to 'Game' instance being the only interface recognized by the observablehq notebook - modifications to classes instantiated by the Game class will not be 're-loaded' automatically by observablehq. Basically, might have to refresh the page ;(
These two classes display the documentation that you are viewing right now!
The goals are:
- Consolidate the documentation in one place
- Navagation to organize documentation
- Have a pleasing transition to show/hide the documention
- Once shown, switch from document to document quickly
- Minimal transitions
- Display appropriate sub-menu (
navsub
)
There are three div's with ids 'navbar', 'navsub' and 'docs'. The transitions are performed by CSS in the Web Page style()
function in an ObservableHq cell below, the styles can be identified by the comment /* Document display */
. The transitions occur when the Docs class adds/removes classes from the <div>
classList.
A sample of the ObservableHq cell you are currently viewing should look something like:
html `
<div id="navbar">
<button onclick="docs.toggleDoc(this);" id="docs-show-btn"> Intro </button>
<button onclick="docs.displayDoc('usagebar','usage');"> Usage </button>
<button onclick="docs.displayDoc('designbar','design');"> Design </button>
<button onclick="docs.displayDoc('nobar','why');"> Why? </button>
<div id="navsub"></div>
</div>
<div id="docs"></div>
`;
The Intro
button is special in that it changes to Hide
when the documention is being displayed. The docs-show-btn
id is used to fix the width of the button so it doesn't change when the text changes.
Note the Intro button calls
docs.toggleDoc()
passing a reference to itself.Intro
is the only button that usesdocs.toggleDoc
. Notice all the others calldocs.displayDoc('sub-menu-name','document-name');
. Also the textIntro
andHide
are hard-coded in theDocs
class.
The Why?
button calls docs.displayDoc
with the 'sub-menu-name' of 'nobar' - which hides the sub-menu.
Docs
controls the DOM to show/hide the documentation and creates an instance of Documents
which reads the documentation Markdown files from a GitHub Gist.
Docs
class uses [globalThis][1] globalThis.docs = this;
in the constructor so that the DOM can reference it in the onclick="..."
attribute. If another (last) instance is created, it becomes the current docs
instance - replacing the previous one (old one will be Garbage Collected). If/whan a new Docs
is instantiated the documents are re-fetch from GitHub, which is a easy way to update documents to the most recent commit.
The targetBlank()
function adds target="_blank"
to all <a>
nchor tags. This allows the reader to click a link without refreshing the page thus wiping out the currently running cellular automaton! - which would be a sad thing ;(
Other than that nothing to special about it. The timing of the transitions was by trial and error, so probably a lot of improvement could be done if someone actually designed a coordinated start/duration/stop/delay between the div
elements.
Documents
is instantiated by Docs
. This class contains all the Markdown documents which are fetch from a [GitHub Gist][2].
The following code fragments from the Documents
class illustrates how the Gist URL and filenames in the Gist are accessed (.md
is automatically appened to each filename.
init() {
this.gist = 'https://gist.githubusercontent.com/' +
'PotOfCoffee2Go/657ae23ec2939600941db6c20443fb13/' +
'raw/';
this.mdFileList = [
'intro',
'usage', 'usage_controls', 'usage_pattern', 'usage_world', 'usage_data',
'design', 'design_document', 'design_game', 'design_display', 'design_pattern',
'design_agent', 'design_cell', 'design_world',
'why'];
}
In this function the sub-menus HTML are declared.
navsubsHtml() {
// --- design sub-menu
this.designbar = html `
<span>
Design:
<button onclick="docs.displayDoc('designbar','design_document');">Docs</button>
<button onclick="docs.displayDoc('designbar','design_game');">Game</button>
<button onclick="docs.displayDoc('designbar','design_display');">Display</button>
<button onclick="docs.displayDoc('designbar','design_pattern');">Pattern</button>
<button onclick="docs.displayDoc('designbar','design_world');">World</button>
<button onclick="docs.displayDoc('designbar','design_cell');">Cell</button>
<button onclick="docs.displayDoc('designbar','design_agent');">Agent</button>
</span>
`;
You can also add documents directly (without the need to fetch from the Gist).
// A document named 'buttons'
this.buttons = md `
Buttons - There are three screens used to control and display the
cellular automata. The World screen, the Pattern screen, and the Data
screen. The World screen has all of the controls and displays info on
the current generation.
`;
}
Note! the names of files, documents, and sub-menus must be unique as all of them are in the same object!
Visit Conway's Game of Life on wikipedia for information about the game itself.
This implementation is very basic and useful for playing around with smaller patterns of gliders, spaceships, oscillators, guns and such. Recommend golly for any serious cellular automata studies.
As a tribute to Mr. Conway, I wish to present the Game of Life in the spirit of the 1970's when he introduced the world to cellular automata. The display is totally text based - a flashback to a simpler, mouseless era of keyboards without a 'cmd' key, fuzzy CRT screens, and when Tiny Pascal was cutting edge. Visualizations were restricted by the hardware but still engaging when done well.
My first attempt at programming a cellular automaton was in BASIC at Kiewit Computation Center, more years ago than I wish to admit. But wasn't until Tiny Pascal was available on the Radio Shack TRS-80 that actually/kinda got one to work.
Thus this notebook is not very '@observablehq'-ish as I just copy/paste(d) the classes from a web page I had created a quite while back and figured would leave well enough alone. Check out the Design for details.
Mr. Conway, we miss you and hopefully you would approve.
{ | |
"name": "Game-of-Life-Docs", | |
"version": "1.0.0", | |
"description": "Cellular automata Conway's Game of Life", | |
"main": "_Observe_GOL.md", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"keywords": ["cellular automata", "Game of Life"], | |
"author": "PotOfCoffee2Go <https://github.com/PotOfCoffee2Go>", | |
"license": "ISC" | |
} |
The control screen has a set of buttons and a slider that controls activities on the world screen.
- Clear
- Sets all cells to dead - all statistics to zero
- Start/Stop
- Toggles starting and stopping generations
- Step
- Perform a single generation
- (slider)
- Delay (speed) between generations
- Edit
- Set cell alive/dead using mouse
- Random
- Fill world with random set of alive cells
One of the most striking early visualizations was to watch the complex patterns generated by the most simpliest rules of the Game of Life, which anyone with an interest in programmming could produce - and watch with amazement as an intricate hereto unseen world of life and death unfolded before them on the screen.
That spirit to describe and portray the complex in visually exciting and yet simple understandable terms. I am amazed and awestruck at some of the visualizations that are producded by people using D3 on ObservableHq. It kindles the excitment of the first visualizations I saw back in the early years of the personal computer.
Is enlightening to see the quest to expand knowledge, challenge minds, and engage curiousity lives on today as much as it did 50+ years ago.