Skip to content

Instantly share code, notes, and snippets.

@Sgeo
Created August 9, 2019 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sgeo/ead48728917153cb8fe2c2c2221f2e75 to your computer and use it in GitHub Desktop.
Save Sgeo/ead48728917153cb8fe2c2c2221f2e75 to your computer and use it in GitHub Desktop.
Source code for Langton's loops CA in MCell
/* DNA.cpp
*
* This automata was designed by Christopher G. Langton at the University
* of Michigan, and is described in his article "Self-Reproduction in
* Cellular Automata", published in the book "Cellular Automata" in 1984.
*
* As described in the above article, this automata is "realistic" and
* "non-trivial", in the following ways:
*
* The reproduction is not simply due to the particular rules used in
* the automata. Many automata can reproduce patterns, but such
* behavior is a simple mathematical property of the rules, and is
* not based on the starting pattern. In this automata, the correct
* starting pattern is essential, otherwise nothing interesting happens.
* True, the rules are VERY convenient for this pattern, but the rules
* themselves do not make the reproduction occur. It is the rules
* acting on this special pattern which enables reproduction (just
* like our own universe!)
*
* Like real organisms, this pattern contains "DNA" which directs the
* reproduction. The "DNA" is processed in two ways, by replicating
* it and by transcribing it. This is necessary for "true" reproduction.
*
* Like bacteria, the reproduction doesn't simply create another copy
* of the starting pattern. It creates two identical copies of
* itself, thus both the parent and the child can continue to make
* new copies of themselves.
*
* There are two questions I have about this automata:
*
* The first one is whether larger patterns can be made with these rules
* which can also reproduce, and whether or not there are any interesting
* "mutations" of the DNA in such patterns to make other interesting things.
* It seems to me that it should be possible to "double" the size of the
* pattern, for example.
*
* The second one is whether a simple change to the rules will allow the
* pattern to run as it does now, EXCEPT that when the pattern "dies"
* because of overcrowding, it would totally disappear, so that another
* copy of the pattern could reuse its space. This would me more interesting.
*
* I hope you enjoy watching this run! If you can answer either of the
* above questions, please let me know.
* - David I. Bell -
* dbell@pdact.pd.necisa.oz.au
*/
#include "stdafx.h"
#define STATES 8
#define STATESIZE (STATES * STATES * STATES * STATES * STATES)
#define STATEINDEX(a,b,c,d,e) \
(((((a) * STATES + (b)) * STATES + (c)) * STATES + (d)) * STATES + (e))
/*
* The rules for the automata: The automata is run on a square grid, with
* a neighborhood of the nearest four orthagonal cells (left, right, up,
* and down). Each cell can be in one of 8 states, numbered from 0 to 7.
* State 0 is the "empty" or "off" state (and is the same as blanks).
* In the following table, the entries are in the following format:
* "cwxyz n".
* Here c is the old state of the current cell, w, x, y, and z are the
* states of the four orthagonal neighbors of the current cell in clockwise
* order, and n is the new state of the current cell. Each rule is used
* for all four starting points of the four orthagonal cells. For example,
* the rule "01725 5" means that a cell in state 0, surrounded by cells
* in states 1, 7, 2, and 5, in that clockwise order, changes to state 5.
* For all rules not given in this table, the cell changes to state 0.
*/
static char *rules[] = {
"00001 2",
"00006 3",
"00007 1",
"00011 2",
"00012 2",
"00013 2",
"00021 2",
"00026 2",
"00027 2",
"00052 5",
"00062 2",
"00072 2",
"00102 2",
"00212 5",
"00232 2",
"00522 2",
"01232 1",
"01242 1",
"01252 5",
"01262 1",
"01272 1",
"01275 1",
"01422 1",
"01432 1",
"01442 1",
"01472 1",
"01625 1",
"01722 1",
"01725 5",
"01752 1",
"01762 1",
"01772 1",
"02527 1",
"10001 1",
"10006 1",
"10007 7",
"10011 1",
"10012 1",
"10021 1",
"10024 4",
"10027 7",
"10051 1",
"10101 1",
"10111 1",
"10124 4",
"10127 7",
"10202 6",
"10212 1",
"10221 1",
"10224 4",
"10226 3",
"10227 7",
"10232 7",
"10242 4",
"10262 6",
"10264 4",
"10267 7",
"10272 7",
"10542 7",
"11112 1",
"11122 1",
"11124 4",
"11125 1",
"11126 1",
"11127 7",
"11152 2",
"11212 1",
"11222 1",
"11224 4",
"11225 1",
"11227 7",
"11232 1",
"11242 4",
"11262 1",
"11272 7",
"11322 1",
"12224 4",
"12227 7",
"12243 4",
"12254 7",
"12324 4",
"12327 7",
"12425 5",
"12426 7",
"12527 5",
"20001 2",
"20002 2",
"20004 2",
"20007 1",
"20012 2",
"20015 2",
"20021 2",
"20022 2",
"20023 2",
"20024 2",
"20026 2",
"20027 2",
"20032 6",
"20042 3",
"20051 7",
"20052 2",
"20057 5",
"20072 2",
"20102 2",
"20112 2",
"20122 2",
"20142 2",
"20172 2",
"20202 2",
"20203 2",
"20205 2",
"20207 3",
"20212 2",
"20215 2",
"20221 2",
"20222 2",
"20227 2",
"20232 1",
"20242 2",
"20245 2",
"20255 2",
"20262 2",
"20272 2",
"20312 2",
"20321 6",
"20322 6",
"20342 2",
"20422 2",
"20512 2",
"20521 2",
"20522 2",
"20552 1",
"20572 5",
"20622 2",
"20672 2",
"20712 2",
"20722 2",
"20742 2",
"20772 2",
"21122 2",
"21126 1",
"21222 2",
"21224 2",
"21226 2",
"21227 2",
"21422 2",
"21522 2",
"21622 2",
"21722 2",
"22227 2",
"22244 2",
"22246 2",
"22276 2",
"22277 2",
"30001 3",
"30002 2",
"30004 1",
"30007 6",
"30012 3",
"30042 1",
"30062 2",
"30102 1",
"30251 1",
"40222 1",
"40232 6",
"40322 1",
"50002 2",
"50021 5",
"50022 5",
"50023 2",
"50027 2",
"50202 2",
"50212 2",
"50215 2",
"50224 4",
"50272 2",
"51212 2",
"51242 2",
"51272 2",
"60001 1",
"60002 1",
"61212 5",
"61213 1",
"61222 5",
"70007 7",
"70222 1",
"70225 1",
"70232 1",
"70252 5",
NULL
};
static char states[STATESIZE];
/*
* Initialize the states table.
*/
static void initstates()
{
char **rpp;
char *rp;
int c0, c1, c2, c3, c4, dest;
memset(states, '0', STATESIZE);
for (rpp = rules; *rpp; rpp++)
{
rp = *rpp;
c0 = *rp++ - '0';
c1 = *rp++ - '0';
c2 = *rp++ - '0';
c3 = *rp++ - '0';
c4 = *rp++ - '0';
dest = rp[1];
states[STATEINDEX(c0, c1, c2, c3, c4)] = dest;
states[STATEINDEX(c0, c2, c3, c4, c1)] = dest;
states[STATEINDEX(c0, c3, c4, c1, c2)] = dest;
states[STATEINDEX(c0, c4, c1, c2, c3)] = dest;
}
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//
// Calculate the new state of the 'Me' cell.
int __declspec(dllexport) __stdcall CARule(int Generation,int col,int row,
int NW, int N, int NE,
int W, int Me, int E,
int SW, int S, int SE)
{
return states[STATEINDEX(Me, N, E, S, W)] - '0';
}
//
// Setup the rule.
// The function is called immediatelly after this rule is selected in MCell.
void __declspec(dllexport) __stdcall CASetup(int* RuleType, int* CountOfColors, char* ColorPalette, char* Misc)
{
*RuleType = 2; // 1 - 1D, 2 - 2D
*CountOfColors = 8; // count of states, 0..n-1
strcpy(ColorPalette, "8 colors"); // optional color palette specification
strcpy(Misc, ""); // optional extra parameters; none supported at the moment
initstates(); // initialize states array
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment