<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
[[TiddlyLife]] is a TiddlyWiki-enabled javascript version of Conway's "Game of Life" cellular automata simulator.  It provides a "life matrix" on which to place cells, run the simulation, and observe the results.
!!!Example: GliderDance
<<life cellsize:.8em tid:GliderDance>>
!!!Try Your Own
<<life cellsize:.8em>>
{{{
-------------------OO---------
--------------------OO--------
-------------------O----------
------------------------------
--------------------------O---
--------------------------O-O-
--------------------------OO--
------------------------------
------OO----------------------
-----OO-----------------------
-------O----------------------
------------------------------
-------------------------O----
--------------------------OO--
-------------------------OO---
----OOO-----------------------
------O-----------------------
-----O------------------------
------------------------------
-----------O-O----------------
-----------OO-----------------
------------O-----------------
------------------------------
--------------------OOO-------
--------------------O---------
---------------------O--------
------------------------------
-----------O------------------
------------O-----------------
----------OOO-----------------
}}}
{{{
--------------------------------------
------------------------O-------------
----------------------O-O-------------
------------OO------OO------------OO--
-----------O---O----OO------------OO--
OO--------O-----O---OO----------------
OO--------O---O-OO----O-O-------------
----------O-----O-------O-------------
-----------O---O----------------------
------------OO------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
--------------------------------------
-------------------------------------#
-------------------------------------#
-----------------------------------###
}}}
digital automata
TiddyLife
/***
|Name|StyleSheetShortcuts|
|Source|http://www.TiddlyTools.com/#StyleSheetShortcuts|
|Version||
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|CSS|
|Description|'convenience' classes for common formatting, alignment, boxes, tables, etc.|

These 'style tweaks' can be easily included in other stylesheet tiddler so they can share a baseline look-and-feel that can then be customized to create a wide variety of 'flavors'.
***/
/*{{{*/

/* text alignments */
.left
	{ display:block;text-align:left; }
.center
	{ display:block;text-align:center; }
.center table
	{ margin:auto !important; }
.right	
	{ display:block;text-align:right; }
.justify
	{ display:block;text-align:justify; }
.indent
	{ display:block;margin:0;padding:0;border:0;margin-left:2em; }
.floatleft
	{ float:left; }
.floatright
	{ float:right; }
.valignTop, .valignTop table, .valignTop tbody, .valignTop th, .valignTop tr, .valignTop td
	{ vertical-align:top; }
.valignBottom, .valignBottom table, .valignBottom tbody, .valignBottom th, .valignBottom tr, .valignBottom td
	{ vertical-align:bottom; }
.clear
	{ clear:both; }
.wrap
	{ white-space:normal; }
.nowrap
	{ white-space:nowrap; }
.hidden
	{ display:none; }
.show
	{ display:inline !important; }
.span
	{ display:span; }
.block
	{ display:block; }
.relative
	{ position:relative; }
.absolute
	{ position:absolute; }

/* font sizes */
.big
	{ font-size:14pt;line-height:120% }
.medium
	{ font-size:12pt;line-height:120% }
.normal
	{ font-size:9pt;line-height:120% }
.small
	{ font-size:8pt;line-height:120% }
.fine
	{ font-size:7pt;line-height:120% }
.tiny
	{ font-size:6pt;line-height:120% }
.larger
	{ font-size:120%; }
.smaller
	{ font-size:80%; }

/* font styles */
.bold
	{ font-weight:bold; }
.italic
	{ font-style:italic; }
.underline
	{ text-decoration:underline; }

/* plain list items (no bullets or indent) */
.nobullets li { list-style-type: none; margin-left:-2em; }

/* vertical tabsets - courtesy of Tobias Beer */
.vTabs .tabset {float:left;display:block;padding:0px;margin-top:.5em;min-width:20%;}
.vTabs .tabset .tab {display:block;text-align:right;padding:2px 3px 2px 7px; margin:0 1px 1px 0;}
.vTabs .tabContents {margin-left:20%;max-width:80%;padding:5px;}
.vTabs .tabContents .tabContents {border:none; background:transparent;}

/* multi-column tiddler content (not supported in Internet Explorer) */
.twocolumns { display:block;
	-moz-column-count:2; -moz-column-gap:1em; -moz-column-width:50%; /* FireFox */
	-webkit-column-count:2; -webkit-column-gap:1em; -webkit-column-width:50%; /* Safari */
	column-count:2; column-gap:1em; column-width:50%; /* Opera */
}
.threecolumns { display:block;
	-moz-column-count:3; -moz-column-gap:1em; -moz-column-width:33%; /* FireFox */
	-webkit-column-count:3; -webkit-column-gap:1em; -webkit-column-width:33%; /* Safari */
	column-count:3; column-gap:1em; column-width:33%; /* Opera */
}
.fourcolumns { display:block;
	-moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%; /* FireFox */
	-webkit-column-count:4; -webkit-column-gap:1em; -webkit-column-width:25%; /* Safari */
	column-count:4; column-gap:1em; column-width:25%; /* Opera */
}

/* page breaks */
.breakbefore { page-break-before:always; }
.breakafter { page-break-before:always; } 

/* show/hide browser-specific content for InternetExplorer vs. non-IE ("moz") browsers */
*[class="ieOnly"]
	{ display:none; } /* hide in moz (uses CSS selector) */
* html .mozOnly, *:first-child+html .mozOnly
	{ display: none; } /* hide in IE (uses IE6/IE7 CSS hacks) */

/* borderless tables */
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody
	{ border:0 !important; margin:0 !important; padding:0 !important; }
.widetable, .widetable table
	{ width:100%; }

/* thumbnail images (fixed-sized scaled images) */
.thumbnail img { height:5em !important; }

/* stretchable images (auto-size to fit tiddler) */
.stretch img { width:95%; }

/* grouped content */
.outline
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; }
.menubox
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#fff; color:#000; }
.menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting
	{ color:#009 !important; }
.groupbox
	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#ffe; color:#000; }
.groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting
	{ color:#009 !important; }
.groupbox code
	{ color:#333 !important; }
.borderleft
	{ margin:0;padding:0;border:0;margin-left:1em; border-left:1px dotted; padding-left:.5em; }
.borderright
	{ margin:0;padding:0;border:0;margin-right:1em; border-right:1px dotted; padding-right:.5em; }
.borderbottom
	{ margin:0;padding:1px 0;border:0;border-bottom:1px dotted; margin-bottom:1px; padding-bottom:1px; }
.bordertop
	{ margin:0;padding:0;border:0;border-top:1px dotted; margin-top:1px; padding-top:1px; }

/* scrolled content */
.scrollbars { overflow:auto; }
.height10em { height:10em; }
.height15em { height:15em; }
.height20em { height:20em; }
.height25em { height:25em; }
.height30em { height:30em; }
.height35em { height:35em; }
.height40em { height:40em; }

/* compact form */
.smallform
	{ white-space:nowrap; }
.smallform input, .smallform textarea, .smallform button, .smallform checkbox, .smallform radio, .smallform select
	{ font-size:8pt; }

/* stretchable edit fields and textareas (auto-size to fit tiddler) */
.stretch input { width:99%; }
.stretch textarea { width:99%; }

/* compact input fields (limited to a few characters for entering percentages and other small values) */
.onechar input   { width:1em; }
.twochar input   { width:2em; }
.threechar input { width:3em; }
.fourchar input  { width:4em; }
.fivechar input  { width:5em; }

/* text colors */
.white { color:#fff !important }
.gray  { color:#999 !important }
.black { color:#000 !important }
.red   { color:#f66 !important }
.green { color:#0c0 !important }
.blue  { color:#99f !important }

/* rollover highlighting */
.mouseover 
	{color:[[ColorPalette::TertiaryLight]] !important;}
.mouseover a
	{color:[[ColorPalette::TertiaryLight]] !important;}
.selected .mouseover
	{color:[[ColorPalette::Foreground]] !important;}
.selected .mouseover .button, .selected .mouseover a
	{color:[[ColorPalette::PrimaryDark]] !important;}

/* rollover zoom text */
.zoomover
	{ font-size:80% !important; }
.selected .zoomover
	{ font-size:100% !important; }

/* [[ColorPalette]] text colors */
.Background	{ color:[[ColorPalette::Background]];	 }
.Foreground	{ color:[[ColorPalette::Foreground]];	 }
.PrimaryPale	{ color:[[ColorPalette::PrimaryPale]];	 }
.PrimaryLight	{ color:[[ColorPalette::PrimaryLight]];	 }
.PrimaryMid	{ color:[[ColorPalette::PrimaryMid]];	 }
.PrimaryDark	{ color:[[ColorPalette::PrimaryDark]];	 }
.SecondaryPale	{ color:[[ColorPalette::SecondaryPale]]; }
.SecondaryLight	{ color:[[ColorPalette::SecondaryLight]];}
.SecondaryMid	{ color:[[ColorPalette::SecondaryMid]];	 }
.SecondaryDark	{ color:[[ColorPalette::SecondaryDark]]; }
.TertiaryPale	{ color:[[ColorPalette::TertiaryPale]];	 }
.TertiaryLight	{ color:[[ColorPalette::TertiaryLight]]; }
.TertiaryMid	{ color:[[ColorPalette::TertiaryMid]];	 }
.TertiaryDark	{ color:[[ColorPalette::TertiaryDark]];	 }
.Error		{ color:[[ColorPalette::Error]];	 }

/* [[ColorPalette]] background colors */
.BGBackground	  { background-color:[[ColorPalette::Background]];	}
.BGForeground	  { background-color:[[ColorPalette::Foreground]];	}
.BGPrimaryPale	  { background-color:[[ColorPalette::PrimaryPale]];	}
.BGPrimaryLight	  { background-color:[[ColorPalette::PrimaryLight]];	}
.BGPrimaryMid	  { background-color:[[ColorPalette::PrimaryMid]];	}
.BGPrimaryDark	  { background-color:[[ColorPalette::PrimaryDark]];	}
.BGSecondaryPale  { background-color:[[ColorPalette::SecondaryPale]]; 	}
.BGSecondaryLight { background-color:[[ColorPalette::SecondaryLight]];	}
.BGSecondaryMid	  { background-color:[[ColorPalette::SecondaryMid]];	}
.BGSecondaryDark  { background-color:[[ColorPalette::SecondaryDark]]; 	}
.BGTertiaryPale	  { background-color:[[ColorPalette::TertiaryPale]];	}
.BGTertiaryLight  { background-color:[[ColorPalette::TertiaryLight]]; 	}
.BGTertiaryMid	  { background-color:[[ColorPalette::TertiaryMid]];	}
.BGTertiaryDark	  { background-color:[[ColorPalette::TertiaryDark]];	}
.BGError	  { background-color:[[ColorPalette::Error]];	 	}
/*}}}*/
/***
|Name|TiddlyLifePlugin|
|Source|http://www.TiddlyTools.com/#TiddlyLifePlugin|
|Documentation|http://www.TiddlyTools.com/#TiddlyLifePlugin|
|Version|1.6.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Cellular Automata: Conway's "Game of Life"|
!!!!!Documentation
<<<
[[TiddlyLife]] is a TiddlyWiki-enabled javascript version of Conway's "Game of Life" cellular automata simulator.  It provides a "life matrix" on which to place cells, run the simulation, and observe the results.  The speed of the simulation is related to the total size of the matrix (i.e., rows X cols): the larger the matrix, the longer it takes to compute each 'generation' of cells.

You can set the number of rows and columns in the matrix, as well as the size of each cell and the color of the cells, grid, and background.  You can use the mouse to click/drag over the grid to add/delete cells (hold shift to add "walls").  The current life matrix can be saved as text in a tiddler and then reloaded later from a popup list of tiddlers tagged with<<tag tiddlyLife>>

Please see Wikipedia for an overview of [[Conway's "Game of Life"|http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life]].
<<<
!!!!!Syntax
<<<
{{{
<<life	cellcolor:... gridcolor:... bgcolor:... wallcolor:...
	cellsize:... gridwidth:... delay:... limit:... stability:...
	autostart nomenu nostats noedit width:... height:... tid:...>>
}}}
where all parameters are optional (default values are shown in parentheses):
*''cellcolor:'' (//green//), ''gridcolor:'' (//#111//), ''bgcolor:'' (//black//) and ''wallcolor:'' (//gray//)<br>are CSS color names or RGB values (e.g.: "black", "blue",  "#fff", "#9af", etc.)
*''cellsize:'' (//1em//), and ''gridwidth:'' (//1px//)<br>are CSS dimensions, including units (e.g., px,em,cm,in)
*''delay:'' (//0//)<br>delay time (in msec) between simulation ticks (a larger number results in a slower simulation, but also leaves more CPU cycles available for other processes)
*''limit:'' (//10000//)<br>automatically stop stimulation after the indicated number of generations (use 0 for no limit)
*''stability:'' (//500//)<br>automatically stop simulation if population count remains stable for the indicated number of generations (use 0 for no limit)
*''autostart'' (//keyword//)<br>when present, causes the simulation to begin running as soon as the macro is rendered
*''nomenu'' (//keyword//)<br>when present, suppresses display of command menu (use with ''autostart'')
*''nostats'' (//keyword//)<br>when present, suppresses display of the current matrix statistics (generation #, population count/min/avg/max, birthrate/deathrate, average age)
*''noedit'' (//keyword//)<br>when present, prevent hand editing of cells in the matrix.  Instead, clicking on the matrix starts/stops the simulation (useful with ''nomenu'' and ''autostart'')
*''width:'' (//30//) and ''height:'' (//30//)<br>are dimensions for an empty life matrix
*''tid:'' (//no default//)<br>specifies a tiddler containing a saved life matrix definition.  note: when using a saved matrix, the width/height are determined by the stored definition and any width/height macro parameters that are present will be ignored.
<<<
!!!!!Examples
<<<
"Multi-cellular organisms" can be constructed by arranging blocks in specific patterns that exhibit emergent behaviors such as movement, symmetry, oscillation and generative abilities.  Two well-known organisms that are [[discussed in the Wikipedia article|http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life]] are ''//gliders//'' and ''//Gosper's glider gun//'':

[[GliderDance]]: many small moving organisms just missing each other!
{{{<<life cellsize:.8em tid:GliderDance>>}}}
<<life cellsize:.8em tid:GliderDance>>
[[GliderGun]]: generates a stream of gliders that hits a wall
{{{<<life cellsize:.6em tid:GliderGun>>}}}
<<life cellsize:.6em tid:GliderGun>>
... and here's an ''empty life matrix'' for you to play with:
{{{<<life>>}}}
<<life>>
<<<
!!!!!Revisions
<<<
2008.10.11 [1.6.5] added 'step' command.  Also, for performance, removed birth/death stats and don't display average age (but //do// calculate it)
2008.10.10 [1.6.0] added birthrate, deathrate, and average age to statistics
2008.10.09 [1.5.0] use //named// params.  changed matrix values: 0==empty, >0==alive, <0==wall, where value=generation # in which cell was created
2008.10.08 [1.4.0] added 'stability' and 'limit' options (replaces 'autostop' checkbox)
2008.10.08 [1.3.0] added optional 'autostart', 'nomenu' and 'nostats' macro params
2008.10.07 [1.2.1] fixed update handling so multiple timers will no longer be created
2008.10.06 [1.2.0] added support for walls (unchanging dead cells) using dead="-", alive="O", wall="#"
2008.10.06 [1.1.1] redraw optimization: 300% speed improvement by setting CSS only when cell state *changes*
2008.10.05 [1.1.0] drag to draw (set/clear) multiple cells, new option controls (rows,cols,cellsize,delay,autostop), popup list for opening saved matrix
2008.10.04 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TiddlyLifePlugin= {major: 1, minor: 6, revision: 5, date: new Date(2008,10,11)};
config.shadowTiddlers.TiddlyLife="<<life>>";
config.macros.life={
//}}}
// // DEFAULTS
//{{{
	cellcolor:	"green",
	cellsize:	"1em",
	gridcolor:	"#111",
	gridwidth:	"1px",
	bgcolor:	"black",
	wallcolor:	"gray",
	width:		30,
	height:		30,
	stability: 	300,
	limit:		5000,
	delay:		0,
//}}}
// // TRANSLATE
//{{{
	lifeTag:	"tiddlyLife",
	titlePrompt:	"Enter a new tiddler title",
	openErr:	"Could not open '%0'",
	limitMsg:	"stopped: completed %0 generations",
	stableMsg:	"stopped: no growth for %0 generations",
	cellEditTip:	"CLICK=set/clear, SHIFT-CLICK=set wall",
	noEditTip:	"CLICK=start/stop simulation",
	startLabel:	"start",
	stopLabel:	"<b>STOP</b>",
	stats:		"gen: <b>%0</b> pop: <b>%1</b> min: <b>%2</b> avg: <b>%3</b> max: <b>%4</b> %5",
	cmds:		"<a href='#' title='start/stop simulation'\
				onclick='return config.macros.life.toggle(\"%0\")'>%1</a> \
			 | <a href='#' title='advance simulation by one generation'\
				onclick='return config.macros.life.step(\"%0\")'>step</a> \
			 | <a href='#' title='reload the starting life matrix'\
				onclick='return config.macros.life.reset(\"%0\")'>reset</a> \
			 | <a href='#' title='clear the life matrix'\
				onclick='return config.macros.life.clear(\"%0\")'>clear</a> \
			 | <a href='#' title='load a life matrix from a tiddler'\
				onclick='return config.macros.life.open(this,event,\"%0\")'>open</a> \
			 | <a href='#' title='save the current life matrix to a tiddler'\
				onclick='return config.macros.life.save(\"%0\")'>save</a> \
			 | <a href='#' title='change simulation option settings'\
				onclick='var s=this.nextSibling.style; var show=s.display==\"none\"; \
					s.display=show?\"block\":\"none\"; \
					return false;'>options</a><span style='display:none'>%2</span>",
	opts:		"delay:<input type='text' title='delay between generations (msec)' \
				value='%1' style='width:4em;font-size:90%;text-align:center;'>\
			 limit:<input type='text' title='automatically stop after N generations (0=no limit)' \
				value='%2' style='width:4em;font-size:90%;text-align:center;'>\
			 stability:<input type='text' title='stop if population count is stable for N generations (0=no limit)'\
				value='%3' style='width:4em;font-size:90%;text-align:center;'><br>\
			 rows:<input type='text' title='matrix height' \
				value='%4' style='width:3em;font-size:90%;text-align:center;'>\
			 cols:<input type='text' title='matrix width' \
				value='%5' style='width:3em;font-size:90%;text-align:center;'>\
			 cells:<input type='text' title='cellsize' \
				value='%6' style='width:3em;font-size:90%;text-align:center;'>\
			 <input type='button' value='OK' style='font-size:90%;' \
				title='change the life matrix dimensions' \
				onclick='var ins=this.parentNode.getElementsByTagName(\"input\"); \
					var t=ins[0].value; var l=ins[1].value; var a=ins[2].value; \
					var h=ins[3].value; var w=ins[4].value; var s=ins[5].value; \
					return config.macros.life.setoptions(\"%0\",w,h,s,t,a,l)'>",
	msgfmt: 	"<br><span title='use \"options\" command to change autostop settings' \
			onclick='this.style.display=\"none\"' \
			style='display:block;position:absolute;padding:0 .5em;cursor:pointer; \
			margin:.5em;color:%1;background-color:%2;border:1px solid %1'>%3</span>",

//}}}
// // GENERAL UTILITIES
//{{{
	empty: function(w,h) { // generate an empty matrix
		var m=[]; for (var r=0; r<h; r++) { m[r]=[]; for (var c=0; c<w; c++) m[r][c]=0; } return m;
	},
	paste: function(row,col,m1,m2) { // copy one matrix into another
		for (var r=row; r<m1.length && r<m2.length; r++)
			for (var c=col; c<m1[r].length && c<m2[r].length; c++)
				m2[r][c]=m1[r][c];
	},
	zeroPad: function(v,m) { // formatting for population stats
		var t=("0000"+v.toString());
		return t.substr(t.length-Math.max(m.toString().length,v.toString().length));
	},
	getValue: function(s) { // cell value from stored matrix symbol
		return s=='O'?1:s=='#'?-1:0;
	},
	getSymbol: function(v) { // stored matrix symbol from cell value
		return v>0?'O':v<0?'#':'-';
	},
	getColor: function(v,d) { // color from cell value
		return v>0?d.cellcolor:v<0?d.wallcolor:'';
	},
	getAge: function(v,d) { // age of a cell or wall
		return v?(d.gen||1)-Math.abs(v):0;
	},
	isAlive: function(v) { // 0 if dead, 1 if alive
		return v>0;
	},
	isWall: function(v) { // 1 if cell is a wall
		return v<0;
	},
	isAncient: function(v,d) { // true if cell age is more than ten times the average age
		return d.avgage>0 && this.getAge(v,d)>10*d.avgage;
	},
//}}}
// // MACRO HANDLER
//{{{
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var autostart	=params.contains("autostart");
		var nomenu	=params.contains("nomenu");
		var nostats	=params.contains("nostats");
		var noedit	=params.contains("noedit");
		params = paramString.parseParams("anon",null,true,false,false);
		var cellcolor	=getParam(params,"cellcolor",this.cellcolor);
		var wallcolor	=getParam(params,"wallcolor",this.wallcolor);
		var cellsize	=getParam(params,"cellsize",this.cellsize);
		var gridcolor	=getParam(params,"gridcolor",this.gridcolor);
		var gridwidth	=getParam(params,"gridwidth",this.gridwidth);
		var bgcolor	=getParam(params,"bgcolor",this.bgcolor);
		var tid		=getParam(params,"tid",this.tid);
		var w		=getParam(params,"rows",this.width);
		var h		=getParam(params,"cols",this.height);
		var delay	=getParam(params,"delay",this.delay);
		var stability	=getParam(params,"stability",this.stability);
		var limit	=getParam(params,"limit",this.limit);
		var m=this.load(tid); if (!m) var m=this.empty(w,h);
		var id="tiddlyLife_"+new Date().getTime()+Math.random();
		var e=createTiddlyElement(place,"span",id,"tiddlyLife");
		e.data={w:w, h:h, tid:tid, matrix:m, gen:0, stopped:!autostart,
			gencount:0, stable:0, total:0, birthrate:0, deathrate:0, age:0, 
			cellcolor:cellcolor, wallcolor:wallcolor, gridcolor:gridcolor, bgcolor:bgcolor,
			cellsize:cellsize, gridwidth:gridwidth, delay:delay, stability:stability, limit:limit,
			nostats:nostats, nomenu:nomenu, noedit:noedit };
		this.draw(id); if (autostart) this.go(id);
	},
//}}}
// // COMMAND HANDLERS
//{{{
	toggle: function(id) { // toggle simulation
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		if (d.stopped) this.go(id); else this.stop(id);
		return false;
	},
	go: function(id) { // start simulation and set command text
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var b=e.getElementsByTagName("a")[0]; if (b) b.innerHTML=this.stopLabel;
		d.stopped=false; d.stable=0; d.gencount=0; clearTimeout(d.timer); this.refresh(id);
		return false;
	},
	stop: function(id) { // stop simulation and set command text
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var b=e.getElementsByTagName("a")[0]; if (b) b.innerHTML=this.startLabel;
		d.stopped=true; clearTimeout(d.timer);		
		return false;
	},
	reset: function(id) { // reload initial matrix
		var e=document.getElementById(id); if (!e) return; var d=e.data;
		var m=this.load(d.tid); if (!m) var m=this.empty(d.w,d.h);
		this.stop(id); d.matrix=m; d.gen=0; this.draw(id);
		return false;
	},
	clear: function(id) { // load empty matrix
		var e=document.getElementById(id); if (!e) return; var d=e.data;
		var tid=d.tid; d.tid=""; this.reset(id); d.tid=tid;
		return false;
	},
	setoptions: function(id,w,h,s,t,a,l) { // options: width,height,cellsize,delaytime,autostop,limit
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		clearTimeout(d.timer); // stop simulation while changing matrix content
		d.w=w; d.h=h; d.stability=a; d.limit=l; d.cellsize=s; d.delay=t;
		var m2=this.empty(w,h); this.paste(0,0,m,m2); d.matrix=m2; this.draw(id);
		d.min=Math.min(d.min,d.count); d.max=Math.max(d.max,d.count);
		if (!d.stopped) d.timer=setTimeout('config.macros.life.refresh("'+id+'")',d.delay);
		return false;
	},
//}}}
// // I/O HANDLERS
//{{{
	load: function(tid) { // read tiddler into matrix
		var t=store.getTiddlerText(tid); if (!t) return;
		var lines=t.split("\n"); var m=[];
		if (lines[0]=="{{{") lines.shift();
		if (lines[lines.length-1]=="}}}") lines.pop();
		for (var r=0; r<lines.length; r++) { m[r]=[];
			for (var c=0; c<lines[r].length; c++) m[r].push(this.getValue(lines[r].substr(c,1)));
		}
		return m;
	},
	save: function(id) { // write matrix to tiddler
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var tid=d.tid; var msg=config.messages.overwriteWarning.format([tid]);
		while (!tid||!tid.length ||(store.tiddlerExists(tid)&&!confirm(msg)))
			{ tid=prompt(this.titlePrompt,tid); if (!tid||!tid.length) return false; }
		d.tid=tid;
		var out=[];
		out.push('{{{');
		for (var r=0; r<m.length; r++) { var row='';
			for (var c=0; c<m[r].length; c++) row+=this.getSymbol(m[r][c]);
			out.push(row);
		}
		out.push('}}}');
		var t=store.getTiddler(tid);
		var txt=out.join('\n');
		var who=t&&config.options.chkForceMinorUpdate?t.modifier:config.options.txtUserName;
		var when=t&&config.options.chkForceMinorUpdate?t.modified:new Date();
		var tags=t?t.tags:[]; tags.pushUnique(this.lifeTag);
		var fields=t?t.fields:{};
		store.saveTiddler(tid,tid,txt,who,when,tags,fields);
		story.displayTiddler(null,tid); story.refreshTiddler(tid,null,true);
		return false;
	},
	open: function(here,event,id) { // select from a list of saved matrix tiddlers
		var p=Popup.create(here); if (!p) return false;
		p.style.padding="2px .5em";
		var tids=store.getTaggedTiddlers(this.lifeTag);
		for (var t=0; t<tids.length; t++) {
			var b=createTiddlyButton(createTiddlyElement(p,"li"),tids[t].title,tids[t].title,
				function() {
					var cml=config.macros.life;
					var id=this.getAttribute("id");
					var e=document.getElementById(id); if (!e) return false; var d=e.data;
					var tid=this.getAttribute("tid");
					var m=cml.load(tid);
					if (!m) { displayMessage(this.openErr.format([tid])); return false; }
					cml.stop(id); d.tid=tid; d.matrix=m; d.gen=0; cml.draw(id);
					return false;
				});
			b.setAttribute("id",id);
			b.setAttribute("tid",tids[t].title);
		}
		Popup.show();
		event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();
		return false;
	},
//}}}
// // EDIT HANDLERS
//{{{
	mousedown: function(here,ev,id,r,c) { // start manual edit
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		d.savedstop=d.stopped; this.stop(id); d.draw=!this.isAlive(m[r][c])?(d.gen||1):0;
		return this.setcell(here,id,r,c,ev&&ev.shiftKey?-(d.gen||1):d.draw);
	},
	mouseover: function(here,ev,id,r,c) { // drag edit
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		if (d.draw!==undefined) this.setcell(here,id,r,c,ev&&ev.shiftKey?-(d.gen||1):d.draw);
		return false;
	},
	mouseup: function(here,ev,id,r,c) { // end manual edit
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		if (d.savedstop!==undefined) d.stopped=d.savedstop; if (!d.stopped) this.go(id);
		d.draw=undefined; d.savedstop=undefined;
		return false;
	},
	setcell: function(here,id,r,c,v) { // set cell content and revise stats display
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		if (m[r][c]==v) return;
		if (this.isAlive(m[r][c]) && !this.isAlive(v)) { d.count--; d.min=Math.min(d.min,d.count); }
		if (!this.isAlive(m[r][c]) && this.isAlive(v)) { d.count++; d.max=Math.max(d.max,d.count); }
		m[r][c]=v; here.style.background=this.getColor(v,d);
		this.showstats(id,'');
		return false;
	},
//}}}
// // RENDER
//{{{
	draw: function(id) { // render entire tiddlyLife container (menu, stats, and table)
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var out=[]; var count=0; var maxwidth=0;
		var style="border:%0 solid %1;background:%2;height:%3 !important;width:%3; !important";
		var onmousedown=d.noedit?"":"return config.macros.life.mousedown(this,event,'%4',%5,%6);";
		var onmouseover=d.noedit?"":"return config.macros.life.mouseover(this,event,'%4',%5,%6);";
		var onmouseup  =d.noedit?"":"return config.macros.life.mouseup(this,event,'%4',%5,%6);";
		var onclick    =d.noedit?"return config.macros.life.toggle('%4');":"";
		var tip="[%7,%8] "+(d.noedit?this.noEditTip:this.cellEditTip);
		var cell='<td style="margin:0;padding:0;'+style +'" title="'+tip+'" onclick="'+onclick
			+'" onmousedown="'+onmousedown+'" onmouseover="'+onmouseover+'" onmouseup="'+onmouseup+'"></td>';
		out.push('<table style="table-layout:fixed;border-collapse:collapse;'
			+'margin:0;padding:0;border:0;background-color:'+d.bgcolor+'">');
		for (var r=0; r<m.length; r++) {
			if (m[r].length>maxwidth) maxwidth=m[r].length;
			out.push('<tr style="margin:0;padding:0;border:0;">');
			for (var c=0; c<m[r].length; c++) {
				out.push(cell.format([d.gridwidth,d.gridcolor,this.getColor(m[r][c],d),
					d.cellsize,id,r,c,r+1,c+1]));
				count+=this.isAlive(m[r][c]);
			}
			out.push('</tr>');
		}
		out.push('</table>');
		d.count=count;
		if (!d.gen) { d.gencount=d.stable=d.total=d.oldest=d.maxage=d.avgage=0; d.min=d.max=d.avg=count; }
		var hdr=[];
		if (!d.nomenu) hdr.push(this.cmds.format([id,d.stopped?this.startLabel:this.stopLabel,
			this.opts.format([id,d.delay,d.limit,d.stability,m.length,maxwidth,d.cellsize])]));
		if (!d.nostats) hdr.push('<div style="font-size:90%">'
			+this.stats.format([d.gen,d.count,d.min,d.avg,d.max])+'</div>');
		e.innerHTML=hdr.join('')+out.join('');
		return false;
	},
//}}}
// // RUN SIMULATION
//{{{
	refresh: function(id) { // timer-based refresh cycle
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		this.step(id); if (!d.stopped) d.timer=setTimeout('config.macros.life.refresh("'+id+'")',d.delay);
		return false;
	},
	step: function(id) { // calc new matrix, gather stats and display changes
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		// calculate next generation
		var m2=[]; var count=agecount=agetotal=oldest=0; d.gen++; d.gencount++;
		var table=e.getElementsByTagName("table")[0]; if (!table) return;
		var rows=table.getElementsByTagName("tr");
		for (var r=0; r<m.length; r++) {
			m2[r]=[];
			var cells=rows[r].getElementsByTagName("td");
			for (var c=0; c<m[r].length; c++) {
				var v=this.tick(d.gen,m,r,c); // apply Conway's 23/3 rule
				m2[r].push(v);
				var color=this.getColor(v,d);
				if (cells[c].style.backgroundColor!=color)
					cells[c].style.backgroundColor=color;
				if (this.isAlive(v)) {
					var a=this.getAge(v,d);
					if (!this.isAncient(v,d)) { agecount++; agetotal+=a; }
					oldest=Math.max(oldest,a);
					count++;
				}
			}
		}
		d.matrix=m2; // update matrix
		this.calcstats(id,count,agecount,agetotal,oldest); // calculate statistics
		var msg=this.autostop(id); // autostop if conditions apply
		this.showstats(id,msg); // show statistics and message (if any)
		return false;
	},
	tick: function(gen,m,r,c) { // apply Conway's 23/3 rule
		if (this.isWall(m[r][c])) return m[r][c]; // walls don't change
		var prevrow=r>0?r-1:(m.length-1);
		var nextrow=r<m.length-1?r+1:0;
		var prevcol=c>0?c-1:(m[r].length-1);
		var nextcol=c<m[r].length-1?c+1:0;
		var near=this.isAlive(m[prevrow][prevcol]) + this.isAlive(m[prevrow][c]) + this.isAlive(m[prevrow][nextcol])
			+this.isAlive(m[r][prevcol])       + this.isAlive(m[r][nextcol])
			+this.isAlive(m[nextrow][prevcol]) + this.isAlive(m[nextrow][c]) + this.isAlive(m[nextrow][nextcol]);
		if (!this.isAlive(m[r][c])&&near==3) return gen; // birth
		if (this.isAlive(m[r][c])&&near==2||near==3) return m[r][c]; // stay alive
		return 0; // death
	},
	autostop: function(id) { // autostop if run limit reached or no changes for N generations
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var msg='';
		var limited=d.limit>0 && d.gencount>=d.limit;
		var stabilized=d.stability>0 && d.stable>=d.stability;
		if (limited || stabilized) {
			this.stop(id); 
			msg=stabilized?this.stableMsg.format([d.stability]):this.limitMsg.format([d.limit]);
			msg=this.msgfmt.format([id,d.cellcolor,d.bgcolor,msg]);
		}
		return msg;
	},
	calcstats: function(id,count,agecount,agetotal,oldest) {
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		d.stable+=(count==d.count)?1:-d.stable; // add one or reset to zero
		d.count=count; d.total+=count;
		d.min=Math.min(d.min,count); d.max=Math.max(d.max,count); d.avg=Math.floor(d.total/d.gen);
		d.avgage=agecount?agetotal/agecount:0; d.oldest=oldest; d.maxage=Math.max(d.maxage,oldest);
		return false;
	},
	showstats: function(id,msg) {
		var e=document.getElementById(id); if (!e) return; var d=e.data; var m=d.matrix;
		var stats=e.getElementsByTagName("div")[0];
		if (stats) stats.innerHTML=this.stats.format([d.gen,this.zeroPad(d.count,d.max),d.min,d.avg,d.max,msg]);
		return false;
	}
}
//}}}