|
Cellular Automata Laboratory
|
|
WebCA Development Log
Build 513 (2017-06-26 12:30 UTC)
Web Cellular Automata Laboratory
Development Log
by John Walker
2017 April 11
When a rule was loaded which specified texture or random bits
in the pattern and then another rule which had no requests,
Map.setRuleRequests() failed to clear the previously set
requests in the map. Fixed.
Implemented the 8 neighbour semitotalistic evaluator for world
type 10, Rule.og8r, and added support for world type 10 in
rule loading and the oneGeneration function in casim.js. Note
that rule lookup tables for world type 10 are not rotated like
those for world types 0 and 1, and hence can be used directly
as loaded from the .jc file.
Implemented the 4 neighbour semitotalistic evaluator for world
type 11. As it happens, none of our standard sample rules
ever use world type 11--it was used only in heat4.pas, which was
not included as a sample. I translated the program to Java and
made a heat4.jc rule, which appears to work OK. The new rule
is in .../pdcalab/ca/sample/java/.
Added an evaluator, Rule.owncode(), which calls a user-defined
own code function for each cell with:
ocf(omap.cells, omap.phyx, omap.phyy, p, this.lut)
namely, the old state map, its X and Y dimensions, the current
cell's index within the map, and the lookup table for the rule
(which the own code function may use or not, at its discretion).
The own code function return the new state for the cell, which
the evaluator stores into the new map. Wrap-around cells are
set before the own code evaluator is invoked depending upon the
world type (12 = open, 13 = closed).
Made the first cut at a more general implementation of own code
evaluators. If you set the world type to 12 or 13,
oneGeneration() in casim.js will call the rule.owncode()
evaluator described above with a function whose name is looked
up in the window[] hash from the name specified in the rule's
ocodereq. If no request was made by the rule or no such
function is defined, and alert is issued and evaluation is
halted. At the moment, own code functions are compiled in as
part of ruledefs.js, but eventually they will be able to be
supplied from a text box in the simulator page or embedded
within rule definitions.
Defined, as the first test of own code, a rug() rule in
ruledefs.js. It is based upon the pure definition of the
averaging rule, and uses no lookup table.
Implemented a lapinc() own code rule. This allows the Ruglap
sample rule to run.
2017 April 12
The Pond rule did not work because its requested initial random
seed was not being set by Map.setRuleRequests() due to an
incorrect test for the presence of a rule request. The absence
of a request is indicated by a starting bit number of -1, not
zero or less. A texture request which started in bit 0 would be
ignored. Fixed, and Pond now works correctly.
Implemented the evaluator for world type 3: 1D, ring world, with
one bit of state from eight neighbours: four to the left and
four to the right. The evaluator is Rule.og1c(). The evaluator
is coded very straightforwardly from the definition of the
lookup table index, and doesn't do all of the fancy footwork
with a bit remapping table the original assembly language
implementation did. Since code in the inner loop only gets
called once for each cell in the top row per generation, that
was a wretched exercise in premature optimisation on my
part--the follies of youth. Since examining four neighbours to
the right and left in a closed world requires us to explicitly
handle the end of line wrap-around, the evaluators for open and
ring world will be separate. The rule installation procedure
tells the map the world is always open, so we don't waste time
mirroring the edges when we're handling wrap ourselves. I
tested the evaluator with our two sample rules that use world
type 3: Axons and Parks.
Added evaluator for world type 2: 1D, open world, with one bit
of state from eight neighbours: four to the left and four to the
right. The evaluator is Rule.og1o(). This is very similar to
the og1c evaluator, except the state vector is surrounded by a
sea of constant zeroes. We don't have any sample rules which
use this world type, so I made a new shift1d.java rule to test
edge conditions.
Added evaluator for world type 5: 1D, ring world, with two bits
of state from each of four neighbours, in Rule.og2c(). Tested
with the two rules we have that use world type: Shortpi and
SoundCA.
Added evaluator for world type 4: 1D, open world, two bits of
state from each of four neighbours, in Rule.og2o(). Once again,
we have no rules which use this world type, so I tested it with
my shift1d.java rule.
Added evaluator for world type 9: ring world, with four bits of
state from two neighbours, in Rule.og4c(). Tested with the
Aurora rule, which is the only one of our samples which uses
this world type.
Added evaluator for world type 8: 1D, open world, four bits of
state from each of two neighbours, in Rule.og4o(). Once again,
we have no rules which use this world type, so I tested it with
my shift1d.java rule.
2017 April 13
Added the ability to load a rule from a URL as well as from a
local file. At the moment, the URL must be a fully qualified
address, and is intended just for testing. This is a proof of
concept for loading standard sample rules from URLs and loading
the patterns and palettes they request from URLs on the server.
Implemented a:
/files/me/webdev/cellab_2017/Tools/awsync
script to put the development build into production in the
private area of the server. This is required for testing loads
from URLs, as they only work when the parent page is loaded from
a HTTP server and it is referencing URLs on the same server.
Added the ability to load a pattern from a URL. Patterns are
loaded from a "patterns" subdirectory in the directory where the
simulator is installed.
Added pattern loading from a URL. Patterns are loaded from a
"patterns" subdirectory.
Implemented automatic loading of pattern and palette requested
by a rule. These are loaded using the URL mechanism, and must
be present in the Web tree library. Since we cannot load files
from the user's machine except those explicitly selected by a
file dialogue, there is no way to load local files specified by
a rule. Some of our legacy rule files are sloppy about the case
of characters in pattern and palette file name requests. To
avoid having to remake all of the rules (at least for now), I
force the name of requested files to lower case before loading
as a URL.
Implemented the Langton own code evaluator in ruledefs.js as
langton(). It provides three bits of state for each von Neumann
neighbour and four bits of state from the current cell. Due to
the way the original lookup table was structured, the state is
shifted one bit to the left in the cells (this made the assembly
language own code run faster), so in order to be compatible with
the existing rule, pattern, and palette files, this bit order is
maintained in the evaluator, so it should not be used as a
general evaluator for this kind of neighbourhood. If such an
evaluator is eventually needed, it should be provided as a
full-fledged world type with open and closed variants.
If the user specified a non-existent URL for a pattern file, the
pattern load would blunder on and try to decode garbage in the
result array. I added a check of the HTTP return status, decode
the pattern only if it is 200, and issue an alert in case of
error.
Added the HTTP return status check when loading a palette from a
URL.
Added the HTTP return status check when loading a rule from a URL.
Added a "Speed:" range control which allows varying the
animation step interval from 5 to 500 milliseconds.
Implemented NLUKY algorithmic rule specification in rule.js.
The function is called with five arguments giving N, L, U, K, Y,
not a composite code number as before. At the moment, until I
get the algorithmic rule specification dialogue done, I'm
testing it with a kludge in the rule URL specification which
tests for a rule name of
nluky N L U K Y
and invokes the generator. Specifying an NLUKY rule sets the
world type to 1 (2D closed). Tested with the NLUKY
specifications for Brain, Faders, Life, and RainZha.
Implemented totalistic algorithmic rule specification in rule.js
in function totalistic(), which is called with the totalistic code
and a Boolean indicating whether history is to be kept. Added
a kludge where this can be invoked with a:
total N H
in rule URL specification, where N is the totalistic code and H
is 1 for history and 0 for no history. Tested with 976, the
code for Vote. Specifying a totalistic rule sets the world type
to 1.
2017 April 14
Implemented random rule specification in rule.js in randrule(),
which takes the zero density of the semitotalistic 8 neighbour
lookup table as its argument. This can be invoked with a
specification of:
random D
in the rule URL specification, with D as the density (0-100).
Added <select> items for the standard rules, patterns, and
palettes to the right of the URL text boxes. These lists are
prepared by a Perl Tools/crunk.pl program from the contents of
the respective directories and manually pasted into index.html.
I may automate this, but as the standard files aren't changing
often, it's probably not worth the bother. Selecting an item
just plugs its name into the text box; you still have to press
the Load button to load it.
Added code so that when a pattern and/or palette are loaded due
to a request of a rule, the name is displayed in the
corresponding URL text box.
Added the semi8 own code evaluator for the Rug rule. This
evaluator uses a lookup table, and I haven't yet figured out how
to remap indices in the table to handle the bit rotation for an
own code rule, so at the moment I just commented out the code
which includes the state of the current cell in the index.
Added the semi8 own code evaluator for the Rugf rule. As with
semi8 above, I commented out the inclusion of the current cell's
state in the lookup table index.
Implemented user-specified own code (to be renamed "evaluator
functions"). A textarea allows the user to paste and edit the
function, which is just defined as code, which is logically
wrapped with the lines:
function(cells, phyx, phyy, p, lut) = {
};
and compiled into a function named ownCode when the "Compile"
button is pressed. If the compilation fails, an alert is issued
and ownCode will remain undefined. If the user loads a rule
which specifies world types 12 or 13 and sets the own code
request for the rule to the null string, the user ownCode
function will be used. (If no such function is defined, an
alert will be issued). It is the job of the evaluator function
to update the cells in byte vector cells, with dimension phyx *
phyy, of the cell with position p in the array, optionally using
the lookup table lut. Open/closed world handling and swapping
of maps is handled automatically before the function is called.
The function returns the new value of the cell. The author of
the evaluator function must know how to use offsets of phyx to
address neighbour cells; this will be explained in the
documentation.
Added a new owncode.jc rule, defined in owncode.java, which
specifies world type 12 and null string own code to invoke user
own code. This won't be necessary once we can set the world
type from the user interface.
Added a new owncode.js file, which simply contains sample own
code definitions which can be pasted into the Evaluator function
box. This file is not included in the Web page.
2017 April 15
Added an algorithmic rule generator for 1D, two neighbour rules
specified by a "Wolfram code", as in
http://mathworld.wolfram.com/ElementaryCellularAutomaton.html.
The generator is called as Rule.wolfram(code), where code is the
rule number from 0 to 255, composed of bits which give the new
state when the code number is shifted by the three bit number
composed of the left, current, and right cells. Specifying a
Wolfram rule sets the world type to 3 (1D, ring, 8 neighbours),
but only the two closest neighbours are used. For the moment,
you specify these rules with:
wolfram C
in the Rule URL box, with C as the rule number.
Added a new standard pattern, onebit.jcp, which is just a single
one bit at the centre of the top line of the map, intended to be
used with Wolfram code rules. This pattern is defined as a
compressed ASCII file.
In Map.paint() we were allocating a new pixel array every time
we updated the screen. This created a lot of clutter, as
garbage collection would have to be invoked to get rid of these
large arrays. I changed the Map constructor to allocate one
static pixel array, shared by all maps, and used within paint()
when called to display a map. I was hoping this might reduce
the pauses when running in Firefox, which sure looked like
garbage collection hiccups, but if it did the effect is
marginal.
Pressing the "Load" button on the rule, map, or pattern URL
lines when no pattern had been entered in the text box or
standard pattern selected from the drop-down list resulted in
the code blundering into the decoder with garbage data. I check
for a void selection and issue an alert inviting the user to
select something before trying to load it.
Trying to load a rule, pattern, or palette file when no file has
been selected from the Choose File button caused a warning on
the error console due to some ill-considered code which tried to
disable the Load button in such a circumstance. The code was
not only dumb, but also wrong, with a missing "this.". I
removed it.
Implemented on-the-fly rule definition in JavaScript. There is
a new RuleMaker object, defined in rulemaker.c, which generates
rules from code specified in a <textarea> which is passed to it
when the object is created. The RuleMaker.generateRule() method
compiles this code into a rule lookup table in the following
manner. Let us assume the code pasted into the text box is as
follows:
rule.worldtype = 1; // 2D torus world
rule.ruleName = "brain";
function brain(oldstate, nw, n , ne,
w, self, e,
sw, s , se) {
var count = nw + n + ne + w + self + e + sw + s + se;
if (oldstate == 2) { // If in refractory state...
return 0; // ...become ready.
}
if (oldstate == 1) { // If firing...
return 2; // ...go to refractory state.
}
return (count == 2) ? 1 : 0; /* If ready, fire if precisely
two neighbours are firing. */
}
The code is parsed into the following components:
header: Everything before the function declaration
funcname: User-supplied function name
arglist: List of arguments (if any) in parentheses
after function name
funcbody: Function body: everything after the argument list
The header is executed with eval(), which allows it it set rule
requests by making assignments to the various fields in the rule
object. All requests are initialised to defaults by calling
rule.initreq() before the header is executed. The rule's header
must set rule.worldtype to specify the world type (which is
needed by the rule generator to determine the neighbourhood
passed to the rule function); all other rule request parameters
retain their defaults if not set.
The arglist and funcbody are transformed to be suitable for
submission to an eval() function which executes a "new
Function()" call, compiling the rule function into an anonymous
function invoked via this.rulefunc. If there is an error
anywhere in this process, an alert is issued and nothing further
is done.
Now, it's just a matter of invoking the rule function for each
cell in the lookup table, passing it arguments which represent
the neighbourhood as defined by the selected rule.worldtype
type. As arguments and indices are stored directly into the
lookup table without the bit shifting of the legacy assembly
language code, this is a straightforward process. At the end,
the rule.lut[] is ready to use to evaluate the rule.
2017 April 16
Ported the following 2D 8 neighbour rules to JavaScript in ruledefs/
balloons.js
bob.js
border.js
brailife.js
dendrite.js
dentim.js
ecolibra.js
ex_life.js
faders.js
flick.js
fractal.js
fredmem.js
gyre.js
hglass.js
hppgas.js
life.js
perfumet.js
perfumex.js
pond.js
rainzha.js
ranch.js
revecoli.js
soot.js
sublime.js
timetun.js
vote.js
votedna.js
xtc.js
zhabo.js
zhabof.js
zhaboff.js
Rule mode requests made in JavaScript rule definitions were not
being executed. I moved the rule request implementation code in
rule.js from the rule loading code into a separate
Rule.processRuleRequests() function and added a call to it after
a JavaScript rule has been compiled.
If the user didn't set rule.ruleName in the header of a rule
definition, set the rule name to the name of the rule function.
Added a Clear button to clear the Rule program textarea.
Nested functions in rule definition functions failed because the
match used by rulemaker.js to locate the function in the rule
definition was "greedy" and sucked up everything prior to the
last function in the text, which would be the nested function
and not the rule function. I added a question mark to the
repetition before "function" so that it will be non-greedy and
match the first occurrence of "function" in the text.
Implemented world types 10 and 11 (2D open averaging rules) in
rulemaker.js. The following rules which use these world types
have been ported:
heat.js
heat4.js
heatwave.js
hodge.js
Note that the interface to the rule function is different than
in Java. In Java, the cell's old state was passed as an
argument to the function, but the sum of the neighbours was
passed as a hidden argument in SUM_8 or SUM_4, which was
inherited by the rule function. Here, the rule function is
called as:
myrule(oldstate, sum)
with sum the sum of the neighbours.
Added a Clear button for the evaluator function definition textarea.
2017 April 17
Added code to rulemaker.js to handle world types 12 and 13: own
code 2D rules with open and torus topology, respectively.
Added rule definitions for own code rules using world types 12
and 13:
langton.js
rug.js
ruglap.js
Added support for world types 2 and 3 (one dimensional, with 8
neighbours of one bit of state) in rulemaker.js. The
neighbourhood is considered as:
l4 l3 l2 l1 self r1 r2 r3 r4
and the rule function is called as:
rulefunc(oldstate, l4, l3, l2, l1, self, r1, r2, r3, r4)
where oldstate is the full 8 bit state of the current cell and
self is its low-order bit. Ported the following rules which use
this 1D neighbourhood:
axons.js
parks.js
If a rule requested a nonexistent palette, the alert which appeared
said "Pattern x not found.", not "Palette...". Fixed.
Fixed typo in the Java rule parks.java. An error message (which
never could appear unless the user edited the rule and changed
the parameters at the top to erroneous values) used a "<"
operator where "<<" was intended. I fixed it in:
pdcalab/ca/sample/java/parks.java
Somehow, the code that tests for world types 4 and 5 in
Rule.loadRule in rule.js had gotten lost. I put it back.
Implemented support for world types 4 and 5 (one dimensional,
with 4 neighbours of two bits each of state) in rulemaker.js.
The neighbourhood is:
l2 l1 self r1 r2
and the rule function is called as:
rulefunc(oldstate, l2, l1, self, r1, r2)
where oldstate is the full 8 bit state of the current cell and
self is its low-order bit. Ported the following rules which use
this 1D neighbourhood:
shortpi.js
soundca.js
Added world types 8 and 9 (one dimensional, with 4 neighbours of
four bits of state) in rulemaker.js. The neighbourhood is:
l self r
and the rule function is called as:
rulefunc(oldstate, l, self, r)
where oldstate is the full 8 bit state of the current cell and
self is its low-order bit. Ported the following rule which uses
this 1D neighbourhood:
aurora.js
Implemented the vonn3 own code evaluator in ruledefs.js and
ported the vonpar.js rule which uses it. The "guts" of the own
code function also work as a user-supplied evaluator function.
The vonn3 evaluator assembled three bits of state from the four
von Neumann neighbours and four from the current cell into a
lookup table index of CCCCNNNW WWEEESSS.
Rewrote how own code (user evaluators) are compiled by
compileOwnCode() in casim.js. Previously, the contents of the
evaluator box contained just the body of the evaluator function,
which was required to use the argument names of the standard
evaluators. I modified this to use the same logic rule program
generation, where the function is picked apart by a regular
expression and then transformed into the creation of an
anonymous function with the user's specified argument names,
which is then passed to eval() to create the ownCode function.
This allows user evaluators to have the identical syntax as
those built in as functions in ruledefs.js.
Created a new "evaluators" subdirectory to hold user evaluator
functions, all with a .js extension. I created copies of the
following evaluators defined in ruledefs.js as files in this
directory as follows. These evaluators remain in ruledefs.js,
and probably will stay there, as it's less fussy to just invoke
them than load, compile, and install an evaluator file, but the
definitions in the evaluators directory will serve as
documentation for those who use them and will provide a starting
point for user who wish to create new evaluators similar to
those provided there.
langton.js
lapinc.js
rug.js
semi4.js
semi8.js
vonn3.js
Added the columbia.jcp pattern file to the standard patterns
directory and the list of standard patterns in index.html.
ASCII palette files (formats 2 and 3) did not work.
Palette.loadPalette() in palette.js incorrectly parsed the
format from the first line, failing to allow comments following
the format number, and then incorrectly extracted the VGA RGB
values from the following lines. Fixed.
Added two new standard images and their colour palettes. These
are shaded images intended as starting points for image
processing rules.
steapot
x29
Implemented an evaluators/runny.js evaluator to demonstrate
insane user evaluators which do things like work on the entire
map at a time. It makes nonzero cells of any map "run" downward
until they collect at the bottom with zero cells propagating to
the top.
2017 April 18
Added a user evaluator, evaluators/meltdown.js, which does the
bubble sort of the original meltdown.asm. It uses the same
dirty tricks as runny.js to update the old map in place, and
refers readers to the comments in that file for details.
Added a user evaluator, evaluators/laplace.js, for the Laplace
averaging rule without the increment done by lapinc.c.
Deleted the ailogo.jcp and biglogo.jcp patterns. They weren't
used in any of the standard rules.
Implemented a evaluators/maskmap.js evaluator for quick and
dirty surgery on patterns. It lets you apply a specified AND
and OR mask to every cell in a map. Just edit the values in the
user evaluator box before pressing "Step".
Added a diagnostic feature I've been missing for some time.
There is now a function in casim.js, dumpArrayHex(array, start,
length), which dumps the specified range of the array in
hexadecimal to a textarea which magically appears on the main
page when the function is called. The user can copy from the
textarea and paste in an editor to save the dump. The dump is
compatible with an uncompressed ASCII pattern file. A Dump
button in the pattern section dumps the current pattern in this
format, using a Map.dump() method.
Loading of uncompressed ASCII pattern files lost the first byte
of the pattern, reported the wrong length in the file, and
shifted the entire pattern left one column. This was happening
because the format character, sucked up to determine the file
format, is actually a data character for uncompressed maps,
which are just pure hex data. I backed up the pointer to keep
this from happening.
Replaced the Autodesk logo in the dentim.jcp pattern with an
ant. The utility used for this, Tools/ImageHacks/buildjcp.pl,
has routines for reading .jcp and .pbm files and writing
uncompressed ASCII .jcp files.
Ported the C++ code to read and write pattern files from the
original JC program into a program called
Tools/ImageHacks/compmap.cpp. This is presently a purpose-built
program for compressing the new dentim.jcp file, but it can be
used as the foundation for assorted manipulations on patterns.
It reads and writes all pattern file formats.
Compressed the dentim.jcp file and installed in the standard
patterns directory.
2017 April 19
Some old rules generated in Pascal contain RSRSEED instructions
(used to specify an initial random seed) with starting bit and
bit count values of 255. This was due to a signed/unsigned
problem. I added code to Rule.loadRule in rule.js to detect
this and set these values to the correct -1 for no initial
random seed specified.
I think that after somewhat of a struggle, I've got the Wator
rule running. This rule uses an evaluator called "swap", which
does a really dirty trick of swapping cells in both the old and
new maps as it runs. It was originally written to run as a
standard own code rule which updated a whole line at a time, and
had to be re-cast to update a single cell per call. We don't
provide the evaluator the new map, but an evaluator can get at
it with:
map[(omap + 1) & 1].cells
assuming nothing changes outside. (If other evaluators need
this, I may pass it as an argument, but it's such a dirty trick,
I'm not motivated to encourage it.) I have rewritten the
original Pascal rule definition as a ruledefs/wator.js file,
which produces an identical lookup table. The original swap.asm
own code has been rewritten as evaluators/randswap.js ("swap"
was too generic a name for an evaluator which will be promoted
to built-in in ruledefs.js). The original own code maintained
its own pseudorandom generator using Wolfram rule 30. I
replaced this with simply calling the JavaScript Math.random()
generator, which seems to be sufficiently fast. We allocate and
discard an array of indices of neighbours every time we're
called, but once again, in the age of Extravagant Computing, you
can't see any time penalty for doing so.
Promoted the randswap evaluator into ruledefs.js, so it can be
invoked without loading a user evaluator. Updated the
ruledefs/wator.js rule definition to request the Billbord
pattern and the Wator palette. We still don't have a
pre-compiled wator.jc rule since we can't save rules and the
original contains embedded patterns and palettes we don't
support. Until we implement saving rules defined in JavaScript
or make a nicer way to load and compile them, you can just copy
and paste the rule definition into the Rule program box and
generate it.
Created a Java rule definition of Wator, wator.java. This
allows making a rule to be included in the precompiled rules
directory and as a standard in index.html which specifies the
correct evaluator and pattern. We also need it in order to
provide Java definitions of all the standard rules, since we're
only supporting Java for external rule definitions from now on.
Ported Griffeath's cyclic appetite rule. This was originally
implemented in a collection of different Pascal programs, each
with a different number of states. I wrote a generic rule
program ruledefs/griff.js, and its evaluator,
evaluators/randnabe.js, which creates a lookup table index from
the current cell and a randomly chosen neighbour. (This
evaluator was originally named naber.js; once again I renamed it
to be less generic.) The evaluator function is also integrated
into ruledefs.js for ease of use. The griff.js rule loads a
pattern patterns/griff.jcp (which for some reason used to be
called earth.jcp) and the autocad.jcc palette. To change the
number of states, simply change the value of N in the rule
definition and re-generate the rule.
Added support for loading embedded patterns and palettes within
rule files. These so-called "experiment" files were largely
created for the demo version of the original program, but since
we have a number of them, it's handy not to have to break them
up into their components. It's only a few lines of code to
support this in rule.js, map.js, and palette.js.
Since we have these dirty trick evaluators that look at the new
map as it is being generated, I modified Rule.owncode() in
rule.js to pass an additional argument to the evaluator that
allows it access to the new map. If an evaluator wants to do
this, it can simply add a new argument after the lookup table
and address it with cell indices based upon the p (current cell)
argument as for the cells argument which addresses the old map.
It's ugly to do this, but it's less ugly when an evaluator
writes ncells[p] rather than map[(omap + 1) & 1].cells[p].
Implemented a custom evaluator for Turmites: turmite() in
ruledefs.js and evaluators/turmite.js. This is another one of
those dirty trick evaluators that look at manipulate the new map
as it is being generated, and it uses the ncells argument
described in the previous paragraph to do so.
Added a new patterns/turmite.jcp and palettes/turmite.jcc to
illustrate three kinds of Turmites running on rectangular
blocks. These were the pattern and palette embedded in the
vante4.jc experiment from the Rules Update release of September
1989.
Implemented two Turmite rule definitions: ruledefs/turmite.js
and ruledefs/turmite4.js. These are translations of the Pascal
programs vant.pas and vant4.pas from the Rules Update and use
the turmite evaluator. They illustrate different kinds of
Turmites; others are possible, but these two probably suffice to
get the interested user started on making their own.
2017 April 20
Deleted scripts/owncode.js. It was a repository of stale code
that doesn't work. It has been superseded by the evaluators
directory.
Modified the randswap() evaluator in ruledefs.js and
evaluators/randswap.js to use the new ncells argument to access
the new map. This is the evaluator used by the Wator rule.
Let's face it: we're going to continue to support external rule
compilation in Java, since it's so much easier when preparing
demos than defining rules in JavaScript where we can't save them
in compiled form except by jumping through flaming hoops. I
created a "rules_java" subdirectory and imported the java
subdirectory in which I've been building rules. There is a lot
of cruft in this directory, which I will now start to
abstergify. All of the legacy rule definitions are marked
read-only. I will make these read/write only if and when they
are modified for some reason.
Deleted all of the obvious trash in the rules_java directory,
including all of the compiled .class files and .jc files.
Everything needed will be recompiled with current Java
compilers. There is a Makefile which is terribly out of date,
but might prove useful as a base for something more
comprehensive in the future. Started to use setbase to manage
changes to ancient Java rule programs which will be kept in
read-only mode until change is required.
Recompiling ruledefs.java squawked about a reference to a
deprecated String.getBytes(0) function call. I replaced it with
one acceptable to the priesthood and tested it by rebuilding the
wator.java rule. It seems to be OK.
Made Java versions of the Turmite4 and Turmite rules in rules_java:
turmite4.java turmite.java.
Installed the turmite4.jc rule in the rules directory and added
a reference to it in index.html so it can be easily loaded. The
dropdown list item is "Turmites", but it actually loads
turmite4.jc. There is presently no item to load turmite.jc, but
you can load it if you wish by typing in the name. I'm not sure
how many of these we want to provide as defaults since there are
so many.
Ported Dan Drake's 1990 Mite rule, a predator-prey model which
develops interesting behaviour started from a state with just a
small square of prey and a dot of predators in the middle. The
rule, pattern, and palette are all named "mite". I added each
to the standard menu in index.html. A JavaScript rule
definition is in ruledefs/mite.js and the Java definition is in
rules_java/mite.java. I converted the palette file, which is in
ASCII format, from DOS to Unix end of line convention. Added
"Mite" to the standard rule, pattern, and palette drop down
lists.
Cleaned up the rules_java/Makefile into something resembling a
first draft. I updated the list of classes to be current and in
alphabetic order, removed the obsolete stuff for generating the
CGI programs for the Java rule compilation server, and got rid
of the explicit -classpath, which shouldn't be necessary with a
modern, properly-installed JDK. Recompiled all of the rules with
no errors. The "all" target now makes all of the rule programs
and their corresponding .jc files, and the "clean" target
deletes both .class and .jc files.
Four of the standard pattern files were in ASCII format with DOS
CR/LF line terminators. This worked OK, but was sloppy, so I
converted them to Unix format with dos2unix. I may convert them
to binary eventually, but in these days the difference in size
hardly matters. Since I no longer have a running copy of the
DOS or Windows versions, I'd have to write a program to convert
these palette files to binary.
Moved the caweb/work directory to Tools/vgapal. Its only
contents were the utilities for making the default VGA palette.
Added the ability to load rule programs from either files or
URLs, with a list of standard rules as is provided for
precompiled rules (.jc files). After a rule is loaded, with its
source placed in the rule program text box, it will be
automatically generated so it's ready to run (assuming there
were no errors executing the rule program). This is a big step
toward making rule programs first class citizens equal to
precompiled rules, and possibly deemphasising precompiled rules
in the user interface. A new rule program file and URL selector
boxes were added in the rule program section of the page, with
load buttons which load and generate the rule. The only time
the user needs to use the Generate button is after making a
change to the rule program in the text box. The loading of rule
programs is handled by two new RuleMaker methods in
rulemaker.js: loadprogfile() and loadprogurl().
2017 April 21
Deleted evaluators/runny.js_OBSOLETE. It was, well, just look
at the name.
Implemented loading user evaluators from either files or URLs,
with a drop down list of standard evaluators. Like rule
programs, loading an evaluator causes it to be immediately
compiled.
When a rule requests a user evaluator, its name is placed in the
URL field of the user evaluator section. Since a rule-requested
evaluator is built-in, there's no need to load the evaluator
file, but the name indicates it's in effect and if the user
wishes to view the source of the evaluator, the Load button will
display it.
Commented out the mouse click handler for the canvas in casim.js
until we find a need for it.
Added a very obscure feature which can be handy for people
developing user evaluators. There is now an "Override" check
box above the evaluator program text box. If set, the program
in the text box, if compiled successfully, will override any
evaluator specified by the current rule. This will only occur
if the rule requests a user evaluator: if it uses one of the
world types with a standard evaluator, it will have no effect.
This allows testing variant evaluators with existing rules
without the need to recompile the rule with a blank evaluator
request. I'm aware that few people may perceive a need for this,
but I've been longing for it for the last week as I try to tweak
evaluators. It allows neat things like running a rule with a
custom evaluator and then swapping the evaluator to "meltdown"
to make a histogram of states per column.
The ruledefs/timetun.js rule definition did not specify the
timetun pattern and default palette as the timetun.jc file did;
fixed. The rules_java/timetun.java file also did not contain
these requests; fixed. All of the legacy rules need to be
audited for such discrepancies between the .jc files and the
declarations in the rules_java directory.
Increased the width of the rule program and user evaluator
textareas to 80 columns. This should avoid ugly wrapping if the
programs are properly formatted.
Added support for header code in user evaluators, as already
implemented for rule programs. User evaluators may need to
define constant or static data which persists across executions
of the evaluator for individual cells. Header code, which is
executed only when the evaluator is compiled, allows this, in
conjunction with a new rule.evaluator object in which they can
stuff their private data. The contents of rule.evaluator
persists over the life of an evaluator, but is purged when a new
evaluator is compiled or loaded by a rule. For example, a user
evaluator may define a constant lookup table in its header or
declare static storage used to operate a pseudorandom number
generator which is invoked on each call of the evaluator.
Modified the evaluators/randswap.js evaluator to keep its
constant "nindex" array in rule.evaluator, declared in the
header.
Updated the evaluators/turmite.js to use a header declaration
for its nindex array.
Updated evaluators/randnabe.js to use a header declaration for
its nindex array.
2017 April 22
Implemented the framework for pop-up dialogue boxes to reduce
the runaway clutter of the user interface and eventually roll it
back to something people can comprehend. Dialogue boxes are
defined as Z-plane overlays, defined in the main index.html
file, but originally given a display value of "none". Their
properties are defined in the new styles/dialogue.css, and
managed by the code in scripts/dialogue.js. All dialogue
management code is defined in the Dialogue object, which is
instantiated in the cawin.js variable "dialogue". A dialogue is
opened by calling dialogue.open("id") where id is the id of its
enclosing <div>, and closed with dialogue.close("id"). Note
that each dialogue content <div> should specify its width in a
style= attribute. If it fails to do so, the width will default
to 100%, which may be infelicitous.
To act as a pathfinder and also provide a needful thing, I
defined an "Algorithmic Rule Specification" dialogue which is
activated by a new "Algorithmic" button on the Rule line, after
the Load button for a Rule file. This allows specifying the
parameters for one-bit totalistic, NLUKY, Random, and Elementary
1D (Wolfram code) rules, which are generated when the "Apply"
button is pressed. All parameters are checked to be valid
non-negative numbers and within range, and alerts issued in case
of error. The parameter checking is done by functions within
the Dialogue object which are available to all dialogues to be
defined.
The style definitions for dialogues can be improved: for
example, to distinguish the title from the contents of the box,
but that's a refinement which can be deferred until the
functionality is in place.
Added a palette dump feature. A new dump button beneath the
palette URL load line dumps the palette to the dump box (also
used by the pattern dump facility) in ASCII VGA format (2). The
internal RGB range of 0-255 is rescaled to 0-63 for
compatibility with the original VGA palettes. One day I should
add a new palette format which allows 0-255 RGB values and
bypasses all the rescaling.
Moved the "Swap" button (which swaps planes 0 and 1 of the map)
up to the line after the pattern URL, where it better belongs,
being a map operation.
Created a new standard palette, grey.jcc, which provides a
smooth grey scale gradient from states 0 to 255, scaled, of
course, to the VGA range of 0 to 63 (which will be scaled back
when it's loaded...sigh).
Created a new version of Bob with a smooth 128 level grey scale
image and a grey scale ramp palette with two ramps from black to
white in states 0-127 and 128-255:
bob128.jcp
grey128.jcp
I have not yet modified the Bob rule to use this pattern and
palette. These files are built in the Tools/bob directory.
Cleaned up some validator squawks in index.html. It doesn't
like an <option> tag with no content, but it's fine with
as the content.
Added the Fourmilab logo to the top right of the page. There's
a blank placeholder for a CelLab logo once I decide what it'll
be. (I'm leaning toward a clip of Hodge, but maybe something
better will come to mind.)
Implemented the monster "Bit Plane Editor" dialogue. This works
just as it did in the Windows version, and allows you to do
logical operations between bit planes of the map, between planes
in the map and an auxiliary buffer (which is automatically
allocated the first time you use it, and persists across
invocations of the dialogue), and perform various initialisation
operations on planes of the map. Re-validated index.html after
adding all of the HTML for the new dialogue.
Went ahead and added a clip of Hodge as an icon at the top left
of the page, linked to /cellab/ on Fourmilab. Changed the icon
at the right from the ancient .gif to the current .png (no
difference in appearance).
2017 April 23
Setting the identity rule with Rule.identity() didn't set the
worldtype type to 1. Fixed.
Started work on the Rule Modes dialogue. This combines the
World type items in the menu of the Windows version with its Bit
Plane Texture dialogue, and will allow setting the rule requests
on the fly. At the moment, I have a first draft of showing the
rule's world type and texture requests in a primate-readable
form, but I haven't extensively tested this (particularly with
the more obscure 1D rule types). Still to be done is encoding
all of this information to the cryptic specifications in the
Rule object when the user clicks "Apply", and the snowdrifts of
error checking code which will be required to detect things such
as non-contiguous settings of texture bits. or random input
overlapping static textures.
Finished the Rule Modes dialogue. It allows you set the world
type without having to know about the numeric codes, and specify
textures as bitmaps with check boxes. Bit masks are check for
non-contiguous bits and for infelicitous overlaps.
The kludge specification of algorithmic rules by text in the
rule URL box has been removed; it was made obsolete by the
Algorithmic Rule Specification dialogue.
Created a new image and colour palette: fullearth.jcp
fullearth.jcc from the Apollo 17 full Earth picture. The image
is developed in Tools/fullearth. I haven't included it in the
standard image and palette directories so far. This image works
well with the following
rules and evaluators:
clowneat.jc randswap.js
clowneat.jc randnabe.js
owncode.jc meltdown.js
owncode.jc runny.js
Set Override for the evaluator to override any evaluator
specified in the rule definition.
Added the framework to handle keyboard events when the mouse is
within the canvas. Naturally, in JavaScript, this is not
straightforward. Rather that registering for keyboard events for
the canvas or its enclosing the division, which doesn't work, we
have to grab keyboard events document-wide, switching the grab
on and off when the mouse enters or leaves the div. This is
handled by mouseInCanvas() in casim.js, which registers
canvasKeyPress() as the keyboard event handler when the mouse is
within the canvas.
Changing the world from open to closed and back in the Rule
Modes dialogue did not change the setting of toroidal in the
maps. Fixed.
2017 April 24
Implemented arrow keys to scroll the map. You can do this while
the rule is running. The arrow keys scroll the map one cell, or
ten cells if the Shift key is down when the arrow key is
pressed. The mouse must be within the display of the map for
the arrow keys to scroll it. Whether the map scrolls with wrap
or by filling cells with zero depends upon the wrap mode set for
the rule, which you can change with the Rule Modes dialogue.
Added the ability to preload a rule by specifying a URL like:
http://www.fourmilab.ch/whatever/?rule=zonk
which will load the rule "zonk" from those stored in our
directory tree along with any pattern, palette, and evaluator it
requests. This will allow the manual to cite examples which run
simply by clicking on their links. I may eventually extend this
to allow specifying a pattern, palette, and evaluator as well,
possibly overriding those requested by the rule, but this is not
that day.
Added the ability to preload patterns and palettes with a
specification like:
http://www.fourmilab.ch/whatever/?rule=zonk&pattern=bonk&palette=honk
You can abbreviate "pattern" to "pat" and "palette" to "pal".
Due to a race condition in the asynchronous loading of rules,
patterns, and palettes from URLs, a pattern and/or palette
request in a rule may override those made in the URL. I need to
fix this.
Fixed the race condition with URL loads of patterns and palettes
overriding requests in rules. The ugliness is in
Rule.processRuleRequests() in rule.js and documented at some
length in a comment there.
The implementation of scroll keys broke keyboard input
everywhere else on the page. The onmouseover to capture the
keyboard when the mouse is within the canvas was placed on a
<div> which I thought enclosed just the canvas but actually
included the entire page contents. I moved the onmouseover to
the canvas tag and it got better.
Implemented a new evaluator: evaluators/randgas.js. This does
random diffusion of cells, updating a percent of cells specified
by rule.evaluator.percent in the header on each generation.
Cells are swapped with a randomly selected neighbour. No lookup
table is used, and the values of cells are never changed apart
from swapping, so it can be used on arbitrary image patterns.
It looks particularly nice with the fullearth pattern and
palette, which I've installed in the standard directories. You
can run it with the generic owncode.jc rule.
Modified rules_java/owncode.java to request world type 13 (own
code, torus). Its choice of 12 was causing a lot of confusion
when people don't expect an open world. If you prefer an open
world, you can always select it from the Rule Modes dialogue
after loading the rule.
Ported the dummy owncode.java rule to ruledefs/owncode.js. This
is for completeness and documentation. Users shouldn't have to
look at or compile Java rule definitions unless they want to.
Added the Fullearth pattern and palette to the drop down lists
in index.html, and the Randgas palette to the Evaluator function
list.
2017 April 25
Implemented the first cut of histogram display. This is quite
different from what was implemented in the earlier versions and
will require some shakedown. You select histogram display with
a Histogram checkbox at the bottom right of the map canvas. A
Background checkbox controls whether background cells are
included, as will be described later. The check box calls
Map.setHisto() in map.js, which computes the tables used to
display the histogram and obtains the required memory, if not
previously allocated.
The updateDisplay() function in casim.js, if a histogram is
requested, calls Map.paintHisto() instead of Map.paint(). This
function creates a histogram, consolidates cells, and builds a
histogram image which is blasted to the display on each
generation. The histogram is based upon the colour of cells
displayed in the map: cells with different states which map to
the same colour are consolidated into a bar with that colour.
The Background checkbox, which is not checked by default,
controls two distinct things. First of all, unless checked,
cells whose state maps to black will not be included in the
histogram. Second, states which have no cell in them will not
be plotted. This usually does what you want with rules with
sparse state maps, but you can always turn it off if you don't
like the results. The histogram is automatically scaled so that
the most populated state will occupy 75% of the height of the
screen. If the change in population causes the most populated
state to overflow 100% or fall below 25%, the histogram will be
automatically rescaled. When background pixels are displayed,
pixels which would have been displayed in black are shown in
dark grey (#606060).
Added a Map.populationHistory(texture) function to map.js. It
computes a histogram of the map, removing texture from states
before counting them if the texture argument is true. The
history is returned in CSV format as pairs of state number and
count of cells in that state. This function shares histotab with
the histogram display and allocates it if required on the first
call.
Changed the width of the dump textarea to 80 characters to be
consistent with the rule and evaluator boxes.
Added a generation counter, myGeneration in casim.js. The
generation counter is zeroed whenever a new rule is loaded. I
will add a button to reset it when I decide where it belongs.
I'm not sure we can afford displaying a generation count in an
HTML element for every generation without slowing things down;
this will require an experiment.
Added population dump with the Ctrl+z key pressed within the
canvas. This keyboard shortcut is compatible with the DOS and
Windows versions, although a more elegant way will be provided
as an alternative. The population is dumped by
Map.appendPopHistory() in map.js, which is passed the dump
panel, textarea, the generation number, and the texture argument
to populationHistory() which is kept in
dialogue.pophist.texture, where the Population History dialogue
will eventually be able to set it. It appends a record in CSV
format with the generation number as the first item, followed by
the state and count pairs. The dump area is displayed if
currently hidden. The records are appended to whatever is in
the dump area; if the user has previously dumped something else,
it's up to them to clear the dump area before adding population
history records.
Added a generation counter display to the bottom left of the
canvas. Updating it doesn't seem to slow down update speed
observably. Gimmick: clicking on the label to the left of the
generation display will reset the generation count to zero. You
can also edit the value in the generation number field to set it
to anything you like.
Selecting an algorithmic rule properly reset the generation
counter to zero but failed to update the displayed number
because it didn't call updateDisplay() (which there was no
reason to do before). Fixed.
Added a Population Census dialogue in dialogue.js. The dialogue
allows you to configure either an automatic dump every specified
number of generations or manually with Ctrl+z or a new "Record"
button (I made something that looks like a VCR record button
from a Unicode filled circle character styled to be red). The
"Census" button below the map pops up the configuration
dialogue. The manual dump button is cryptic because I'm running
out of room on the line below the map for buttons.
Added a "Select" button above the Dump textarea. This makes it a
little easier to copy the contents to another application. I'd
like to be able to copy to the clipboard, but JavaScript security
restrictions prevent this on most platforms.
2017 April 26
Added the "randgas" user evaluator to ruledefs.js. This will
allow making "Earthgas" a standard rule to illustrate image
diffusion.
Added ruledefs/earthgas.js as a rule definition. It requests
the fullearth pattern and palette and the randgas evaluator.
Added as a selection in the drop-down list for Rule program, but
not yet ported to Java or as a .jc file.
Changed the multiplier used to mix up the bits in the randgas()
evaluator for the second use of the value from Math.random() to
25523, a prime number.
Added a new evaluator, evaluators/gaswall.js, and its gaswall()
function to ruledefs.js. This is similar to randgas.js, but it
allows specification of a bit plane which, if set, will be treated
as an impermeable wall. I added a new ruledefs/perfumer.js
which invokes this evaluator along with the "perfume" pattern
and palette to run the random gas for comparison to the Perfumet/x
lattice gas rules. I haven't created a Java definition or .hc
file for perfumer as of yet, nor added Perfumer to the drop down
lists of standard rules and gaswall to the list of evaluators.
Added a new evaluator, evaluators/gasflow.js. This is similar
to gaswall.js, but creates flow by introducing a bias in the
direction of particle flow. There is a "nogo" array which
specifies directions particles are disinclined to move and a
rule.evaluator.flow value between 0 and 100 which controls the
strength of flow. If set to zero, particles will be free to
move in any direction; if 100, particles will never move in a
nogo direction. Note that if you set flow to 0, the evaluator
reduces to gaswall, and if you set both flow and wall to 0, it
reduces to randgas. When run with a closed world, it handles
wrap-around itself to enforce strict conservation of particles.
In an open world, of course, particles are lost off the edges.
Implemented a new utility, Tools/makejcp/makejcp.pl which makes
it easy to create simple patterns conforming to a palette mapped
to states. Create the palette first, assigning colours to the
states you'll use in the rule. The make a drawing of the
standard size with Gimp or another paint program. Export the
drawing as an ASCII PPM file, say mypat.ppm, and process with
your palette with:
perl makejcp.pl mypat mypal.jcc
The result will be an uncompressed ASCII mypat.jcc ready to load
into the simulator along with the palette. When you draw the
pattern, be sure to set the colour of each component to the RGB
values from the palette for the state, and don't forget to remap
the palette values from 0-63 to the 0-255 range used by paint
programs. Also, be sure to turn off antialias mode in the paint
program, lest you get intermediate colour pixels at the edges of
lines and filled objects which can't be found in the palette.
Made all of the drop-down boxes to select standard rules,
patterns, etc. immediately load the object when selected, rather
than making the user press the separate Load button. If other
people are baffled as often as I am after forgetting to press
Load, this will be a big improvement.
Promoted Earthgas to a full-fledged standard rule, with a Java
rule definition and a rules/earthgas.jc made by it. Added it
to the drop down list of Rule URLs in index.html.
2017 April 30
Added support for two new palette types. Type 5 is an ASCII
palette identical to type 2 (VGA palette) except that the RGB
values have a range of 0-255 instead of 0-63. Type 6 is a
binary palette in which the RGB values are bytes with values
from 0-255. In a type 6 palette the trick of hiding the CGA
colour in the top two bits of the red byte is not used. I
haven't yet tested type 6 palettes since I don't have any way to
make them. Type 5 works fine.
Modified the Palette.dump() method to write type 5 ASCII
palettes if its internal variable scalepal is set to false,
which is the default. Used this to test import of type 5
palettes.
Somehow I never got around to adding the zhabo.jcp pattern file
to the standard patterns directory or drop-down list. I think
we may have omitted it from the original DOS release because it
was so big (58 Kb). It's there now.
Updated ruledefs/zhabo.js and rules_java/zhabo.java to request
the zhabo.jcp pattern at start. There's no reason to make the
user wait an hour for it to develop. If you want to see the
pattern emerge, just override zhabo.jcp with a random pattern
before starting the simulation.
Ported the Spins rule from the original CA directory to
ruledefs/spins.js. This is spin-only Ising system from
Toffoli & Margolus section 17.3, page 190, and was originally
defined only in C. It has a corresponding spins.jcp pattern
file. This rule used the ancient "auxplane" mechanism from
the first version of CA, and had to be rewritten to use
the current vertical, horizontal, and temporal phase of
the 8 bit state version. (There is no way I am going to
carry the auxplane into the 21st century; it was obsolete
in 1989.) I think I've got it right, but I need to check
it against T&M, which I can't do right now since I'm on the
road. I'll wait until I'm sure it's right before porting
to Java and making a compiled rule. Installed the spins.jcp
file in the patterns directory. The rule requests the mask1.jcc
palette. Update (2017-05-12): Upon returning to Fourmilab, I
compared this rule's behaviour to T&M, and concluded it is
correct.
Modified Tools/fullearth/ppmtojcp.pl to create a type 5 colour
palette file (ASCII, 0-255 RGB). If you set $VGAcol inside the
program to 1, a type 2 palette will be created as before.
Remade the fullearth.jcc palette to be type 5 and installed in
palettes.
Further modified Tools/fullearth/ppmtojcp.pl to create binary
palette files (types 4 or 6) if $BINpal is set to 1. Made a
type 6 palette of fullearth.jcc to test loading this format
(it worked) and replaced palettes/fullearth.jcc with the binary
file.
2017 May 1
Ported the annealing driven by randomness rule, originally
sraneal.c, to ruledefs/sraneal.js. This is as given in Toffoli
& Margolus, sec. 8.3, p. 70, and performs annealing driven by
random input, which we obtain from 3 bits of random stimulus
used to produce a random input with a density of 1/8.
Qualitatively, it behaves much like the Vote rule, and
illustrates how similar results can be obtained by different
processes.
Ported Banks' 4 state computer, Toffoli & Margolus sec. 5.5, p.
42, to ruledefs/banks.js. This needs some pre-built patterns to
demonstrate the propagation of patterns along structures,
including around corners.
2017 May 2
Completed the first-cut implementation of shows. You can load a
show from either a local file or a URL on the server just as you
can load rules, patterns, etc. The show is placed in a show
<textarea> where it can be edited. A "Run" button starts the
show, and a "Stop" button halts a running show. There is
presently no mechanism to pause and resume a show at the current
location. A "Clear" button clears the show box. The only show
currently defined in the drop-down box is shows/demo.jss, which
reproduces the original DOS version demo which was done with a
.bat file and command line arguments.
While a show is running, the animation timer is always active.
On each animation interval, if a show is running, we proceed as
follows. First of all, if we're waiting for the interval
specified by a "wait" command to expire, count down the time
remaining and return. If we're waiting for an asynchronous
request (for example, loading a rule, pattern, or palette from a
URL), return and continue to poll until it completes. If we're
executing a specified number of generations from a "run"
command, perform the generation, count down generations left,
and continue. Otherwise, call show.nextShow() to execute the
next command from the show.
Show commands are as follows:
banner <time> // Display banner for <time>, 0 = no timeout
// Followed by banner HTML, terminated by --
cell [<op>]v col row // Set (col,row) to v, op = & | ^ or null for store
evaluator [<url> [override]] // Null spec cancels existing evaluator
generation <n> // Set generation counter to n
palette <url>
patch (eval[uator]|rule]prog]) /<regex>/ "<replacement>" // Rebuilds
pattern <url>
plane <mask> clear/set/invert/random [<n%>] // Set hex mask bitplanes
random <density> // Set plane 0 to random density, clear 1-7
rule <url> // Note that rule may load pattern, palette
ruleprog <url> // Loads .js rule program, generates
run <generations>
speed <gen/sec> // Sets generations/second, 2-200
stop // Stops show (running off the end stops also)
swap <plane1> <plane2> // Swap bit planes in map
top // Scroll to top of page
wait <seconds> // Pause show
Comments are denoted by "//" and blank lines are ignored. New commands
will be added here as they are implemented, so that this can serve as
a reference for the manual, when it is written.
You can start a show from the URL with the query "?show=url".
2017 May 3
Just a note on strategy: it would be easy to slog on and
implement every conceivable operation (the bit plane editor,
etc.) in the show language, but let's be reasonable. The only
people who are going to write shows are the creators of this
program, and only for demos or examples linked to the manual.
Consequently, the show language should be restricted to only
those capabilities needed by those demos. It would be easy
enough to allow shows to run other shows with a stack, but
unless we really need it, why bother with the complexity?
Better to invest the time in the documentation or more
interesting rules.
The evaluators/laplace.js evaluator was missing from the
drop-down list. I added it as "Laplace".
When a show is running, the "Start/Pause" button below the
canvas changes to a "Stop" button which aborts the show and
stops the simulator (if running). It then reverts to a "Start"
button which behaves as when no show is running. This provides
a more intuitive way of stopping a show than the "Stop" button
above the show window.
Added support for type 5 palettes (ASCII, 0-255 intensity) to
Tools/makejcp/makejcp.pl.
2017 May 4
To make it easier to experiment with gas flow rules, I added the
following to the standard directories (but not drop down lists):
ruledefs/_gasflow.js
patterns/_gasflow.jcp
palettes/_gasflow.jcc
evaluators/_gasflow.js
The leading "_" indicates experimental files not ready for
general release. The rule loads the pattern and palette and
sets up the initial random pattern for the gas. It assumes
the user will load the evaluator and set override, as it does
not request an evaluator (which currently would have to be
compiled into scripts/ruledefs.js, and hence difficult to tweak
during development).
Added onkeydown event handlers to all of the URL load text
boxes in index.html so that pressing the Enter key in the
box causes the name in the box to be loaded. It's a shortcut
for pressing the corresponding "Load" button.
Added a "top" command to shows to scroll to the top of the
page, guaranteeing the map is displayed.
While a show was running the Start/Pause button changed to
"Stop" to stop the show, but when the show ended, it didn't
change back to "Start". Fixed.
Added "ruleprog=" as a URL query option. This loads and
compiles the named rule program, setting overrideRule so that
URL pattern and palette requests can override those requested by
the rule program.
Added "eval[uator]=<eval>[!]" as a URL query option. The
named <eval> is loaded and compiled, and the Override box is
checked if the evaluator's name is followed by an exclamation
point.
Created a colour bar pattern generator in Tools/colourbar. The
resulting colour bar consists of columns with states from 0 to
255 and 0 thereafter. It allows simple visualisation of a
palette. This could be a lot fancier, but it gets the job done.
2017 May 5
Implemented a very raw first cut of a continuous cellular
automaton simulating flow of a compressible fluid. This is
based upon the work of Janis Elsts / W-Shadow as described in:
http://w-shadow.com/blog/2009/09/01/simple-fluid-simulation/
I rewrote his Java dialect evaluator as a JavaScript user
evaluator for WebCA. The evaluator allocates its own private
single precision floating point arrays to keep track of the mass
in each cell and updates them on each generation. The world is
taken to be open, but this can be constrained at discretion by
drawing GROUND state cells at the boundaries. The evaluator is
in evaluators/_water.js, and palettes and patterns are developed
in Tools/makejcp/water*. You can draw patterns with water in
blue, ground in yellow, and air in black, then convert them with
makejcp.pl using the water.jcc palette.
This continuous rule illustrates that we need some more
facilities for fancy evaluators like these. In particular, an
evaluator should be able to register a rule.evaluator.init
function which is called the first time the evaluator is called
after a new rule or pattern is loaded (or when the evaluator
itself is loaded and run the first time with an existing rule or
pattern).
Yeah, OK, we're going to call it WebCA. I detest the name, but
I detest it less than any of the alternatives which have come
to hand so far.
Modified the "Clear" button for the Evaluator function box to
not just clear the textbox but also delete the ownCode function
definition and any evaluator local storage in rule.evaluator.
Added a "speed=n" query to the URL. It sets the animation speed
to display n generations per second, with n constrained to be in
the range 2-200.
Added optional rule.evaluator.generationStart and
rule.evaluator.generationEnd functions which a user evaluator
can register to perform operations before and after each
generation. These functions are declared by assigning the
variables in the evaluator's prologue and are called before
and after the loop which invokes the evaluator for every
cell. Currently only user-defined evaluators in .js files
may use this facility because only they have prologues in
which the variables can be assigned.
Bit the bullet and made a global change:
treesed reqworld worldtype -tree
to replace the nonstandard rule.reqworld with the nomenclature
used in all other rule definition procedures. This brings the
variables assigned by JavaScript rule definitions into agreement
with those used by C. (Java has its own functions to set rule
requests and doesn't use the variables directly.) It also fixes
the inconsistency between "reqworld" and "patreq", etc. I'm not
going to delete the backup files from this change until I'm sure
I didn't break anything.
2017 May 6
Added a warning in rule.js Rule.loadRule() if the rule
(experiment) contains embedded own code (RSEOCODE instruction).
An alert tells the user that the embedded own code will be
ignored and that an equivalent JavaScript user evaluator should
be loaded and the Override box checked.
Commented out the built-in rug() evaluator in ruledefs.js. This
was just for testing; the Rug rule actually uses the semi8
evaluator.
Commented out Rule.builtin() in rule.js. This was used to evaluate
built-in rules during the early development phase. It has been
superseded by user evaluator functions.
If a rule requests a user evaluator and it is not built-in as a
function in ruledefs.js, Rule.processRuleRequests() in rule.js
will now attempt to load the evaluator via URL from the evaluators
directory and set the Override check box to cause it to be used.
This should eliminate the need to build in any additional
evaluators. Evaluators don't run any faster when built in
as opposed to loaded from a file and compiled.
We have traditionally set the world type to 1 (2D torus) in all
of the rule maker programs so the user didn't have to specify it
for the most common case. This was not the case for JavaScript
rule definitions, which had to set rule.worldtype. For
consistency, I made 1 the default rule.worldtype in
Rule.initreq() in rule.js. I still think sample rules should
always specify the worldtype in the interest of documentation.
Added a rule.evaluator.onChange variable which to which the
prologue of a user evaluator can assign a function which will be
called whenever a new pattern or rule is loaded. The argument
is a string, "rule" or "pattern", indicating what has changed.
Added a rule.evaluator.generationFirst facility to casim.js.
If the prologue of a user evaluator has assigned a function
to this variable, it will be called before the first time the
evaluator is invoked to update a cell (and before its
generationStart function, if any). The variable
rule.evaluator.generationFirstDone will then be set true to
suppress subsequent calls. If the evaluator wants to
reinitialise (for example, in response to a call to onChange
indicating the loading of a new pattern), it can set
generationFirstDone to false, and generationFirst function will
be called before the next generation. All one-time evaluator
initialisation should be done this way, as it is 64,000 times
faster than checking a first time flag within the evaluator
function itself.
Updated the _water.js evaluator to use the new evaluator
generationEnd, generationFirst, and onChange functions.
We seem to have survived the global change from reqworld to
worldtype, so I deleted the treesed backup files from
the change.
2017 May 7
Replaced evaluators/randgas.js with a new version derived
from the more general _gasflow.js which maintains strict
conservation of particles. Deleted the gasflow() evaluator
from scripts/ruledefs.js, since we can now automatically
load the source evaluator from the evaluators directory.
Replaced evaluators/gaswall.js with a new version derived
from the more general _gasflow.js which maintains strict
conservation of particles. Deleted the gaswall() evaluator
from scripts/ruledefs.js, since we can now automatically
load the source evaluator from the evaluators directory.
Added a new patterns/dot.jcp, which is just a single cell
set to state 1 in the centre of the map, surrounded by
zeroes.
Added new triangs.js and squares.js in ruledefs.js. These
are two unconstrained growth rules from Toffoli & Margolus,
section 5.1, included for completeness.
2017 May 8
Moved assorted experiments and obsolete attempts at random
gas diffusion and flow into Tools/gasflow so they don't
clutter up the evaluators directory.
Ported the following Toffoli & Margolus rules from C to
ruledefs/*.js:
diamonds.c -- Diamonds unconstrained growth
oneof8.c -- Constrained growth
lichens.c -- Lichens
lwdeath.c -- Lichens with death
endworld.c -- Sorcerer's apprentice (Renamed sorcerer.js.
I'm not sure what this is supposed to do.
Will have to consult T&M when I get back.)
majority.c -- Majority voting
aging.c -- Rudy's aging rule
Further progress on the animated logo. Development is in
Tools/logo. The current cut has CelLab in a bold font with
an invariant border. Inside the letters TimeTun runs, while
outside Brain runs. Installed in the standard rule, pattern,
and palette directories as _logo.* to facilitate testing.
Added the logo to the start of the shows/demo.jss show.
2017 May 9
Renamed the working directory webca.
2017 May 12
Commented out the randnabe() evaluator in ruledefs.js. We've
already implemented it in evaluators/randnabe.js. I'll review
ruledefs.js and remove other duplications of evaluators now
available as loadable functions.
Confirmed that ruledefs/spins.js is behaving as described in
T&M. I added a comment to the top mentioning that it is
reversible and how to get it to reverse. Added to the drop-down
list of rule programs and the demo.jss show. Note that this
rule is not yet defined in rules-java.
2017 May 13
Created a:
/files/me/webdev/cellab_2017/Tools/mansync
script to synchronise the local manual directory with the test
directory:
aws:/home/me/web/entrenous/rxvwm
Added a new:
plane <mask> clear/set/invert/random [<n%>]
command to shows. <mask> is hexadecimal.
Used the plane command to demonstrate reversing the Spins
rule in shows/demo.jss.
Added a simple benchmark facility. If you press Ctrl+b with the
mouse in the map window while the simulator is running, an alert
will tell you how many generations per second you're getting.
Each press of Ctrl+B resets the benchmark interval. This will
be handy to compare tweaks to user evaluators.
Fixed an off-by-one error in Map.edges() in map.js handling
wrapping the bottom right corner cell to the top left. The code
actually propagated the wrap-around cell, not the bottom right
cell of the map. Amazingly, this did not destroy the coherence
of TimeTun or Revecoli, but my Swapdiag Margolus neighbourhood
testbed picked it up. Fixed.
2017 May 14
Developed two new evaluators, margolus and margolusp, (they
currently have leading underscores, which will go away when
they're off probation) which directly implement the alternating
four cell block Margolus neighbourhood without the need for a
rule definition to do any of its own housekeeping with textures,
temporal phase, or sacrifice bits in the cell to keep track of
them. In addition, a rule can see 2 bits of state from each of
its three Margolus neighbours (plus, as usual, all 8 bits of its
own state). The evaluator keeps track of horizontal, vertical,
and temporal phase and assembles a lookup table index in which
the high byte is:
CW1 CW0 CCW1 CCW0 OPP1 OPP0 A B
where the six top bits give the two low bits of state from the
three relative neighbours in the current phase. The A and B
bits provide the vertical and horizontal phase to the rule for
the margolus evaluator and 0 and the temporal phase for the
margolusp evaluator; this the only difference between them.
A rule program takes apart the oldstate provided to it with
code like:
function hppgas_walls(oldstate) {
// Extract Margolus relative neighbours from oldstate
var CENTER = BITV(0),
CW = BITV(14),
CCW = BITV(12),
OPP = BITV(10);
// You only need these if you care about plane 1 values
var CENTERp = BITV(1),
CWp = BITV(15),
CCWp = BITV(13),
OPPp = BITV(11);
// Return bit from oldstate
function BITV(p) {
return (oldstate >> p) & 1;
}
and the rule is then written using the logical neighbours. The
rule is, of course, free to use the other bits of the centre
cell's own state in the low byte of oldstate. For example, here
is the equivalent of our PerfumeX written using the margolus
evaluator:
return (wall() ? CENTER :
(collision() ? CW : OPP)) | (CENTERp << 1);
// Detect a collision between two particles
function collision() {
return (CENTER == OPP) &&
(CW == CCW) &&
(CENTER != CW);
}
// Detect the presence of a wall
function wall() {
return (CENTERp | CWp | OPPp | CCWp);
}
I added several experimental rules, patterns, and palettes to
test these new evaluators, as follows:
ruledefs/_swapdiagM.js Simple swap diagonal gas
ruledefs/_hppgasM.js HPP gas
ruledefs/_hppgas_wallsM.js HPP gas with walls in plane 1 (PerfumeX)
ruledefs/_tmgasM.js TM gas
ruledefs/_tmgas_wallsM.js TM gas with walls in plane 1 (PerfumeT)
patterns/_tmgas_wallsm.jcp Perfume pattern with planes reassigned
palettes/_tmgas_wallsm.jcc Palette for the above pattern
Due to limits on the number of bits in the lookup table index,
it isn't possible for a rule to simultaneously see both the
spatial (vertical and horizontal) and temporal phase at the same
time; it must choose between margolus and margolusp. However,
there's nothing to prevent a rule from using the margolus
evaluator, which provides spatial phase, then using one bit of
its own state to maintain a temporal phase in the usual manner.
Added a special case to Map.paint() for zoom == 2. This is by far
the most common (in fact, at the moment, the only) setting, and we
were copying the map to the screen buffer with general code which
handled any zoom factor, involving multiplies in the loop and
doing all the work over for lines which were guaranteed to be
copies of lines we'd just created. I wrote new code which does
all accesses to the map and screen buffers with progressive
indexing, replicates pixels horizontally with written-out
assignments in the inner loop, and blast copies even lines
to odd lines with TypedArray.copyWithin(). If the browser
does not support copyWithin(), the general pixel-by-pixel code
is used. The speed-up, measured by the benchmark, using the
default 2D evaluator, is between 10-15%.
Implemented a new utility:
Tools/jcpcomp/jcpcomp.pl
which is invoked as:
perl jcpcomp.pl [-ascii] infile.jcp outfile.jcp
It reads infile.jcp, an uncompressed ASCII pattern file, and
writes outfile.jcp, either a binary pattern file (which is
always compressed) or a compressed ASCII pattern file is -ascii
is specified. It only reads uncompressed ASCII pattern files,
but this is no problem because you can always load a pattern
file in another format into WebCA, dump it as uncompressed
ASCII, and then convert it to whatever other format you wish.
This is mostly for our own use. Since you can't save a pattern
file except as an ASCII dump, it provides a way to convert them
to compressed binary for faster downloads. I will make it
available for users, but I doubt if anybody will need it, since
storage is so extravagant these days and loading from a local
file takes hardly any time regardless of size. It's messy that
it's in Perl, since that compromises the JavaScript purity of
the project, but I decided that getting Perl to run (which it
does, out of the box, on any Linux installation or Mac) is
generally less trouble than installing node.js, it's preferable
for little utilities like this which are developer nerd features
not on the critical path for users. Besides, if a demand really
appears to compress pattern files, it's a one hour hack to turn
this program into a CGI server that lets users paste
uncompressed ASCII pattern files into a box and get back
compressed binary files in return.
2017 May 15
Ported ruledefs/_hppgas_wallsM.js to
rules_java/_hppgas_wallsm.java. The difference in capitalisation
of the name is due to the fussiness of Java about file names
having to agree with the name of classes declared within them.
This works exactly the same, and is a pathfinder for possible
including the Margolus neighbourhood definitions in
ruletable.java along with the shortcuts for other evaluators. I
haven't done anything with the .jc file other than test it. I
won't install it anywhere until all of this frenzy settles down.
Loading a rule with an own code request which was satisfied by a
compiled-in evaluator did not turn off the "Override" request
for an evaluator loaded by a previous rule Fixed. It we
proceed to make all evaluators dynamically loaded, this will
cease to be an issue.
Added a cryptography demo in:
shows/crypto.jss
patterns/crypto.jcp
This loads the Revecoli rule and crypto.jcp, which is a message
that has been run 1000 generations through Revecoli and then had
planes 0-3 and 4-7 swapped before saving. We then run 1001
generations to recover the original message. The encrypted
original pattern is 64K, but who cares any more?
2017 May 16
Changed the name of "Timetun" to "TimeTun" in the drop-down
lists in index.html to agree with the manual. Changed the name
of "Votedna" to "VoteDNA" in the drop-down lists in index.html
to agree with the manual.
2017 May 17
Tested using gtk-recordmydesktop to capture a run of the
Demo show. With 100% video quality, it was a faithful
and viewable capture which occupied 367 Mb. I will try
with different levels of quality to see how the tradeoff
works out. The goal is to be able to post a promo on
YouTube. It may be better to capture the video at 100%
quality, then edit and encode with OpenShot, which offers
many more options.
Added Crypto to the list of standard shows in the drop-down list.
Implemented "procedural palettes". This is a new form of
ASCII palette file, specified by a type code of 7 on the first
line, which consists of a sequence of statements which assign
colours, which can be any form of colour specification accepted
by CSS, to logical states. The physical states from 0 to 255,
and a mask applied to select bits we wish to affect the colour,
allowing "housekeeping bits" to be excluded. Each physical state
is ANDed with the mask, and the resulting logical state
looked up in the table of those specified. The statements
in a procedural palette are:
mask <number>
Mask the physical states by ANDing with <number>.
The number can be in any form acceptable to JavaScript's
parseInt() function. If no mask is specified, 0xFF is
assumed.
state <state list> <colour>
The CSS <colour> specification is assigned to the states
in <state list>, which is a comma separated list of states,
each of which can be a number (again, parseInt() format),
or a range separated by a hyphen. "state" may be
abbreviated to "s".
Comments are indicated by "//", as in JavaScript. Blank lines
are ignored. For example, here is a complete procedural palette
for the Perfume rules:
7 // Procedural palette for the Perfume rules
mask 6
state 0 black // Color name
s 2 #0000FF // Hex RGB specification
state 4,6 rgb(255, 255, 0) // Decimal RGB
You can have fancy list of state specifications like:
state 2,3,7-12,0x19-0x21 hsl(120, 60%, 70%)
2017 May 18
Commented ruledefs/wator.js. I needed to understand how it
worked in order to document it for the Rules chapter in the
manual, and decided to embed what I learned in the program. I
haven't added the comments to th Java version, and may not
bother since few people are likely to look at it.
The evaluators/randgas.js contained a wall test inadvertently
left in when the code was back-ported from gaswall.js. Fixed.
The evaluators/randswap.js, used by Wator, contained the same
bug which caused swapped cells to be lost in the wrap-around
edges when running in toroidal mode which was earlier fixed in
randgas, gaswall, etc. I integrated the code from them handles
the wrap-around internally in order to preserve particle
conservation. Commented out the built-in version of randswap in
ruledefs.js to force the one from the evaluators directory to be
used.
Created a new test directory:
aws:~/web/entrenous/rxvwu
which will be an exact mirror of the final production directory.
A new Tools/allsync script mirrors the manual, webca, and
index.html files into this directory. Additional directories
will be added eventually for tool and source downloads.
Changed the rule and ruleprog drop-down list items to "Turmite"
to agree with the nomenclature in the manual and the name of the
evaluator.
2017 May 19
Added PerfumeM and PerfumeR to the Rule program drop-down list.
Changed names of PerfumeT and PerfumeX to capitalise final letter
and agree with manual.
Changed drop-down item to RainZha to agree with manual.
Added Water to the drop-down list for Rule programs.
Renamed rules_java/_hppgas_wallsm.java to perfumem.java;
made internal name changes to agree, modified pattern and
palette requests to "perfumem" and evaluator to "margolus".
Added to drop-down list of standard evaluators:
Gasflow, Gaswall, Margolus, Margolusp, Water
Made a trivial rules_java/perfumer.java, generated
rules/perfumer.java, and added PerfumeR to the Rule URL
drop-down menu.
Added a shows/_logo.jss to run the logo for automated logo
development. Note that we don't have an option on the show
run command to run forever.
Continued work on the animated logo. I created a testbed,
logowork.html, in the parent directory. This contains a display
of 640x200 pixels (the first test of our ability to run with a
display and map size other than the default) and just enough
controls to run a show with a single ruleprog. The new
shows/_logo.jss loads ruledefs/_logo_short.js, which is
identical with _logo.js except it loads patterns/logo_short, a
version of the logo pattern cropped to fit in a 320x100 map.
This was created from Tools/logo/_logo_short.xcf, which was used
to make the pattern file with:
perl ../makejcp/makejcp.pl _logo_short _logo1.jcc
it turns out makejcp.pl is cool with making patterns of
nonstandard dimensions. To enable the emulator to find
everything it needs, I made symbolic links in the parent
directory of:
palettes -> webca/palettes
patterns -> webca/patterns
ruledefs -> webca/ruledefs
shows -> webca/shows
I may make a more elegant solution to this, such as creating
actual directories with just the files needed for the logo, but
this get the job done for now and provides flexibility for
testing things. Note that I don't create links for directories
I'm not presently using in the logo. I have left a "Stop"
button in the logowork.html for the moment. All the other
fields and controls are hidden in a "display: none;" <div>. A
static image, manual/figures/logo_static.png, is used if the
browser does not support <canvas>.
Added the ability to override the search string supplied by the
URL (window.parent.location.search) by setting overrideSearch in
the onload= attribute of a page's <head> tag. It would be nice
to be able to store into window.parent.location.search but that
causes the page to be reloaded. This allows pages using the
animated logo to specify the "?show=_logo" query without the
need to include it on the URL.
Integrated the animated logo into the main index.html file. I
moved the "Start/Stop/Pause" button to the right of the by-line
below the logo. Integrating the animated logo required
converting the page to HTML5, which was straightforward. The
animated log has the advantage that if the user's browser won't
support running WebCA, he'll know before proceeding further.
2017 May 20
Renamed "water.*" to:
ruledefs/glooper.js
patterns/glooper.jcp
palettes/glooper.jcc
after MONIAC in Terry Pratchett's "Making Money". Note that the
evaluator is still called "evaluators/water.js". Changed the
Rule Program URL drop-down menu item to agree. Added a
rules_java/glooper.java and made a rules/glooper.jc. Added
Glooper to the Rules URL drop-down.
Added precomputation of the Margolus neighbours for both plane 0
and plane 1 to rules_java/ruletable.java when an own code
worldtype is in use. We don't check for the margolus evaluators
since the user may not have explicitly requested it. Neighbours
are:
CENTER, CW, CCW, OPP, // Plane 0
CENTERp, CWp, CCWp, OPPp // Plane 1
Modified rules_java/perfumem.java to use these precomputed
definitions.
Commented out console.log debug output in rule.js which echoed
rule requests.
Modified evaluators/runny.js and meltdown.js to use the
rule.evaluator.generationStart function to determine whether
its call is the first per generation rather than testing the
cells[] index, which is kind of hokey.
Cleaned up comments in evaluators/turmite.js to eliminate
references to assembly language code and reformat for
easier reading.
Used jcpcomp.pl to compress patterns/_logo_short.jcp. I put in
a patch to ignore the length of the map in this image. With the
check turned off, the compressor works with maps of any length.
Created a Tools/make_devkit directory and make_devkit
shell script within it to assemble the Cellab Development Kit
archive users can download to obtain all of the standard rules,
patterns, palettes, shows, and development tools. The archive
will contain a README.txt, maintained in the make_devkit directory,
which explains the contents. The archive is created as
cellab_devkit-<VERSION>.zip
in the make_devkit directory. It's up to you to install it in
the download directory when it's ready for release.
Added synchronisation of the download directory to the production
directory in Tools/allsync.
2017 May 21
Added a utility to convert colour palette (.jcc) files, whether
in VGA or RGB colour format, into binary format or ASCII (either
VGA or RGB). The utility is in:
Tools/jcccomp/jcccomp.pl
and is invoked as:
perl jcccomp.pl <input.jcc> <output.jcc>
You set the output format by variables within the program. The
defaults (which you'll always use unless you're crazy or doing
something inadvisable) are RGB colours and binary.
Made a new logo for the manual table of contents. This is built
in Tools/logo/hodgelogo* with the final image hodgelogo1.png.
I'm still not entirely happy with this, but it's a lot better
than the one it replaced.
Replaced palettes/perfumem.jcc with a procedural palette, just to
provide an example, and because it's so much smaller than the one
it replaced.
Used jcpcomp to compress patterns/
glooper.jcp
perfumem.jcp
_logo.jcp
fullearth.jcp
bob128.jcp
Deleted patterns/_tmgas_wallsm.jcp: it was a duplicate of
perfumem.jcp.
Deleted patterns/_waterglassleak.jcp. It has been replaced by
the more complicated (and better-drawn) glooper.jcp. If you miss
it, it's still in Tools/makejcp.
Fixed ruledefs/_gasflow.js to load the "gasflow" evaluator.
Previously it required the user to manually load the evaluator.
Added a Java rules_java/spins.java definition, added the
resulting spins.jc to the rules directory and the drop-down list
of compiled rules.
Replaced the following palettes/ with procedural palettes, which
are even smaller than a binary file:
mite.jcc
glooper.jcc
wator.jcc
Compressed the following palettes/ with jcccomp.pl:
turmite.jcc
After further deliberation, I decided I did actually need an
increment as part of a range specification in a procedural
palette. You can specify, for example:
state 5-253-4 yellow
to set states 5, 9, 13,...253 to yellow. Ranges with increments
can be combined with other states and ranges in comma-separated
lists.
Removed tmgas.java and its rules/tmgas.jc, and removed from the
compiled rule drop-down list. This was an obsolete version of
TM-gas which has been superseded by PerfumeT.
Added an automatic build counter which is added to the
webca/index.html page by Tools/buildno/buildno.pl when
Tools/allsync is run. I started the build counter at 265,
which is the number of flashbacks done to date.
Now that Griff is a sample rule, I added a rules_java/griff.java
and rules/griff.jc definition of it.
Added new sample rules to shows/demo.jss.
2017 May 22
Added the ability to create relative length shows. The run command
in shows has been extended to accept the syntax:
run [=+-*/]<generations>
If no operator appears before <generations>, it runs the
specified number of generations as before. The operators:
= Store <generations> as the default; use on this run
+ Run default + <generations>
- Run default - <generations>
* Run default * <generations>
/ Run default / <generations>
The argument to operators can be floating point; the result is
rounded to the nearest integer.
Started to work on publication of the development log. The
first step is:
Tools/mergelog/texttohtml.pl
which converts arbitrary text to HTML. I installed this,
without the .pl extension, in ~/bin on Hayek and Ragnar, since
it will doubtless prove useful elsewhere. I do not, however
rely upon it being there in the WebCA development scripts.
Implemented:
Tools/mergelog/mergelog.pl
This reads a log_template.html file from its execution directory
and merges it with the development log from webca/log.txt and
the build number and date from Tools/buildno/webca.txt and
creates the HTML log file in log/log.html in the CelLab parent
directory. The log is converted to HTML with texttohtml.pl,
dates are wrapped in bold tags, and references to local user
names are replaced by <em>me</em>.
Added a call to mergelog.pl to Tools/allsync and an rsync
command to copy the log directory to its destination on the
server.
Modified Tools/allsync to exclude webca/log.txt since it is now
supplied in easier-to-read HTML form in log/log.html.
Deleted evaluators/_rug.js. This was a stand-alone rug rule
evaluator developed while debugging the semi8.js evaluator
and the ruledefs/rug.js rule program.
Deleted evaluators/_fluidflow.js. This was an ill-conceived
attempt at flow with sources and sinks. It turned out to be
essentially a re-implementation of the Heat rule.
Promoted Gasflow to a full-fledged sample rule. Removed the
leading underscore on its name in ruledefs, patterns, and
palettes (the evaluator had already been promoted). Replaced
palettes/gasflow.jcc with a procedural palette which is more
comprehensible and much smaller. Added to Rule and Rule
program drop-down lists. Made a Java gasflow.java and used
it to build rules/gasflow.jc. Added to shows/demo.jss.
I changed the flow parameter in evaluators/gasflow.js
to 25, which produces more realistic flow. The setting of
100 is great for debugging, but it produces unrealistic
piling up of particles on leading edges.
Implemented colour gradients in procedural palette files.
This is handy when you want to create "false colour" maps to
show, for example, heat in an averaging rule. You specify a
list of states in the usual way and a start and end colour
separated by a hyphen.
state 128-255 blue-red
The gradient will be scaled to provide a smooth transition over
the number of states specified by all of the states and ranges
named on the command.
Created a replacement for the obsolete (and incorrect)
patterns/chroma.jcp image with:
Tools/colourbar/chromap.pl
This creates a 16x16 square test pattern which shows the colours
of all states in the current palette in a grid, with blocks of 8
separated by extra space for easier reading. The background is
state 0, so if that isn't black, it may be less readable. I
compressed this to binary with Tools/jcpcomp/jcpcomp.pl and
installed it in patterns/chroma.jcp (note the change in name).
This image is just what you need when verifying that palette
files are what you intended. It is also an interesting start
pattern to understand averaging rules and other which operate on
ranges of states.
Added Tools/colourbar/chromap.pl to the tools directory in the
Development Kit.
Integrated the existing ~/web/cellab tree under classic. Added
links to it in index.html and manual/chap5.html for those
consumed by nostalgia who wish to visit programs of yore. Note
that this is maintained only on the server, not the development
directory, and is not disturbed by Tools/allsync, which never
references it.
2017 May 23
Replaced palettes/grey.jcc and grey128.jcc with procedural
palettes using gradients. Added these to the drop-down list
of standard palettes. Note how grey128.jcc combines a gradient
and a mask to produce a sawtooth gradient.
Compressed the following palettes/ to binary:
steapot.jcc
x29.jcc
_logo.jcc
2017 May 24
Implemented the initial cut of a computational fluid dynamics
simulation as a WebCA evaluator. This is based upon:
http://physics.weber.edu/schroeder/fluids/
Please see the copyright statement in evaluators/cfd.js for
details and full attribution.
The evaluator implements a lattice Bernoulli algorithm which
maintains a private map consisting of 12 single-precision
floating point quantities per cell which specify the microscopic
densities for the cell and its eight neighbours, the macroscopic
density, and macroscopic velocity (x and y) for its contents,
plus a flag distinguishing impermeable barrier cells from those
containing fluid. An additional array holding the curl of each
cell is used only in displaying the map if curl display if
desired, and is computed on demand.
The evaluator examines the map it is given on the first
generation and sets any cells with state 255 as impermeable
barriers. There is a source automatically placed at the left of
the map creating a flow from left to right. The wind.jcc
palette defines false colours representing intensity for states
1-254, with state 255 reserved for barriers and rendered in
black. The ruledefs/wind.js program exists only to load the
evaluator, pattern, and palette; no lookup table is used.
The evaluator can compute multiple updates of its internal maps
per displayed generation. Setting rule.evaluator.stepsPerGeneration
at the top can almost double effective performance. By default,
it is set to 10 which, on my modest laptop, delivers an effective
update rate of more than 140 generations per second.
Other variables at the top allow you to set the speed of the fluid
flow between 0 and 0.12, the viscosity of the fluid between
0.005 and 0.2, and which property of cells is displayed in the map:
0 Density
1 x Velocity
2 y Velocity
3 Speed
4 Curl (default)
Replaced palettes/wind.jcc, which had been generated by a Perl
program, Tools/cfd/cfdpal.pl, with a procedural palette that
produces identical results and is around 1/8 the size and a lot
more comprehensible.
Created a Tools/cfd/template.xcf image to use as the base for
drawing things to run with the Wind rule.
Added a gimmick to Rule.owncode() in rule.js. If a user
evaluator returns null, it immediately aborts the loop calling
the evaluator. This allows evaluators which do everything in
generationStart() and/or generationEnd() to do away with the
overhead of calling the evaluator for every cell in the map.
It's far more efficient for such an evaluator to update the map
itself than make a function call for every cell.
Used the null return gimmick to rewrite the wind.js evaluator
function to blast update the entire ncells map in one call and
then abort the evaluation loop. This picked up a small but
visible amount of speed.
Added a rules_java/wind.java definition, built a wind.jc, and
installed in the rules directory. Added to drop-down list in
index.html.
Just as an experiment, I converted the arrays in cfd.js to
Float64Array to see what would happen to execution speed. It
seems to have slowed down very slightly. I changed them back to
Float32Array.
2017 May 25
Implemented the T&M BBM (billiard ball machine) rule from section
18.2, p. 214. This was easy with the margolus evaluator. I'm
developing demo patterns in Tools/bbm. So far, I've verified that
particle motion, fixed blocks, reflection, and collision work
as intended.
Misplaced code in Palette.loadProceduralPalette() (palette.js)
caused mask statements to be rejected if they occurred before
the first state declaration. Fixed.
Rewrote the palettes/mask1.jcc file as a procedural palette. It was
this one that smoked out the previous bug.
Converted palettes/mask2.jcc and mask3.jcc to procedural palettes.
Renamed all of the _logo* files to logo*. This required
changing the pattern and palette requests in ruledefs/logo*.js,
the ruleprog statements in shows/logo.jss and demo.jss, and the
reference that runs the logo in the main index.html file. I
rewrote logo.jcc as a procedural palette. Added a link in
index.html so you can launch WebCA by clicking on the animated
logo at the top of the page.
In Tools/makejcp/makejcp.pl, the test when building the hash
from RGB colours to state table indices would never assign state
0 because the test as to whether the colour had been previously
seen considered index 0 as not defined. I added a defined() to
the test to distinguish the two cases.
Built a bbm.jcp pattern to demo the BBM rule in Tools/bbm,
compressed with Tools/jcpcomp/jcpcomp.pl.
Created a ruledefs_java/bbm.java and used it to build
rules/bbm.jc. Added Bbm to the drop-down lists in webca/index.html.
Note: to run the Bbm rule in reverse, pause, perform:
rule.evaluator.phase ^= 4
and resume. You can create a pattern which will run backwards by
the following trick. Start with your coherent pattern and run it
forward until it randomises. Then step until you're stopped with
rule.evaluator.phase == 4 (you can query this with the debug console
in Chrome). Now save the pattern. When you reload the pattern
with the evaluator just loaded, the phase will be set to 0, since
that is where the evaluator always starts. Now when you run the
same number of steps, you'll be back at the starting point.
Added a show/bbmrev.jss, which demonstrates reversibility of the
Bbm rule.
Added a patterns/circle.jcp, a medium-sized circle in state 1
surrounded by a sea of state 0. This is a handy alternative to
square.jcp when you want less initial symmetry. Developed in
Tools/makejcp/circle.xcf.
Implemented the Toffoli & Margolus Critters rule (section
12.8.2, p. 132) as both JavaScript and Java, and added to the
drop-down list and shows/demo.jss. Critters is a one-bit
Margolus neighbourhood rule which is reversible (but not
trivially--you have to load an inverse rule). My version avoids
the strobe effect of the simple rule by including the temporal
phase provided by the margolusp evaluator in conjunction with a
specially-contrived palettes/critters.jcp that inverts the
mapping of states to colours according to the phase. Added
links to the Critters rule in chap5.html and footnote.html
in the manual.
2017 May 26
Implemented the Toffoli & Margolus Tron rule (section 12.8.3,
p. 134). This isn't sufficiently interesting or enlightening
to include as a standard rule; I'll leave it for the collection
of T&M "minor works". It's in ruledefs/tron.js, and includes
my modification to avoid the strobe effect.
2017 May 27
Implemented the Toffoli & Margolus Logic rule (section 12.8.4,
p. 136). This is a rule which uses the Margolus neighbourhood
to simulate the propagation of bits along wires which permit
the following logical operations:
Fanout of signals to multiple outputs
Cross-over of signals on wires without interference
Invert
And
The latter two, of course, composed as NAND, suffice to compute
all of the operations of Boolean algebra. The rule is defined
in ruledefs/logic.js and uses the demo pattern
patterns/logic.jcp and colour palette palettes/logic.jcc. The
palette is similar to mask3, but has a gimmick to allow
annotation with states >= 0xF0 to be displayed without
modification (the rule definition conspires in this). The
palette includes commented out state declarations which allow
debugging patterns by tagging cells with how many wires were
counted within a Margolus block in each step of the evaluation.
This rule is extraordinarily fussy about the precise alignment
of patterns with the horizontal and vertical texture, and
uncommenting these additional states can help track down
problems when making new patterns. The demo pattern for Logic
is developed in Tools/makejcp/logic.xcf. The pattern in
patterns/logic.jcp was compressed with Tools/jcpcomp/jcpcomp.pl.
Added Logic to the shows/demo.jss show.
Created a rules_java/logic.java file and rules/logic.jc file to
support this standard rule in Java.
Added:
patterns/wind1.jcp
as a pattern for the Wind rule with an interesting evolution.
This is not currently referenced in the manual or in any of the
demos.
Replaced absolute URL references used to run rules in the
manual with relative URLs. The absolute references permitted
testing the links when the documents were view on the local
machine, but now that the manual is approaching convergence,
there's no reason not to make them portable; testing them only
on the server isn't a burden at this stage.
Added a table to rules.html in the manual to provide access to
the following minor rules. These are defined in JavaScript
only, and are presented in M&T mostly to illustrate simple rule
programming. They don't produce sufficiently interesting
results to merit a full write-up in the Rules chapter. Each is
linked to a URL which will load the rule program with a suitable
pattern and palette to demonstrate it.
M&T sec. M&T page
Unconstrained growth:
diamonds.js 5.1 38
squares.js 5.1 37
triangs.js 5.1 38
Constrained growth:
lichens.js 5.2 40
lwdeath.js 5.3 40
oneof8.js 5.2 39
Margolus neighbourhood:
hppgasm.js 12.4 125 (margolus eval)
hppgas.js 12.4 125 (texture version)
swapdiagm.js 12.4 125 (margolus eval)
swapdiag.js 12.4 125 (texture version)
tmgasm.js 13.7 131
tmgas_wallsm.js 15.2 160
tron.js 12.8.3 134
Voting:
majority.js 5.4 41
Computing:
banks.js 5.5 42
2017 May 28
Finally got the "End of the World" rule (T&M 18.3.2, p. 219)
working. I foolishly assumed the version of it in C that I had
developed in 1994 was correct. It wasn't: it was entirely
ill-conceived and failed to correctly compute the phase used to
determine the Margolus neighbours. Also, I didn't note that you
have to start this rule with a pattern in an exquisitely
carefully-defined state: one created by running the Bbm rule
with an echo of the previous state to plane 1. Otherwise, the
pattern will explode into gibberish. I created a
ruledefs/bbmecho.js rule to create such patterns, which I'll
probably roll back into the standard bbm.js rule. I ran this
rule on the starting pattern bbm.jcp and saved it as
patterns/bbmecho.jcp. Running ruledefs/endworld.js on this
pattern resumes its evolution from where it was saved.
Now the trick about this pattern is that it is in an
extraordinarily low entropy state. All you have to do is to
flip a single bit in either the current or history plane, and it
will quickly self-destruct into seething dog barf. For example,
load endworld, let it run for a while, pause, and then flip a
bit in the middle of the map by entering and running the
following show command:
cell ^1 160 100
When you restart, that cell, which has no valid previous state
in the history plane, will go berserk and start spewing chaos
bombs into the map which will quickly reduce it to SDB. This
is the "End of the World" alluded to by the rule's name. This is
a metaphor for the fragility of highly-developed technological
society which is dependent upon a low-entropy infrastructure
few of its inhabitants are aware even exists.
I ended up rewriting the rule from the messy (and wrong) C
definition to proper JavaScript, using a nested function in
the rule table generator which accesses the Moore neighbours
as variables in the outer function context.
Modified ruledefs/bbm.js to always echo cells' previous state
in Plane #1, and preserve all other bits (mask 0xFC) as
colour tags. This eliminates the need for a separate
bbmecho.js to prepare starting maps for endworld.js, and
also means you can run Bbm, pause at any point, and have
a map on which you can run Endworld. I deleted bbmecho.js,
as it's no longer necessary.
Remade patterns/bbm.jcp and palettes/bbm.jcc. The new palette
ignores the history bit and assigns state 5 as the grey border
(which, since the 1 bit is set, remains active cells). The
pattern changes the border state to 5 to agree, but also is
the result of running two generations on the original pattern
drawn in Tools/bbm/bbm.xcf and then saving and compressing
the result. This puts in the history bits on plane 1, which
makes this a starting pattern compatible with endworld.js as
well.
Modified endworld.js to request the "bbm" pattern and palette
and to preserve the colour tag bits in cell state along with
the texture so the border appears in grey as with bbm.js. All
of this reassignments of bits and states means you can now flip
the direction of time in Endworld with the "Swap" button in the
Pattern section. The bbmecho.jcp pattern for Endworld is
now obsolete and was deleted.
Similarly remade patterns/bbmrev.jcp with the new palette and
including history so it can be used with both Bbm and Endworld.
Made it the default starting pattern for Endworld.
Ported endworld.js to rules_java/endworld.java, built
endworld.jc, and installed in rules. Added Endworld to the
drop-down lists for Rule and Rule program in index.html.
Fixed the bugs in endworld.c, wherever it lurked in the
development directories. We aren't going to distribute this,
but I wouldn't want someone else to blunder into it, think the
1994 version was correct, and suffer the anguish I just
experienced. It now produces a correct .jc file.
Added a shows/endworld.jss to demonstrate the reversibility
of Endworld and what happens if you introduce a discrepancy
between the state of particles and their history. Added the
show to the drop-down list in index.html.
Compressed patterns/wind.jcp with jcpcomp.pl. I had somehow
never gotten around to that and it was 192 Kb in ASCII.
Show commands with in-line comments were treated as full-line
comments and ignored. I fixed the regular expression that
looks for them to distinguish the two cases in show.js.
Added a patch command to shows:
patch (eval[uator]|rule]prog]) /<regex>/ "<replacement>"
patch evaluator /display = 1/ "display = 2"
Built and added a new patterns/airfoil.jcp for the Wind rule.
Added Wind as a standard show in the drop-down list. It is
defined in shows/wind.jss.
Banks' paper about his computer rule is:
https://dspace.mit.edu/bitstream/handle/1721.1/6891/AITR-233.pdf?sequence=2
I have made a local copy in:
Tools/banks/AITR-233.pdf
2017 May 29
Built a three-way Banks fanout in:
Tools/makejcp/banks.xcf
These are very fussy to build. The slightest error results in
your signal going nowhere.
Made jcpmake.pl, jcpcomp.pl, jcccomp.pl, and ppmtojcp.pl
executable and added #! /usr/bin/perl so they can be run without
invoking Perl.
Modified the Banks rule (ruledefs/banks.js and
rules_java/banks.java) to preserve the high 7 bits of the cell's
state. Although this rule works only on the low bit, this
allows using the high bits to colour-tag the various components
of the Banks computer.
The shows/logo.jss show began with a "top" statement, which
scrolled the window to the top. This broke any attempt to link
to an id="tag" within the document from another document. I
removed it.
Moved the development of patterns for the Banks rule to
Tools/banks.
Deleted the Tools/JavaScrypt directory. This was just a copy of
the online JavaScrypt release I made as a "code mine" to use while
I was on the road. Nothing was changed from the posted version.
Deleted Tools/
awsync*
mansync
which were obsolete sync scripts now supplanted by Tools/allsync.
Moved the cfd directory to Tools/cfd.
Moved the cellab and pdcalab directories to an "old" directory.
These are archives of earlier Web releases of CelLab used as
resources in development. They no longer need to clutter up the
top-level directory.
Added Banks to the drop-down lists of Rules and Rule programs
in index.html.
Installed patterns/banks.jcp and palettes/banks.jcc to support
the Banks rule.
Added pattern and palette requests of "banks" to the Banks rule
definitions in ruledefs/banks.js and rules_java/banks.java. The
Banks pattern is developed in Tools/banks.
Converted all of the "rule" commands in shows/demo.jss into
"ruleprog" so the JavaScript code for the rule definition will
be displayed.
Added Banks to shows/demo.jss.
2017 May 30
Modified Tools/allsync to exclude Base directories from the
sync. This allows us to carry along setbase Base directories for
development without having then appear on the public server.
The only such directory at this time is in the webca/rules_java
directory. I deleted the Base directory on the server; the new
rsync rule will keeping it from being copied again.
2017 May 31
Made an experimental version of the cfd evaluator, _cfd_opt.js.
When building the barrier array, it scans the cells and
determines the rule.evaluator.top and rule.evaluator.bottom
lines in the map which are the first and last which contain
non-barrier cells. This allows you to draw a "letterbox" pattern
in which the top and bottom are all barrier cells, and in which
only the non-barrier region in between them will be evaluated.
This linearly speeds up evaluation as the number of active cells
is reduced. I made a test drawing to illustrate a Karman
street, and it evaluates at 38.25 generations per second while
the same pattern running on a full height screen evaluates at
14.52 generations per second. Promoted to cfd.js and moved the
previous version to evaluators/Obsolete. Installed the letterbox
pattern as patterns/wind_karman.jcp.
Added a rule to Tools/allsync to keep Obsolete subdirectories in
the webca tree from being synced to the production server.
Installed the Brave browser for testing. Confirmed that
everything, including the Wind rule, runs as fast as it does on
Chrome.
Added a:
generation <number>
statement to shows to set the generation number.
Added accesskey= keyboard short-cuts for some common operations
to help in making demo movies.
r Start/Pause
s Step
S Run show
2017 June 1
Modified Show.loadURL() in show.js to permit a slash within the URL
specification to load a show (but not a leading slash). This
allows subdirectories within the shows directory, permitting the
collection of the shows used to make videos in shows/videos.
I may eventually extend this to the other load from URL methods,
although none of the other directories presently has subdirectories.
Modified Tools/make_devkit/make_devkit to create an intermediate
tar archive of the files to be included in the kit, unpack it into
a temporary directory, and make sure the read-only bit is clear on
any files included in the kit. Any subdirectories named Base or
Obsolete in the kit directory tree are ignored.
2017 June 2
We're in production! The current version is posted at:
http://www.fourmilab.ch/cellab/
with the simulator at:
http://www.fourmilab.ch/cellab/webca/
There is a new:
Tools/prodsync
script to sync the development directories with production. The
Tools/allsync
remains, for the nonce, to be used to sync to the test tree as a
staging site.
Deleted the ~/web/entrenous/rxvwt and rxvwm directories. These
were old test directories for WebCA and the manual which haven't
been used since May 18th.
2017 June 7
Added the shows from shows/videos to the drop-down list of shows
in index.html. They are given descriptive names, not just the
file name.
The shows/zhabo.jss started with the Hodge rule but assumed the
screen was in its initial random condition. If the show was run
after another which left a non-random pattern, the rule could get
off to a bad start. I added an explicit "random 50" before
starting the rule.
Fixed a typo in the first information banner in shows/cfd.jss.
2017 June 8
Reviewed all of the shows/videos and made sure that any which
required a random starting pattern explicitly created one with
"random 50" before starting the first rule. This keeps them
from misbehaving if run after another show that leaves a
non-random pattern in the map. The cfd.jss show, which sets
the simulator to "ridiculous speed" with a "speed 200"
statement, now resets the speed to the default "speed 33"
at the end so the next show will run at normal speed. Made
the same change to shows/wind.jss.
I added a "speed 33" reset to the end of shows/videos/zhabo.jss
which sets the speed to 10 to make the development of patterns
more clear.
2017 June 9
Updated the development kit to include the recent fixes to shows.
2017 June 10
In a procedural palette file, if a specification of the colour
of a single state followed the specification of a gradient, the
previous gradient would be used instead of the given colour.
In loadProceduralPalette() in palette.js, the code failed to
reset grad to null, indicating a single colour had been
specified, when parsing a single colour specification. Fixed.
Added the Forest rule, a forest fire model in:
evaluators/forest.js
ruledefs/forest.js
palettes/forest.jcc
rules_java/forest.java
rules/forest.jc
In addition, I added Forest to the Rule and Rule program
drop-down lists in index.html.
Set the disabled="disabled" attribute on the blank option lines
at the top of the drop-down lists so the user can't select them
after having selected another option. You also have to
specify selected="selected" on these items, otherwise the
browser will auto-select the first non-disable item. Specifying
both disabled and selected for the same option items is OK
with the W3C validator and works with both Chrome and Firefox.
2017 June 12
Added the ability to randomise maps to a floating point fraction
of one bits. In map.js, the Map.randomise() method now accepts
an optional fourth argument which, if true, indicates the
density argument is a floating point number between 0 and 1
which specifies the fraction of one bits in the map. If the
fourth argument is false or omitted, the density argument
remains an integer between 0 and 256 or -1 indicating 50%. If a
floating point density is given, a new Map.randtabF() method is
called which takes a floating point density.
Modified the onclick code for the "Random" button in index.html
to parse a floating point density number and pass it to
Map.randomise().
Extended the "plane" and "random" commands in show.js to accept
a floating point number for the density of one bits.
Updated the "Random" button handler in the Bit Plane Editor
dialogue in dialogue.js to accept a floating point density.
Added a new Dialogue.floatfield() method to parse and range
check a floating point argument from a dialogue field.
Note that because the rule initial random seed density request
is still encoded in a rule definition as a single byte from
0-255, floating point density cannot be requested by a rule.
Perhaps some day we'll extend the rule file format to permit
that, but this is not that day. For the moment, the extensions
to the main page, Bit Plane Editor, and shows suffice for
experiments and demonstrations of critical density in
percolation models.
Added a Forest demo to demo.jss.
Added the Bootperc bootstrap percolation rule as:
ruledefs/bootperc.js
palettes/bootperc.jcc
rules_java/bootperc.java
rules/bootperc.jc
Added Bootperc to the Rule and Rule program drop-down
lists in index.html.
Added a new patterns/zero.jcp, an all zero pattern to be used by
rules such as Forest which like to start with all zeroes. I
suppose it could be done by requesting a random seed of all
planes with zero density, but that's a little obscure for lots
of people. It also allows clearing out earlier map contents
from previous runs in a show before starting a new rule which
wishes to set up a random seed with zeroes or a texture in other
planes.
Added a demo of Bootperc to shows/demo.jss.
2017 June 13
Rebuilt the development kit to include Bootperc and its support
files.
2017 June 17
Added Langton's Ant as ruledefs/lant.js, rules_java.lant.java,
rules/lant.jc, and palettes/lant.jcc. I added the JavaScript
and .jc rules to index.html.
2017 June 21
Implemented Byl's Loop and Chou-Reggia Loop rules in:
ruledefs/byl.js
choureg.js
rules_java/byl.java
choureg.java
rules/byl.jc
choureg.jc
patterns/byl.jcp
choureg.jcp
palettes/byl.jcc
choureg.jcc
These are loop-based replicators which are simpler and replicate
in fewer generations than the Langton rule.
2017 June 22
Remade the patterns/langton.jcp pattern to centre the initial
replicator better so it runs longer before wrapping around the
edges.
Added a patterns/blank.jcp pattern for rules which wish to start
with an all zero map.
2017 June 23
Installed preliminary versions of Evoloops support in:
ruledefs/evoloops.js -- Main rule
evoloopsab.js -- Abiogenesis experiment
evaluators/vonn4.js
vonn4ab.js -- For abiogenesis: random stimulus
patterns/evoloops.jcp -- From 18-2.img
palettes/evoloops.jcc
Evoloops is developed in Tools/evoloops, with CelLab components
in its cellab subdirectory.
Installed the vonpar4.js rule in ruledefs. This is a von
Neumann parity rule that looks at 4 bits of state from the cell
and neighbours, analogous to vonpar.js which looks at 3 bits of
state. Its main purpose is to illustrate the use of a 20 bit
index auxiliary lookup table and its generation within a rule
program in a simple rule where the rule computation doesn't
obscure the mechanics of working with the auxiliary lookup
table.
2017 June 24
Added commands to Tools/prodsync to automatically generate the
webca/index_640.html double-wide simulator page from index.html
right after the build number is patched into it. This means
there will be no extra effort needed to maintain this page as
index.html is updated.
Deleted webca/bindex.html. With the automatic generation of
index_640.html, it is no longer required.
Installed Sexyloop and support files in:
ruledefs/sexyloopf.js
sexyloopm1.js
sexyloopm2.js
patterns/sexyloopf.jcp
sexyloopf_640.jcp -- Pattern for double-wide sim
sexyloopm.jcp
palettes/sexyloop.jcc
I only added SexyloopF to the drop-down list for rule programs
in index.html; the others can be accessed by explicit links
from the manual.
2017 June 25
Installed the Abelian sandpile model in:
evaluators/sand.js
ruledefs/sand.js
rules_java/sand.java
rules/sand.jc
palettes/sand.jcc
To do:
Another interesting rule we might want to promote is
clowneat.jc, which uses the randnabe() evaluator to cause
diffusion on an arbitrary 255 colour map image. I may try to
find a more interesting image, and aspect correct it for square
pixels, which clown.jcp is not. It also dissolves into a gas if
used with the randswap() evaluator.
Need to review which operations will stop a running simulation:
loading a new rule, for example, should stop the simulation.
Many of the dialogues will want to stop the simulation until
they're applied or cancelled.
Rule name display.
Possibly allow uncompressed ASCII rule definitions to permit
dumping randomly discovered rules. Format would be:
Rule1\r\n
<65536 hex bytes>
and we could have an external Perl program to compress them
as we do for patterns.
Procedural patterns: file composed of Canvas 2D context
draw commands. Use pixel colours to represent states.