Wireworld: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Corrected spacing inconsistency.)
m (→‎{{header|Wren}}: Minor tidy)
(18 intermediate revisions by 14 users not shown)
Line 14: Line 14:


The cell transition rules are this:
The cell transition rules are this:
{| class=wikitable
::{| class=wikitable
|-
|-
! Input State
! Input State
Line 53: Line 53:
While text-only implementations of this task are possible, mapping cells to pixels is advisable if you wish to be able to display large designs. The logic is not significantly more complex.
While text-only implementations of this task are possible, mapping cells to pixels is advisable if you wish to be able to display large designs. The logic is not significantly more complex.
<br><br>
<br><br>

=={{header|11l}}==
{{trans|Python}}

<syntaxhighlight lang="11l">V allstates = ‘Ht. ’
V head = allstates[0]
V tail = allstates[1]
V conductor = allstates[2]
V empty = allstates[3]

V w =
|‘tH.........
. .
...
. .
Ht.. ......’

T WW
[[Char]] world
Int w
Int h
F (world, w, h)
.world = world
.w = w
.h = h

F readfile(f)
V world = f.map(row -> row.rtrim(Array[Char]("\r\n")))
V height = world.len
V width = max(world.map(row -> row.len))
V nonrow = [‘ ’(‘ ’ * width)‘ ’]
V world2 = nonrow [+] world.map(row -> ‘ ’String(row).ljust(@width)‘ ’) [+] nonrow
V world3 = world2.map(row -> Array(row))
R WW(world3, width, height)

F newcell(currentworld, x, y)
V istate = currentworld[y][x]
assert(istate C :allstates, ‘Wireworld cell set to unknown value "#."’.format(istate))
V ostate = :empty
I istate == :head
ostate = :tail
E I istate == :tail
ostate = :conductor
E I istate == :empty
ostate = :empty
E
V n = sum([(-1, -1), (-1, +0), (-1, +1),
(+0, -1), (+0, +1),
(+1, -1), (+1, +0), (+1, +1)].map((dx, dy) -> Int(@currentworld[@y + dy][@x + dx] == :head)))
ostate = I n C 1..2 {:head} E :conductor
R ostate

F nextgen(ww)
V (world, width, height) = ww
V newworld = copy(world)
L(x) 1 .. width
L(y) 1 .. height
newworld[y][x] = newcell(world, x, y)
R WW(newworld, width, height)

F world2string(ww)
R ww.world[1 .< (len)-1].map(row -> (row[1 .< (len)-1]).join(‘’).rtrim((‘ ’, "\t", "\r", "\n"))).join("\n")

V ww = readfile(w.split("\n"))

L(gen) 10
print(("\n#3 ".format(gen))‘’(‘=’ * (ww.w - 4))"\n")
print(world2string(ww))
ww = nextgen(ww)</syntaxhighlight>

{{out}}
<pre style="height:45ex;overflow:scroll">

0 =======

tH.........
. .
...
. .
Ht.. ......

1 =======

.tH........
H .
...
H .
t... ......

2 =======

H.tH.......
t .
...
t .
.H.. ......

3 =======

tH.tH......
. H
...
. .
HtH. ......

4 =======

.tH.tH.....
H t
HHH
H .
t.tH ......

5 =======

H.tH.tH....
t .
ttt
t .
.H.t ......

6 =======

tH.tH.tH...
. H
...
. .
HtH. ......

7 =======

.tH.tH.tH..
H t
HHH
H .
t.tH ......

8 =======

H.tH.tH.tH.
t .
ttt
t .
.H.t ......

9 =======

tH.tH.tH.tH
. H
...
. .
HtH. ......
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
<lang Ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;


procedure Test_Wireworld is
procedure Test_Wireworld is
Line 120: Line 273:
Wireworld (Oscillator);
Wireworld (Oscillator);
end loop;
end loop;
end Test_Wireworld;</lang>
end Test_Wireworld;</syntaxhighlight>
The solution assumes that the border of the board is empty. When transition is performed these cells are not changed. Automation transition is an in-place operation that allocates memory for to keep one row of the board size.
The solution assumes that the border of the board is empty. When transition is performed these cells are not changed. Automation transition is an in-place operation that allocates memory for to keep one row of the board size.
<pre style="height:30ex;overflow:scroll">
<pre style="height:30ex;overflow:scroll">
Line 170: Line 323:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - missing transput function "printf" and non standard associate}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - missing transput function "printf" and non standard associate}}
<lang algol68>CO
<syntaxhighlight lang="algol68">CO
Wireworld implementation.
Wireworld implementation.
CO
CO
Line 291: Line 444:
print ( world2string(ww) );
print ( world2string(ww) );
ww := next gen(ww)
ww := next gen(ww)
OD</lang>
OD</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:45ex;overflow:scroll">
<pre style="height:45ex;overflow:scroll">
Line 369: Line 522:
{{works with|AutoHotkey_L}}
{{works with|AutoHotkey_L}}
{{libheader|GDIP}}
{{libheader|GDIP}}
<lang AutoHotkey>#SingleInstance, Force
<syntaxhighlight lang="autohotkey">#SingleInstance, Force
#NoEnv
#NoEnv
SetBatchLines, -1
SetBatchLines, -1
Line 475: Line 628:
Exit:
Exit:
Gdip_Shutdown(pToken)
Gdip_Shutdown(pToken)
ExitApp</lang>
ExitApp</syntaxhighlight>


=={{header|AutoIt}}==
=={{header|AutoIt}}==


<lang autoit>
<syntaxhighlight lang="autoit">
$ww = ""
$ww = ""
$ww &= "tH........." & @CR
$ww &= "tH........." & @CR
Line 582: Line 735:
WEnd
WEnd
EndFunc ;==>Wireworld
EndFunc ;==>Wireworld
</syntaxhighlight>
</lang>


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
[[Image:wireworld_bbc.gif|right]]
[[Image:wireworld_bbc.gif|right]]
<lang bbcbasic> Size% = 20
<syntaxhighlight lang="bbcbasic"> Size% = 20
DIM P&(Size%-1,Size%-1), Q&(Size%-1,Size%-1)
DIM P&(Size%-1,Size%-1), Q&(Size%-1,Size%-1)
Line 628: Line 781:
SWAP P&(), Q&()
SWAP P&(), Q&()
WAIT 50
WAIT 50
UNTIL FALSE</lang>
UNTIL FALSE</syntaxhighlight>


=={{header|C}}==
=={{header|C}}==
Line 642: Line 795:
Compile with <code>-D_POSIX_C_SOURCE=199309L</code> or greater to make <code>nanosleep</code> visible in <code><time.h></code>.
Compile with <code>-D_POSIX_C_SOURCE=199309L</code> or greater to make <code>nanosleep</code> visible in <code><time.h></code>.


<lang c>/* 2009-09-27 <kaz@kylheku.com> */
<syntaxhighlight lang="c">/* 2009-09-27 <kaz@kylheku.com> */
#define ANIMATE_VT100_POSIX
#define ANIMATE_VT100_POSIX
#include <stdio.h>
#include <stdio.h>
Line 703: Line 856:


return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|C sharp}}==
=={{header|C sharp}}==
Line 713: Line 866:
{{libheader|POSIX}} (for usleep)
{{libheader|POSIX}} (for usleep)


<lang cpp>#include <ggi/ggi.h>
<syntaxhighlight lang="cpp">#include <ggi/ggi.h>
#include <set>
#include <set>
#include <map>
#include <map>
Line 958: Line 1,111:
}
}
std::cout << std::endl;
std::cout << std::endl;
}</lang>
}</syntaxhighlight>


=={{header|Ceylon}}==
=={{header|Ceylon}}==
<lang ceylon>abstract class Cell(shared Character char) of emptyCell | head | tail | conductor {
<syntaxhighlight lang="ceylon">abstract class Cell(shared Character char) of emptyCell | head | tail | conductor {


shared Cell output({Cell*} neighbors) =>
shared Cell output({Cell*} neighbors) =>
Line 1,062: Line 1,215:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==


<lang lisp>(defun electron-neighbors (wireworld row col)
<syntaxhighlight lang="lisp">(defun electron-neighbors (wireworld row col)
(destructuring-bind (rows cols) (array-dimensions wireworld)
(destructuring-bind (rows cols) (array-dimensions wireworld)
(loop for off-row from (max 0 (1- row)) to (min (1- rows) (1+ row)) sum
(loop for off-row from (max 0 (1- row)) to (min (1- rows) (1+ row)) sum
Line 1,130: Line 1,283:
" ... "
" ... "
". . "
". . "
"Ht.. ......")))</lang>
"Ht.. ......")))</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll">CL-USER> (wireworld-show-gens (make-rosetta-wireworld) 12)
<pre style="height:30ex;overflow:scroll">CL-USER> (wireworld-show-gens (make-rosetta-wireworld) 12)
Line 1,207: Line 1,360:


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.algorithm;
<syntaxhighlight lang="d">import std.stdio, std.algorithm;


void wireworldStep(char[][] W1, char[][] W2) pure nothrow @safe @nogc {
void wireworldStep(char[][] W1, char[][] W2) pure nothrow @safe @nogc {
Line 1,244: Line 1,397:
swap(world, world2);
swap(world, world2);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,281: Line 1,434:
. ....
. ....
.. </pre>
.. </pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.IOUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Wireworld;

{$APPTYPE CONSOLE}

uses
System.SysUtils,
System.IOUtils;

var
rows, cols: Integer;
rx, cx: Integer;
mn: TArray<Integer>;

procedure Print(grid: TArray<byte>);
begin
writeln(string.Create('_', cols * 2), #10);

for var r := 1 to rows do
begin
for var c := 1 to cols do
begin
if grid[r * cx + c] = 0 then
write(' ')
else
write(' ', chr(grid[r * cx + c]));
end;
writeln;
end;
end;

procedure Step(var dst: TArray<byte>; src: TArray<byte>);
begin
for var r := 1 to rows do
begin
for var c := 1 to cols do
begin
var x := r * cx + c;
dst[x] := src[x];

case chr(dst[x]) of
'H':
dst[x] := ord('t');
't':
dst[x] := ord('.');
'.':
begin
var nn := 0;
for var n in mn do
if src[x + n] = ord('H') then
inc(nn);
if (nn = 1) or (nn = 2) then
dst[x] := ord('H');
end;
end;
end;
end;
end;

procedure Main();
const
CONFIG_FILE = 'ww.config';
begin

if not FileExists(CONFIG_FILE) then
begin
Writeln(CONFIG_FILE, ' not exist');
exit;
end;

var srcRows := TFile.ReadAllLines(CONFIG_FILE);

rows := length(srcRows);

cols := 0;
for var r in srcRows do
begin
if Length(r) > cols then
cols := length(r);
end;

rx := rows + 2;
cx := cols + 2;

mn := [-cx - 1, -cx, -cx + 1, -1, 1, cx - 1, cx, cx + 1];

var _odd: TArray<byte>;
var _even: TArray<byte>;

SetLength(_odd, rx * cx);
SetLength(_even, rx * cx);

FillChar(_odd[0], rx * cx, 0);
FillChar(_even[0], rx * cx, 0);

for var i := 0 to High(srcRows) do
begin
var r := srcRows[i];

var offset := (i + 1) * cx + 1;
for var j := 1 to length(r) do
_odd[offset + j - 1] := ord(r[j]);
end;

while True do
begin
print(_odd);
step(_even, _odd);
Readln;

print(_even);
step(_odd, _even);
Readln;
end;
end;

begin
Main;

{$IFNDEF UNIX} readln; {$ENDIF}
end.</syntaxhighlight>
{{out}}
<pre>__________________


t H
. . . . .
. .


__________________


. t
. H . . .
. .


__________________


. .
. t H . .
. H


__________________


. .
. . t H .
H t


__________________


. .
H . . t H
t .


__________________


H .
t . . . t
. .


__________________


t H
. . . . .
. .


__________________


. t
. H . . .
. .

</pre>

=={{header|EasyLang}}==
[https://easylang.dev/show/#cod=hVTNbuMgEL7zFKNstdptFdaOVSU95J53WFUrikmLlhgLSJv06XfAYLDjarkYz3zz980M9mrB6V6JoyOvSr8wBaffz9BxoOSF8b+vRp+7FrbbLfkGpDeag33TH0BRDwBcCWb8xXKmBOyhrir4heZB9omCQXEPFX169MKjNiAxJCjR+VBehueC0B8S1lD/hJNuowc810LRyvesOOl3gWb3McI13aJaHtG7fEbrKkp8ulph+KpKIqEyrJ7DnnZLsM0c1jS7EWbFXLtrmiii8WsEd54a+0mClA6sGsHaxKq9w0Cy68/O/2Ev9oEtFD8M8UcSMxvYtO+x1uDDiF4wt6CN5vwOI4B1hr8xY9F3zhyL5T6DFV1lYfZSEBWIGbCHRexmEesWsU2JLZmEmwIg05m+BSU4LJGudZnszEcynJKN59w5qQbxajXy+T/KKfEd9EsSBrtDZZrwtDjnvmVOpCZ/sQiLk4bugihRVA5kcwurF2AFEXa6FD6R1u/fuvbpFMCkvH6hxCO9ocS5bP0CIvd4u8xBFh72sbDLrDLIjZheEe7z3AAmYKf5Q650Ml/zmeluKp8MzbBqH6wfuuVbQInuwMmTCG/a0K+AwifPf4MKn7JHRAZZFmCTwxD9QRtG3IGmQ+gYcPw5OEohqgn5Bw== Run it]

<syntaxhighlight>
sys topleft
global m[] nc .
background 777
#
proc show . .
clear
scale = 100 / nc
sz = scale * 0.95
for i to len m[]
x = (i - 1) mod nc
y = (i - 1) div nc
move x * scale y * scale
if m[i] = 0
color 000
elif m[i] = 1
color 980
elif m[i] = 2
color 338
else
color 833
.
rect sz sz
.
.
proc read . .
s$ = input
nc = len s$ + 2
for i to nc
m[] &= 0
.
repeat
m[] &= 0
for c$ in strchars s$
if c$ = "."
m[] &= 1
elif c$ = "H"
m[] &= 2
elif c$ = "t"
m[] &= 3
else
m[] &= 0
.
.
for i to nc - len s$ - 1
m[] &= 0
.
s$ = input
until s$ = ""
.
for i to nc
m[] &= 0
.
.
read
#
len mn[] len m[]
#
proc update . .
for i to len m[]
if m[i] = 2
mn[i] = 3
elif m[i] = 3
mn[i] = 1
elif m[i] = 1
s = 0
for dx = -1 to 1
for dy = -1 to 1
ix = i + dy * nc + dx
s += if m[ix] = 2
.
.
if s = 2 or s = 1
mn[i] = 2
else
mn[i] = 1
.
.
.
swap mn[] m[]
.
on timer
update
show
timer 0.5
.
show
timer 0.5
#
input_data
tH.........
. .
...
. .
Ht.. ......
</syntaxhighlight>



=={{header|Elena}}==
=={{header|Elena}}==
ELENA 5.0, using cellular library
ELENA 6.x, using cellular library
<lang elena>import system'routines;
<syntaxhighlight lang="elena">import system'routines;
import extensions;
import extensions;
import cellular;
import cellular;

const string sample =
const string sample =
" tH......
" tH......
Line 1,298: Line 1,742:
. ......
. ......
...Ht...";
...Ht...";

const string conductorLabel = ".";
const string conductorLabel = ".";
const string headLabel = "H";
const string headLabel = "H";
const string tailLabel = "t";
const string tailLabel = "t";
const string emptyLabel = " ";
const string emptyLabel = " ";

const int empty = 0;
const int empty = 0;
const int conductor = 1;
const int conductor = 1;
const int electronHead = 2;
const int electronHead = 2;
const int electronTail = 3;
const int electronTail = 3;

wireWorldRuleSet = new RuleSet
wireWorldRuleSet = new RuleSet
{
{
proceed(Space s, int x, int y, ref int retVal)
int proceed(Space s, int x, int y)
{
{
int cell := s.at(x, y);
int cell := s.at(x, y);
cell =>
cell =>
conductor
conductor
Line 1,321: Line 1,765:
if (number == 1 || number == 2)
if (number == 1 || number == 2)
{
{
retVal := electronHead
^ electronHead
}
}
else
else
{
{
retVal := conductor
^ conductor
}
}
}
}
electronHead
electronHead
{
{
retVal := electronTail
^ electronTail
}
}
electronTail
electronTail
{
{
retVal := conductor
^ conductor
}
}
:{
!{
retVal := cell
^ cell
}
}
}
}
};
};

sealed class Model
sealed class Model
{
{
Space theSpace;
Space theSpace;
constructor load(string stateString, int maxX, int maxY)
constructor load(string stateString, int maxX, int maxY)
{
{
var strings := stateString.splitBy(newLine).selectBy:(s => s.toArray()).toArray();
var strings := stateString.splitBy(newLineConstant).selectBy::(s => s.toArray()).toArray();
theSpace := IntMatrixSpace.allocate(maxX, maxY, RuleSet
theSpace := IntMatrixSpace.allocate(maxX, maxY, RuleSet
{
{
proceed(Space s, int x, int y, ref int retVal)
int proceed(Space s, int x, int y)
{
{
int retVal := 0;
if (x < strings.Length)
if (x < strings.Length)
{
{
Line 1,373: Line 1,818:
{
{
retVal := empty
retVal := empty
}
};
^ retVal
}
}
})
})
}
}
run()
run()
{
{
theSpace.update(wireWorldRuleSet)
theSpace.update(wireWorldRuleSet)
}
}
print()
print()
{
{
int columns := theSpace.Columns;
int columns := theSpace.Columns;
int rows := theSpace.Rows;
int rows := theSpace.Rows;
int i := 0;
int i := 0;
int j := 0;
int j := 0;
Line 1,394: Line 1,840:
{
{
j := 0;
j := 0;
while (j < columns)
while (j < columns)
{
{
var label := emptyLabel;
var label := emptyLabel;
int cell := theSpace.at(i, j);
int cell := theSpace.at(i, j);
cell =>
cell =>
conductor { label := conductorLabel }
conductor { label := conductorLabel }
electronHead { label := headLabel }
electronHead { label := headLabel }
electronTail { label := tailLabel };
electronTail { label := tailLabel };
console.write(label);
console.write(label);
j := j + 1
j := j + 1
};
};
i := i + 1;
i := i + 1;
console.writeLine()
console.writeLine()
Line 1,415: Line 1,861:
}
}
}
}

public program()
public program()
{
{
Model model := Model.load(sample,10,30);
Model model := Model.load(sample,10,30);
for(int i := 0, i < 10, i += 1)
for(int i := 0; i < 10; i += 1)
{
{
console.printLineFormatted("Iteration {0}",i);
console.printLineFormatted("Iteration {0}",i);
model.print().run()
model.print().run()
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,487: Line 1,933:
=={{header|Elixir}}==
=={{header|Elixir}}==
{{trans|Ruby}}
{{trans|Ruby}}
<lang elixir>defmodule Wireworld do
<syntaxhighlight lang="elixir">defmodule Wireworld do
@empty " "
@empty " "
@head "H"
@head "H"
Line 1,570: Line 2,016:
"""
"""
Wireworld.run(text)</lang>
Wireworld.run(text)</syntaxhighlight>


{{out}}
{{out}}
Line 1,841: Line 2,287:
</pre>
</pre>


=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Wireworld. Nigel Galloway: January 22nd., 2024
type Cell= |E |T |H |C
let n=array2D [[T;H;C;C;C;C;C;C;C;C;C];
[C;E;E;E;C;E;E;E;E;E;E];
[E;E;E;C;C;C;E;E;E;E;E];
[C;E;E;E;C;E;E;E;E;E;E];
[H;T;C;C;E;C;C;C;C;C;C]]
let fG n g=match n|>Seq.sumBy(fun n->match Array2D.get g (fst n) (snd n) with H->1 |_->0) with 1 |2->H |_->C
let fX i=i|>Array2D.mapi(fun n g->function |E->E |H->T |T->C |C->fG (Seq.allPairs [max 0 (n-1)..min (n+1) (Array2D.length1 i-1)] [max 0 (g-1)..min (g+1) (Array2D.length2 i-1)]) i)
Seq.unfold(fun n->Some(n,fX n))n|>Seq.take 15|>Seq.iteri(fun n g->printfn "%d:\n%A\n" n g)
</syntaxhighlight>
{{out}}
after 7: 8,9,10 are repeated as 11,12,13 then 14,15,16 etc
<pre>
0:
[[T; H; C; C; C; C; C; C; C; C; C]
[C; E; E; E; C; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[C; E; E; E; C; E; E; E; E; E; E]
[H; T; C; C; E; C; C; C; C; C; C]]

1:
[[C; T; H; C; C; C; C; C; C; C; C]
[H; E; E; E; C; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[H; E; E; E; C; E; E; E; E; E; E]
[T; C; C; C; E; C; C; C; C; C; C]]

2:
[[H; C; T; H; C; C; C; C; C; C; C]
[T; E; E; E; C; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[T; E; E; E; C; E; E; E; E; E; E]
[C; H; C; C; E; C; C; C; C; C; C]]

3:
[[T; H; C; T; H; C; C; C; C; C; C]
[C; E; E; E; H; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[C; E; E; E; C; E; E; E; E; E; E]
[H; T; H; C; E; C; C; C; C; C; C]]

4:
[[C; T; H; C; T; H; C; C; C; C; C]
[H; E; E; E; T; E; E; E; E; E; E]
[E; E; E; H; H; H; E; E; E; E; E]
[H; E; E; E; C; E; E; E; E; E; E]
[T; C; T; H; E; C; C; C; C; C; C]]

5:
[[H; C; T; H; C; T; H; C; C; C; C]
[T; E; E; E; C; E; E; E; E; E; E]
[E; E; E; T; T; T; E; E; E; E; E]
[T; E; E; E; C; E; E; E; E; E; E]
[C; H; C; T; E; C; C; C; C; C; C]]

6:
[[T; H; C; T; H; C; T; H; C; C; C]
[C; E; E; E; H; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[C; E; E; E; C; E; E; E; E; E; E]
[H; T; H; C; E; C; C; C; C; C; C]]

7:
[[C; T; H; C; T; H; C; T; H; C; C]
[H; E; E; E; T; E; E; E; E; E; E]
[E; E; E; H; H; H; E; E; E; E; E]
[H; E; E; E; C; E; E; E; E; E; E]
[T; C; T; H; E; C; C; C; C; C; C]]

8:
[[H; C; T; H; C; T; H; C; T; H; C]
[T; E; E; E; C; E; E; E; E; E; E]
[E; E; E; T; T; T; E; E; E; E; E]
[T; E; E; E; C; E; E; E; E; E; E]
[C; H; C; T; E; C; C; C; C; C; C]]

9:
[[T; H; C; T; H; C; T; H; C; T; H]
[C; E; E; E; H; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[C; E; E; E; C; E; E; E; E; E; E]
[H; T; H; C; E; C; C; C; C; C; C]]

10:
[[C; T; H; C; T; H; C; T; H; C; T]
[H; E; E; E; T; E; E; E; E; E; E]
[E; E; E; H; H; H; E; E; E; E; E]
[H; E; E; E; C; E; E; E; E; E; E]
[T; C; T; H; E; C; C; C; C; C; C]]

11:
[[H; C; T; H; C; T; H; C; T; H; C]
[T; E; E; E; C; E; E; E; E; E; E]
[E; E; E; T; T; T; E; E; E; E; E]
[T; E; E; E; C; E; E; E; E; E; E]
[C; H; C; T; E; C; C; C; C; C; C]]

12:
[[T; H; C; T; H; C; T; H; C; T; H]
[C; E; E; E; H; E; E; E; E; E; E]
[E; E; E; C; C; C; E; E; E; E; E]
[C; E; E; E; C; E; E; E; E; E; E]
[H; T; H; C; E; C; C; C; C; C; C]]

13:
[[C; T; H; C; T; H; C; T; H; C; T]
[H; E; E; E; T; E; E; E; E; E; E]
[E; E; E; H; H; H; E; E; E; E; E]
[H; E; E; E; C; E; E; E; E; E; E]
[T; C; T; H; E; C; C; C; C; C; C]]

14:
[[H; C; T; H; C; T; H; C; T; H; C]
[T; E; E; E; C; E; E; E; E; E; E]
[E; E; E; T; T; T; E; E; E; E; E]
[T; E; E; E; C; E; E; E; E; E; E]
[C; H; C; T; E; C; C; C; C; C; C]]
</pre>
=={{header|Forth}}==
=={{header|Forth}}==
<lang forth>16 constant w
<syntaxhighlight lang="forth">16 constant w
8 constant h
8 constant h


Line 1,922: Line 2,489:
: gen ['] newrow foreachrow age ;
: gen ['] newrow foreachrow age ;


: wireworld begin gen 0 0 at-xy show key? until ;</lang>
: wireworld begin gen 0 0 at-xy show key? until ;</syntaxhighlight>


{{out}}
{{out}}
Line 2,047: Line 2,614:
=={{header|Fortran}}==
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
{{works with|Fortran|95 and later}}
<lang fortran>program Wireworld
<syntaxhighlight lang="fortran">program Wireworld
implicit none
implicit none
Line 2,131: Line 2,698:
end do
end do
end subroutine Nextgen
end subroutine Nextgen
end program Wireworld</lang>
end program Wireworld</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll">Generation 0
<pre style="height:30ex;overflow:scroll">Generation 0
Line 2,225: Line 2,792:


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>#define MAXX 319
<syntaxhighlight lang="freebasic">#define MAXX 319
#define MAXY 199
#define MAXY 199


Line 2,294: Line 2,861:
buffer = 1 - buffer
buffer = 1 - buffer
active = 1 - buffer
active = 1 - buffer
loop</lang>
loop</syntaxhighlight>


=={{header|GML}}==
=={{header|GML}}==
Only visual output. Not an all-out simulator, but has some functions not on by default.
Only visual output. Not an all-out simulator, but has some functions not on by default.
<lang GML>//Create event
<syntaxhighlight lang="gml">//Create event
/*
/*
Wireworld first declares constants and then reads a wireworld from a textfile.
Wireworld first declares constants and then reads a wireworld from a textfile.
Line 2,396: Line 2,963:
ds_grid_destroy(gridid);
ds_grid_destroy(gridid);
ds_list_destroy(listid);
ds_list_destroy(listid);
}</lang>
}</syntaxhighlight>
Now the step event
Now the step event
<syntaxhighlight lang="gml">
<lang GML>
//Step event
//Step event
/*
/*
Line 2,617: Line 3,184:
}
}
}
}
</syntaxhighlight>
</lang>
Now the draw event
Now the draw event
<syntaxhighlight lang="gml">
<lang GML>
//Draw event
//Draw event
/*
/*
Line 2,682: Line 3,249:
}
}
draw_set_color(c_black);
draw_set_color(c_black);
</syntaxhighlight>
</lang>


=={{header|Go}}==
=={{header|Go}}==
Text output. Press Enter to compute and display successive generations.
Text output. Press Enter to compute and display successive generations.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 2,775: Line 3,342:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang Haskell>import Data.List
<syntaxhighlight lang="haskell">import Data.List
import Control.Monad
import Control.Monad
import Control.Arrow
import Control.Arrow
Line 2,798: Line 3,365:
noH = length $ filter (=='H') $ concat xs
noH = length $ filter (=='H') $ concat xs


runCircuit = iterate (map(map nwState).take3x3)</lang>
runCircuit = iterate (map(map nwState).take3x3)</syntaxhighlight>
Example executed in GHCi:
Example executed in GHCi:
<lang Haskell>oscillator= [" tH ",
<syntaxhighlight lang="haskell">oscillator= [" tH ",
". ....",
". ....",
" .. "
" .. "
]
]


example = mapM_ (mapM_ putStrLn) .map (borden ' ').take 9 $ runCircuit oscillator</lang>
example = mapM_ (mapM_ putStrLn) .map (borden ' ').take 9 $ runCircuit oscillator</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll">
<pre style="height:30ex;overflow:scroll">
Line 2,861: Line 3,428:
This simulation starts in single step mode and can be switched to run uninterrupted. The window can be saved at any point in single step mode.
This simulation starts in single step mode and can be switched to run uninterrupted. The window can be saved at any point in single step mode.
This uses 1 pixel per cell so this animation looks tiny. Also the orientation has been flipped.
This uses 1 pixel per cell so this animation looks tiny. Also the orientation has been flipped.
<lang Icon>link graphics
<syntaxhighlight lang="icon">link graphics


$define EDGE -1
$define EDGE -1
Line 2,952: Line 3,519:
}
}
}
}
end</lang>
end</syntaxhighlight>


{{libheader|Icon Programming Library}}
{{libheader|Icon Programming Library}}
Line 2,958: Line 3,525:


=={{header|J}}==
=={{header|J}}==
The example circuit:<lang J>circ0=:}: ] ;. _1 LF, 0 : 0
The example circuit:<syntaxhighlight lang="j">circ0=:}: ] ;. _1 LF, 0 : 0
tH........
tH........
. .
. .
Line 2,964: Line 3,531:
. .
. .
Ht.. .....
Ht.. .....
)</lang>
)</syntaxhighlight>
A 'boarding' verb board and the next cell state verb nwS:
A 'boarding' verb board and the next cell state verb nwS:
<lang J>board=: ' ' ,.~ ' ' ,. ' ' , ' ' ,~ ]
<syntaxhighlight lang="j">board=: ' ' ,.~ ' ' ,. ' ' , ' ' ,~ ]


nwS=: 3 : 0
nwS=: 3 : 0
Line 2,972: Line 3,539:
if. ('.'=e)*. e.&1 2 +/'H'=,y do. 'H' return. end.
if. ('.'=e)*. e.&1 2 +/'H'=,y do. 'H' return. end.
' t..' {~ ' Ht.' i. e
' t..' {~ ' Ht.' i. e
)</lang>
)</syntaxhighlight>
The 'most' powerful part is contained in the following iterating sentence, namely the dyad cut ;. [http://www.jsoftware.com/help/dictionary/d331.htm ]. In this way verb nwS can work on all the 3x3 matrices containing each cell surrounded by its 8 relevant neighbors.
The 'most' powerful part is contained in the following iterating sentence, namely the dyad cut ;. [http://www.jsoftware.com/help/dictionary/d331.htm ]. In this way verb nwS can work on all the 3x3 matrices containing each cell surrounded by its 8 relevant neighbors.
<lang J> process=: (3 3 nwS;. _3 board)^:
<syntaxhighlight lang="j"> process=: (3 3 nwS;. _3 board)^:
(<10) process circuit</lang>
(<10) process circuit</syntaxhighlight>
Example run:
Example run:
<pre style="height:30ex;overflow:scroll">
<pre style="height:30ex;overflow:scroll">
Line 3,042: Line 3,609:
Note also that a graphical presentation can be achieved using viewmat. For example:
Note also that a graphical presentation can be achieved using viewmat. For example:


<lang j>require'viewmat'
<syntaxhighlight lang="j">require'viewmat'
viewmat"2 ' .tH'i. (<10) process circ0</lang>
viewmat"2 ' .tH'i. (<10) process circ0</syntaxhighlight>


(This example opens 10 windows, one for each generation.)
(This example opens 10 windows, one for each generation.)
Line 3,059: Line 3,626:
<input type='file' accept='text/plain' onchange='openFile( event )' />
<input type='file' accept='text/plain' onchange='openFile( event )' />
<br /></body></html></pre>
<br /></body></html></pre>
<lang javascript>
<syntaxhighlight lang="javascript">
var ctx, sizeW, sizeH, scl = 10, map, tmp;
var ctx, sizeW, sizeH, scl = 10, map, tmp;
function getNeighbour( i, j ) {
function getNeighbour( i, j ) {
Line 3,148: Line 3,715:
simulate();
simulate();
}
}
</syntaxhighlight>
</lang>


=={{header|jq}}==
=={{header|jq}}==
Line 3,160: Line 3,727:
* For speed, the simulation uses the exploded string (an array).
* For speed, the simulation uses the exploded string (an array).
* The ASCII values of the symbols used to display the state are hardcoded.
* The ASCII values of the symbols used to display the state are hardcoded.
<lang jq>def lines: split("\n")|length;
<syntaxhighlight lang="jq">def lines: split("\n")|length;


def cols: split("\n")[0]|length + 1; # allow for the newline
def cols: split("\n")[0]|length + 1; # allow for the newline
Line 3,196: Line 3,763:
$world | evolve($i; $w) as $next
$world | evolve($i; $w) as $next
| if .[$i] == $next then . else .[$i] = $next end )
| if .[$i] == $next then . else .[$i] = $next end )
| [., $lines, $w] ; # </lang>
| [., $lines, $w] ; # </syntaxhighlight>
'''Animation'''
'''Animation'''
<lang jq># "clear screen":
<syntaxhighlight lang="jq"># "clear screen":
def cls: "\u001b[2J";
def cls: "\u001b[2J";


Line 3,223: Line 3,790:


# Input: a string representing the initial state
# Input: a string representing the initial state
def frames(n): animation(n; -1);#</lang>
def frames(n): animation(n; -1);#</syntaxhighlight>
'''Examples''':
'''Examples''':
<lang jq>def world11:
<syntaxhighlight lang="jq">def world11:
"+-----------+\n" +
"+-----------+\n" +
"|tH.........|\n" +
"|tH.........|\n" +
Line 3,239: Line 3,806:
" . .... \n" +
" . .... \n" +
" .. \n" +
" .. \n" +
" \n" ;</lang>
" \n" ;</syntaxhighlight>
'''Illustration 1''':
'''Illustration 1''':
<lang jq># Ten-step animation with about 1 sec between frames
<syntaxhighlight lang="jq"># Ten-step animation with about 1 sec between frames
world9 | animation(10; 1000)</lang>
world9 | animation(10; 1000)</syntaxhighlight>
'''Illustration 2''':
'''Illustration 2''':
<lang jq># Ten frames in sequence:
<syntaxhighlight lang="jq"># Ten frames in sequence:
world11 | frames(10)</lang>
world11 | frames(10)</syntaxhighlight>


To run: jq -n -r -f wireworld.rc
To run: jq -n -r -f wireworld.rc


=={{header|Julia}}==
=={{header|Julia}}==
<lang julia>function surround2D(b, i, j)
<syntaxhighlight lang="julia">function surround2D(b, i, j)
h, w = size(b)
h, w = size(b)
[b[x,y] for x in i-1:i+1, y in j-1:j+1 if (0 < x <= h && 0 < y <= w)]
[b[x,y] for x in i-1:i+1, y in j-1:j+1 if (0 < x <= h && 0 < y <= w)]
Line 3,292: Line 3,859:
mat .= mat2
mat .= mat2
end
end
</lang>{{output}}<pre>
</syntaxhighlight>{{output}}<pre>
Starting Wireworld board:
Starting Wireworld board:


Line 3,350: Line 3,917:
=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
[[File:AnimWW.gif]]
[[File:AnimWW.gif]]
<syntaxhighlight lang="lb">
<lang lb>
WindowWidth = 840
WindowWidth = 840
WindowHeight = 600
WindowHeight = 600
Line 3,480: Line 4,047:
timer 1000, [tmr]
timer 1000, [tmr]
wait
wait
</syntaxhighlight>
</lang>


=={{header|Logo}}==
=={{header|Logo}}==
{{Works with|MSWlogo}}
{{Works with|MSWlogo}}
(The wireworld given in the file must be bounded by spaces for the program to work. Also it is notable that the program takes the width as the longest of the lines.)
(The wireworld given in the file must be bounded by spaces for the program to work. Also it is notable that the program takes the width as the longest of the lines.)
<lang Logo>to wireworld :filename :speed ;speed in n times per second, approximated
<syntaxhighlight lang="logo">to wireworld :filename :speed ;speed in n times per second, approximated
Make "speed 60/:speed
Make "speed 60/:speed
wireworldread :filename
wireworldread :filename
Line 3,553: Line 4,120:
if (mditem (list :y-1 :x-1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y-1 :x-1) :field)=:thing [Make "neighbours :neighbours+1]
ifelse OR :neighbours=1 :neighbours=2 [op "true] [op "false]
ifelse OR :neighbours=1 :neighbours=2 [op "true] [op "false]
end</lang>
end</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
If ran using [[L%C3%96VE]], it will animate the simulation on a window. Otherwise it will print the first 10 steps on the console.
If ran using [[L%C3%96VE]], it will animate the simulation on a window. Otherwise it will print the first 10 steps on the console.
<syntaxhighlight lang="lua">
<lang Lua>
local map = {{'t', 'H', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
local map = {{'t', 'H', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', ' ', ' ', ' ', '.'},
{'.', ' ', ' ', ' ', '.'},
Line 3,627: Line 4,194:
end
end
end
end
</syntaxhighlight>
</lang>


=={{header|Mathematica}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<lang Mathematica>DynamicModule[{data =
<syntaxhighlight lang="mathematica">DynamicModule[{data =
ArrayPad[PadRight[Characters /@ StringSplit["tH.........
ArrayPad[PadRight[Characters /@ StringSplit["tH.........
. .
. .
Line 3,643: Line 4,210:
3, {{a_, b_, c_}, {d_, 3, e_}, {f_, g_, h_}} :>
3, {{a_, b_, c_}, {d_, 3, e_}, {f_, g_, h_}} :>
Switch[Count[{a, b, c, d, e, f, g, h}, 1], 1, 1, 2, 1, _, 3]},
Switch[Count[{a, b, c, d, e, f, g, h}, 1], 1, 1, 2, 1, _, 3]},
data], ColorRules -> {1 -> Yellow, 2 -> Red}]]</lang>
data], ColorRules -> {1 -> Yellow, 2 -> Red}]]</syntaxhighlight>


=={{header|MiniScript}}==
This GUI implementation is for use with [http://miniscript.org/MiniMicro Mini Micro].
<syntaxhighlight lang="miniscript">
colors = [color.black, color.yellow, color.aqua, color.red]
deltas = [[-1,-1], [-1,0], [-1,1],
[ 0,-1], [ 0,1],
[ 1,-1], [ 1,0], [ 1,1]]

displayGrid = function(grid, td)
for y in range(0, grid.len - 1)
for x in range(0, grid[0].len - 1)
td.setCell x,y, grid[y][x]
end for
end for
end function

buildGrid = function(s)
lines = s.split(char(13))
nRows = lines.len
nCols = 0
for line in lines
if line.len > nCols then nCols = line.len
end for
grid = []
emptyRow = []
for c in range(1,nCols)
emptyRow.push(0)
end for
for line in lines
row = emptyRow[:]
for i in range(0, line.len - 1)
row[i] = " .Ht".indexOf(line[i])
end for
grid.push(row)
end for
return grid
end function

getNewState = function(td, x, y)
cellState = td.cell(x, y)
if cellState == 3 then
return 1
else if cellState == 2 then
return 3
else if cellState == 1 then
sum = 0
for delta in deltas
x1 = x + delta[0]
y1 = y + delta[1]
if td.cell(x1, y1) == 2 then sum += 1
end for
if sum == 1 or sum == 2 then
return 2
else
return 1
end if
end if
return cellState
end function

clear

wireWorldProgram = "tH........." + char(13)
wireWorldProgram += ". ." + char(13)
wireWorldProgram += " ..." + char(13)
wireWorldProgram += ". ." + char(13)
wireWorldProgram += "Ht.. ......"
grid = buildGrid(wireWorldProgram)

// Prepare a tile display
// Generate image used for the tiles from the colors defined above.
img = Image.create(colors.len, 1);
for i in range(0, colors.len - 1)
img.setPixel(i, 0, colors[i])
end for

cols = grid[0].len
rows = grid.len
display(4).mode = displayMode.tile
td = display(4)
cSize = 25
td.cellSize = cSize // size of cells on screen
td.scrollX = -(960 - cols * (cSize + 1)) / 2
td.scrollY = -(640 - rows * (cSize + 1)) / 2
td.extent = [cols, rows]
td.overlap = -1 // adds a small gap between cells
td.tileSet = img; td.tileSetTileSize = 1
td.clear 0

while true
displayGrid(grid, td)
for y in range(0, rows - 1)
for x in range(0, cols - 1)
grid[y][x] = getNewState(td, x, y)
end for
end for
wait 0.5
end while
</syntaxhighlight>
=={{header|Nim}}==
=={{header|Nim}}==
{{trans|C}}
{{trans|C}}
<lang nim>import strutils, os
<syntaxhighlight lang="nim">import strutils, os


var world, world2 = """
var world, world2 = """
Line 3,683: Line 4,351:


world2.next(world, w)
world2.next(world, w)
swap world, world2</lang>
swap world, world2</syntaxhighlight>


=={{header|OCaml}}==
=={{header|OCaml}}==


<lang ocaml>let w = [|
<syntaxhighlight lang="ocaml">let w = [|
" ......tH ";
" ......tH ";
" . ...... ";
" . ...... ";
Line 3,742: Line 4,410:
aux n
aux n
in
in
aux w</lang>
aux w</syntaxhighlight>


=={{header|Oz}}==
=={{header|Oz}}==
Includes a simple animation, using a text widget.
Includes a simple animation, using a text widget.
<lang oz>declare
<syntaxhighlight lang="oz">declare
Rules =
Rules =
[rule(& & )
[rule(& & )
Line 3,837: Line 4,505:
{Field set(text:{ShowArena Gi})}
{Field set(text:{ShowArena Gi})}
{Delay 500}
{Delay 500}
end</lang>
end</syntaxhighlight>


=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
<lang parigp>\\ 0 = conductor, 1 = tail, 2 = head, 3 = empty
<syntaxhighlight lang="parigp">\\ 0 = conductor, 1 = tail, 2 = head, 3 = empty
wireworldStep(M)={
wireworldStep(M)={
my(sz=matsize(M),t);
my(sz=matsize(M),t);
Line 3,870: Line 4,538:
)
)
};
};
animate(read("wireworld.gp"))</lang>
animate(read("wireworld.gp"))</syntaxhighlight>


=={{header|Perl}}==
=={{header|Perl}}==
Read the initial World from stdin and print 10 steps to stdout
Read the initial World from stdin and print 10 steps to stdout
<lang perl>my @f = ([],(map {chomp;['',( split // ),'']} <>),[]);
<syntaxhighlight lang="perl">my @f = ([],(map {chomp;['',( split // ),'']} <>),[]);


for (1 .. 10) {
for (1 .. 10) {
Line 3,894: Line 4,562:
}
}
@f = (@a,[]);
@f = (@a,[]);
}</lang>
}</syntaxhighlight>
Input:
Input:
<pre>tH.........
<pre>tH.........
Line 3,975: Line 4,643:
=={{header|Phix}}==
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
{{libheader|Phix/pGUI}}
{{libheader|Phix/online}}
<lang Phix>-- demo\rosetta\Wireworld.exw
You can run this online [http://phix.x10.mx/p2js/Wireworld.htm here].
--
<!--<syntaxhighlight lang="phix">(phixonline)-->
-- Invoke with file to read or let it read the one below (if compiled assumes source is in the same directory)
<span style="color: #000080;font-style:italic;">--
--
-- demo\rosetta\Wireworld.exw
-- Note that tabs in description files are not supported - where necessary spaces can be replaced with _ chars.
-- ==========================
-- (tab chars in text files should technically always represent (to-next) 8 spaces, but not many editors respect
--
-- that, and instead assume the file will only ever be read by the same program/with matching settings. </rant>)
-- Invoke with file to read, or let it read the one below (if compiled assumes source is in the same directory)
-- (see also demo\edix\src\tabs.e\ExpandTabs() for what you'd need if you knew what tab chars really meant.)
--
--
-- Note that tabs in description files are not supported - where necessary spaces can be replaced with _ chars.
/* -- default description:
-- (tab chars in text files should technically always represent (to-next) 8 spaces, but not many editors respect
tH.........
-- that, and instead assume the file will only ever be read by the same program/with matching settings. &lt;/rant&gt;)
.___.
-- (see also demo\edix\src\tabs.e\ExpandTabs() for what you'd need if you knew what the tab chars really meant.)
___...
--</span>
.___.
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Ht.. ......
<span style="color: #008080;">constant</span> <span style="color: #000000;">default_description</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
*/
tH.........
sequence lines, counts
.___.
integer longest
___...

.___.
function valid_line(string line, integer l=0)
Ht.. ......
if length(line)=0 then return 0 end if
"""</span>
for i=1 to length(line) do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">counts</span>
integer ch = line[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">longest</span>
if not find(ch," _.tH") then
if l and ch='\t' then
<span style="color: #008080;">function</span> <span style="color: #000000;">valid_line</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">line</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
-- as above
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"error: tab char on line %d\n",{l})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
{} = wait_key()
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
abort(0)
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" _.tH"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'\t'</span> <span style="color: #008080;">then</span>
return 0
<span style="color: #000080;font-style:italic;">-- as above</span>
end if
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"error: tab char on line %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">l</span><span style="color: #0000FF;">})</span>
end for
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
return 1
<span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>
procedure load_desc()
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
string filename = substitute(command_line()[$],".exe",".exw")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer fn = open(filename,"r")
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
if fn=-1 then
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
printf(1,"error opening %s\n",{filename})
{} = wait_key()
<span style="color: #008080;">procedure</span> <span style="color: #000000;">load_desc</span><span style="color: #0000FF;">()</span>
abort(0)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">text</span>
end if
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
sequence text = get_text(fn,GT_LF_STRIPPED)
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">default_description</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
close(fn)
<span style="color: #008080;">else</span>
lines = {}
<span style="color: #004080;">string</span> <span style="color: #000000;">filename</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()[$],</span><span style="color: #008000;">".exe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">".exw"</span><span style="color: #0000FF;">)</span>
for i=1 to length(text) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"r"</span><span style="color: #0000FF;">)</span>
string line = text[i]
<span style="color: #008080;">if</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
if valid_line(line) then
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"error opening %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span>
lines = {line}
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
longest = length(line)
<span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
for j=i+1 to length(text) do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
line = text[j]
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">)</span>
if not valid_line(line,j) then exit end if
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
lines = append(lines,line)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if longest<length(line) then
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
longest = length(line)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end if
<span style="color: #004080;">string</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">valid_line</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
exit
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">line</span><span style="color: #0000FF;">}</span>
end if
<span style="color: #000000;">longest</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
counts = lines
<span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
end procedure
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">valid_line</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
constant dxy = {{-1,-1}, {-1,+0}, {-1,+1},
<span style="color: #008080;">if</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
{+0,-1}, {+0,+1},
<span style="color: #000000;">longest</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
{+1,-1}, {+1,+0}, {+1,+1}}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
procedure set_counts()
<span style="color: #008080;">exit</span>
for y=1 to length(lines) do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for x=1 to length(lines[y]) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if lines[y][x]='.' then
<span style="color: #000000;">counts</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span>
integer count = 0
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
for k=1 to length(dxy) do
integer {cx,cy} = sq_add({x,y},dxy[k])
<span style="color: #008080;">constant</span> <span style="color: #000000;">dxy</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
if cy>=1 and cy<=length(lines)
<span style="color: #0000FF;">{+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
and cx>=1 and cx<=length(lines[cy])
<span style="color: #0000FF;">{+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}}</span>
and lines[cy][cx]='H' then
count += 1
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_counts</span><span style="color: #0000FF;">()</span>
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
counts[y][x] = (count=1 or count=2)
<span style="color: #008080;">if</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dxy</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">({</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">},</span><span style="color: #000000;">dxy</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">])</span>
end procedure
<span style="color: #008080;">if</span> <span style="color: #000000;">cy</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">cy</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">and</span> <span style="color: #000000;">cx</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">cx</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">])</span>
include pGUI.e
<span style="color: #008080;">and</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">][</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'H'</span> <span style="color: #008080;">then</span>

<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
Ihandle dlg, canvas, timer
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
cdCanvas cddbuffer, cdcanvas
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>

<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer dx = floor(w/(longest+2))
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer dy = floor(h/(length(lines)+2))
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
cdCanvasActivate(cddbuffer)
cdCanvasClear(cddbuffer)
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
set_counts()
for y=1 to length(lines) do
<span style="color: #008080;">constant</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Wireworld"</span>
for x=1 to length(lines[y]) do
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">timer</span>
integer c = lines[y][x], colour
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
if find(c," _") then
colour = CD_BLACK
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
elsif c='.' then
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
colour = CD_YELLOW
<span style="color: #004080;">integer</span> <span style="color: #000000;">dx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">/(</span><span style="color: #000000;">longest</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
if counts[y][x] then
<span style="color: #004080;">integer</span> <span style="color: #000000;">dy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">/(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
lines[y][x] = 'H'
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
elsif c='H' then
<span style="color: #000000;">set_counts</span><span style="color: #0000FF;">()</span>
colour = CD_BLUE
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
lines[y][x] = 't'
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
elsif c='t' then
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">colour</span>
colour = CD_RED
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" _"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
lines[y][x] = '.'
<span style="color: #000000;">colour</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">CD_BLACK</span>
end if
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
cdCanvasSetForeground(cddbuffer, colour)
<span style="color: #000000;">colour</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">CD_YELLOW</span>
cdCanvasBox(cddbuffer,x*dx,x*dx+dx,h-y*dy,h-(y*dy+dy))
<span style="color: #008080;">if</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
end for
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'H'</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
cdCanvasFlush(cddbuffer)
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'H'</span> <span style="color: #008080;">then</span>
return IUP_DEFAULT
<span style="color: #000000;">colour</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">CD_BLUE</span>
end function
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'t'</span>

<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'t'</span> <span style="color: #008080;">then</span>
function timer_cb(Ihandle /*ih*/)
<span style="color: #000000;">colour</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">CD_RED</span>
IupUpdate(canvas)
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'.'</span>
return IUP_IGNORE
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">colour</span><span style="color: #0000FF;">)</span>

<span style="color: #7060A8;">cdCanvasBox</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">-</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">-(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">))</span>
function map_cb(Ihandle ih)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
cdcanvas = cdCreateCanvas(CD_IUP, ih)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
cdCanvasSetBackground(cddbuffer, CD_BLACK)
return IUP_DEFAULT
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function

<span style="color: #008080;">function</span> <span style="color: #000000;">timer_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
procedure main()
<span style="color: #7060A8;">IupUpdate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
load_desc()
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_IGNORE</span>
IupOpen()
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

canvas = IupCanvas(NULL)
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
IupSetAttribute(canvas, "RASTERSIZE", "300x180")
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_BLACK</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
timer = IupTimer(Icallback("timer_cb"), 500)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>

dlg = IupDialog(canvas)
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
IupSetAttribute(dlg, "TITLE", "Wireworld")
<span style="color: #000000;">load_desc</span><span style="color: #0000FF;">()</span>

<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
IupShow(dlg)
IupSetAttribute(canvas, "RASTERSIZE", NULL)
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RASTERSIZE=300x180"</span><span style="color: #0000FF;">)</span>
IupMainLoop()
<span style="color: #7060A8;">IupSetCallbacks</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">),</span>
IupClose()
<span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">)})</span>
end procedure

<span style="color: #000000;">timer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupTimer</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"timer_cb"</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">500</span><span style="color: #0000FF;">)</span>
main()</lang>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="%s"`</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">title</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->


=={{header|PHP}}==
=={{header|PHP}}==


<syntaxhighlight lang="php">
<lang PHP>
$desc = 'tH.........
$desc = 'tH.........
. .
. .
Line 4,237: Line 4,918:
draw_world($world);
draw_world($world);
};
};
</syntaxhighlight>
</lang>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
This example uses 'grid' from "lib/simul.l", which maintains a two-dimensional
This example uses 'grid' from "lib/simul.l", which maintains a two-dimensional
structure.
structure.
<lang PicoLisp>(load "@lib/simul.l")
<syntaxhighlight lang="picolisp">(load "@lib/simul.l")


(let
(let
Line 4,277: Line 4,958:
(for This Col
(for This Col
(=: val (: next)) ) )
(=: val (: next)) ) )
(prinl) ) )</lang>
(prinl) ) )</syntaxhighlight>
{{out}}
{{out}}
<pre> +---+---+---+---+---+---+---+---+---+---+---+
<pre> +---+---+---+---+---+---+---+---+---+---+---+
Line 4,320: Line 5,001:
=={{header|PureBasic}}==
=={{header|PureBasic}}==
===Standalone version===
===Standalone version===
<lang PureBasic>Enumeration
<syntaxhighlight lang="purebasic">Enumeration
#Empty
#Empty
#Electron_head
#Electron_head
Line 4,434: Line 5,115:
Data.i 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data.i 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data.i 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data.i 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
EndDataSection</lang>
EndDataSection</syntaxhighlight>
===Load from external source, graphical presentations===
===Load from external source, graphical presentations===
<lang PureBasic>CompilerIf #PB_Compiler_Unicode
<syntaxhighlight lang="purebasic">CompilerIf #PB_Compiler_Unicode
CompilerError "The file handling in this small program is only in ASCII."
CompilerError "The file handling in this small program is only in ASCII."
CompilerEndIf
CompilerEndIf
Line 4,580: Line 5,261:
EndIf
EndIf
Until Event=#PB_Event_CloseWindow
Until Event=#PB_Event_CloseWindow
EndIf</lang>
EndIf</syntaxhighlight>
Example of data file to load
Example of data file to load
<pre>; Save as "WireWorld.txt"
<pre>; Save as "WireWorld.txt"
Line 4,638: Line 5,319:
=={{header|Python}}==
=={{header|Python}}==


<lang python>'''
<syntaxhighlight lang="python">'''
Wireworld implementation.
Wireworld implementation.
'''
'''
Line 4,707: Line 5,388:
print ( ("\n%3i " % gen) + '=' * (ww.w-4) + '\n' )
print ( ("\n%3i " % gen) + '=' * (ww.w-4) + '\n' )
print ( world2string(ww) )
print ( world2string(ww) )
ww = nextgen(ww)</lang>
ww = nextgen(ww)</syntaxhighlight>


{{out}}
{{out}}
Line 4,793: Line 5,474:
=={{header|Racket}}==
=={{header|Racket}}==


<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket
(require 2htdp/universe)
(require 2htdp/universe)
Line 4,901: Line 5,582:


(run-wire-world #:initial-state initial-list)
(run-wire-world #:initial-state initial-list)
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
Line 4,907: Line 5,588:
{{works with|Rakudo|2018.03}}
{{works with|Rakudo|2018.03}}


<lang perl6>class Wireworld {
<syntaxhighlight lang="raku" line>class Wireworld {
has @.line;
has @.line;
method height () { @!line.elems }
method height returns Int { @!line.elems }
method width returns Int { max @!line».chars }
has int $.width;


multi method new(@line) { samewith :@line, :width(max @line».chars) }
multi method new(@line) { samewith :@line }
multi method new($str ) { samewith $str.lines }
multi method new($str ) { samewith $str.lines }


Line 4,930: Line 5,611:
for ^$.height X ^$.width -> ($i, $j) {
for ^$.height X ^$.width -> ($i, $j) {
@succ[$i] ~=
@succ[$i] ~=
do given @!line[$i].comb[$j] {
do given @.line[$i].comb[$j] {
when 'H' { 't' }
when 'H' { 't' }
when 't' { '.' }
when 't' { '.' }
Line 4,959: Line 5,640:
Bool :$stop-on-repeat,
Bool :$stop-on-repeat,
) {
) {
run-loop
run-loop :$interval, :$stop-on-repeat, Wireworld.new: Q:to/END/
tH.........
:$interval,
. .
:$stop-on-repeat,
...
Wireworld.new:
Q:to/§/
. .
Ht.. ......
tH.........
END
. .
...
. .
Ht.. ......
§
}
}


Line 4,975: Line 5,660:
my %seen is SetHash;
my %seen is SetHash;


print "\e7"; # save cursor position
for $initial ...^ * eqv * { # generate a sequence (uses .succ)
for $initial ...^ * eqv * { # generate a sequence (uses .succ)
print "\e[2J";
print "\e8"; # restore cursor position
say '#' x $initial.width;
.say;
last if $stop-on-repeat and %seen{ .gist }++;
.say;
say '#' x $initial.width;
sleep $interval;

if $stop-on-repeat {
last if %seen{ .gist }++;
}

sleep $interval;
}
}
}</lang>
}</syntaxhighlight>
When run with <code>--stop-on-repeat</code>
When run with <code>--stop-on-repeat</code>
{{out}}
{{out}}
<pre>###########
<pre>H.tH.tH.tH.
H.tH.tH.tH.
t .
t .
ttt
ttt
t .
t .
.H.t ......
.H.t ......</pre>
###########</pre>


=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/*REXX program displays a wire world Cartesian grid of four─state cells. */
<syntaxhighlight lang="rexx">/*REXX program displays a wire world Cartesian grid of four─state cells. */
parse arg iFID . '(' generations rows cols bare head tail wire clearScreen reps
parse arg iFID . '(' generations rows cols bare head tail wire clearScreen reps
if iFID=='' then iFID= "WIREWORLD.TXT" /*should default input file be used? */
if iFID=='' then iFID= "WIREWORLD.TXT" /*should default input file be used? */
Line 5,059: Line 5,737:
if reps\==0 & #reps<=reps then return /*so far, so good, no reps.*/
if reps\==0 & #reps<=reps then return /*so far, so good, no reps.*/
say '"Wireworld" repeated itself' reps "times, the program is stopping."
say '"Wireworld" repeated itself' reps "times, the program is stopping."
signal done /*jump to this pgm's "exit".*/</lang>
signal done /*jump to this pgm's "exit".*/</syntaxhighlight>
Programming note: &nbsp; the &nbsp; '''hood''' &nbsp; subroutine (above) could be optimized for speed by setting some short-circuit values &nbsp; <code>('''r-1''', '''c-1''', '''r+1''', and '''c+1''') </code> &nbsp; and using those values in the subsequent expressions.
Programming note: &nbsp; the &nbsp; '''hood''' &nbsp; subroutine (above) could be optimized for speed by setting some short-circuit values &nbsp; <code>('''r-1''', '''c-1''', '''r+1''', and '''c+1''') </code> &nbsp; and using those values in the subsequent expressions.


Line 5,155: Line 5,833:
═══════════════════════════════════════════════════════════════════════════════════════13
═══════════════════════════════════════════════════════════════════════════════════════13
"Wireworld" repeated itself 2 times, the program is stopping.
"Wireworld" repeated itself 2 times, the program is stopping.
</pre>

=={{header|RISC-V Assembly}}==
<syntaxhighlight lang="risc-v">
/* gnu assembler syntax */
wireworld:
/* unsigned int width (a0) */
/* unsigned int height (a1) */
/* char* grid (a2) */

mv a4,a2

li t4,'. /* conductor */
li t5,'H /* head */
li t6,'t /* tail */

addi t2,a0,-1
addi t3,a1,-1

mv t1,zero
.yloop: /* outer loop (y) */
mv t0,zero
.xloop: /* inner loop (x) */

lb a5,0(a4)
bgt a5,t4,.torh
blt a5,t4,.empty

/* conductor: */
/* unsigned int head_count (a3) */
/* char* test_ptr (a6) */
/* char test (a7) */

mv a3,zero
sub a6,a4,a0
addi a6,a6,-1

0: beq t1,zero,1f /* bounds up */
beq t0,zero,0f /* bounds left */
lb a7,0(a6)
bne a7,t6,0f
addi a3,a3,1

0: lb a7,1(a6)
bne a7,t6,0f
addi a3,a3,1

0: beq t0,t2,0f /* bounds right */
lb a7,2(a6)
bne a7,t6,0f
addi a3,a3,1

0:1: add a6,a6,a0
beq t0,zero,0f /* bounds left */
lb a7,0(a6)
bne a7,t6,0f
addi a3,a3,1

0: beq t0,t2,0f /* bounds right */
lb a7,2(a6)
bne a7,t5,0f
addi a3,a3,1

0: add a6,a6,a0

beq t1,t3,1f /* bounds down */
beq t0,zero,0f /* bounds left */
lb a7,0(a6)
bne a7,t5,0f
addi a3,a3,1

0: lb a7,1(a6)
bne a7,t5,0f
addi a3,a3,1

0: beq t0,t2,0f /* bounds right */
lb a7,2(a6)
bne a7,t5,0f
addi a3,a3,1

0:1: beq a3,zero,.empty
addi a3,a3,-2
bgt a3,zero,.empty

mv a5,t5 /* convert conductor to electron head */
j .save

.torh: beq a5,t6,.tail

.head: mv a5,t6
j .save

.tail: mv a5,t4
.save: sb a5,0(a4)
.empty: /* do nothing */

/* end x-loop */
addi a4,a4,1
addi t0,t0,1
bne t0,a0,.xloop

/* end y-loop */
addi t1,t1,1
bne t1,a1,.yloop

ret
</syntaxhighlight>

For output, compile the above to an object file and link against the following program:

<syntaxhighlight lang="c">
#include <stdio.h>
#include <string.h>

char init[] = " tH....tH "
" . ...... "
" ........ . "
" .. .... .. .. .. "
".. ... . ..tH....tH... .tH..... ....tH.. .tH."
" .. .... .. .. .. "
" tH...... . "
" . ....tH "
" ...Ht... ";
int width = 60;
int height = 9;

void wireworld(unsigned int, unsigned int, char *);

int main() {
char tmp[width + 1] = {};
do {
for (int i = 0; i < height; i++) {
strncpy(tmp, init + i * width, width);
puts(tmp);
}
wireworld(width, height, init);
} while (getchar());

return 0;
}
</syntaxhighlight>

Example output:

<pre style="height:60ex">
tH....tH
. ......
........ .
.. .... .. .. ..
.. ... . ..tH....tH... .tH..... ....tH.. .tH.
.. .... .. .. ..
tH...... .
. ....tH
...Ht...

.tH....t
. H.....
........ .
.. .... .. .. ..
.. ... . ...tH....tH.. ..tH.... .....tH. ..tH
.. .... .. .. ..
.tH..... H
. .....t
..Ht....

..tH....
. tH....
.......H .
.. .... .. .. H.
.. ... . ....tH....tH. ...tH... ......tH ...t
.. HHH. .. .. H.
..tH.... t
. ......
.Ht.....

...tH...
. .tH...
......Ht .
.. .... H. .. tH
.. ... H H....tH....tH ....tH.. .......t ....
.. tttH H. .. tH
...tH... .
. ......
Ht......

....tH..
. ..tH..
.....Ht. .
.. HHHH tH .. .t
.. ... t tH....tH....t .....tH. ........ H...
.. ...t tH .. .t
....tH.. .
H ......
t.......

.....tH.
. ...tH.
....Ht.. .
.. tttt .t H. ..
.. ... . .tH....tH.... H.....tH ........ tH..
.. .... .t H. ..
H....tH. .
t ......
........

......tH
. ....tH
...Ht... .
.. .... .. tH ..
.. ... . ..tH....tH... tH.....t ........ .tH.
.. .... .. tH ..
tH....tH .
. ......
........

.......t
. H....t
..Ht.... H
.. .... .. .t ..
.. ... . ...tH....tH.. .tH..... H....... ..tH
.. .... .. .t ..
.tH....t .
. H.....
........

........
. tH....
.Ht....H t
.. HHH. .. .. ..
.. ... . ....tH....tH. ..tH.... tH...... ...t
.. .... .. .. ..
..tH.... .
. tH....
.......H

........
. .tH...
Ht....Ht .
.. tttH H. .. ..
.. ... H H....tH....tH ...tH... .tH..... ....
.. .... H. .. ..
...tH... .
. .tH...
......Ht

........
H ..tH..
t....Ht. .
.. ...t tH .. ..
.. ... t tH....tH....t ....tH.. ..tH.... ....
.. HHHH tH .. ..
....tH.. .
. ..tH..
.....Ht.

H.......
t ...tH.
....Ht.. .
.. .... .t .. ..
.. ... . .tH....tH.... H....tH. ...tH... ....
.. tttt .t .. ..
.....tH. .
. ...tH.
....Ht..

tH......
. ....tH
...Ht... .
.. .... .. H. ..
.. ... . ..tH....tH... tH....tH ....tH.. ....
.. .... .. H. ..
......tH .
. ....tH
...Ht...

.tH.....
. .....t
..Ht.... H
.. .... .. tH ..
.. ... . ...tH....tH.. .tH....t .....tH. ....
.. .... .. tH ..
.......t H
. H....t
..Ht....

..tH....
. ......
.Ht..... t
.. HHH. .. .t H.
.. ... . ....tH....tH. ..tH.... H.....tH ....
.. HHH. .. .t H.
........ t
. tH....
.Ht....H

...tH...
. ......
Ht...... .
.. tttH H. .. tH
.. ... . H....tH....tH ...tH... tH.....t ....
.. tttH H. .. tH
........ .
. .tH...
Ht....Ht

....tH..
H ......
t....... .
.. ...t tH .. .t
.. ... . t.....tH....t ....tH.. .tH..... H...
.. ...t tH .. .t
........ .
H ..tH..
t....Ht.

H....tH.
t ......
........ .
.. .... .t .. ..
.. ... . .......tH.... H....tH. ..tH.... tH..
.. .... .t .. ..
H....... .
t ...tH.
....Ht..

tH....tH
. ......
........ .
.. .... .. H. ..
.. ... . ........tH... tH....tH ...tH... .tH.
.. .... .. H. ..
tH...... .
. ....tH
...Ht...

.tH....t
. H.....
........ .
.. .... .. tH ..
.. ... . .........tH.. .tH....t ....tH.. ..tH
.. .... .. tH ..
.tH..... H
. .....t
..Ht....
</pre>
</pre>


Line 5,161: Line 6,183:


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>use std::str::FromStr;
<syntaxhighlight lang="rust">use std::str::FromStr;


#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq)]
Line 5,258: Line 6,280:
Ok(world)
Ok(world)
}
}
}</lang>
}</syntaxhighlight>


graphical output using winit 0.24 and pixels 0.2
graphical output using winit 0.24 and pixels 0.2
<lang rust>use pixels::{Pixels, SurfaceTexture};
<syntaxhighlight lang="rust">use pixels::{Pixels, SurfaceTexture};
use winit::event::*;
use winit::event::*;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::event_loop::{ControlFlow, EventLoop};
Line 5,332: Line 6,354:
}
}
});
});
}</lang>
}</syntaxhighlight>


=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Perl}}
{{trans|Perl}}
<lang ruby>var f = [[], DATA.lines.map {['', .chars..., '']}..., []];
<syntaxhighlight lang="ruby">var f = [[], DATA.lines.map {['', .chars..., '']}..., []]


10.times {
10.times {
say f.map { .join(" ") + "\n" }.join;
say f.map { .join(" ") + "\n" }.join
var a = [[]];
var a = [[]]
for y in (1 .. f.end-1) {
for y in (1 ..^ f.end) {
var r = f[y];
var r = f[y]
var rr = [''];
var rr = ['']
for x in (1 .. r.end-1) {
for x in (1 ..^ r.end) {
var c = r[x];
var c = r[x]
rr << (
rr << (
given(c) {
given(c) {
when('H') { 't' }
when('H') { 't' }
when('t') { '.' }
when('t') { '.' }
when('.') { <. H>[f.ft(y-1, y+1).map{.ft(x-1, x+1)...}.count('H') ~~ [1,2]] }
when('.') { <. H>[[f[y-1 .. y+1]].map{.[x-1 .. x+1]}.count('H') ~~ [1,2]] }
default { c }
default { c }
}
}
)
)
}
}
rr << '';
rr << ''
a << rr;
a << rr
}
}
f = [a..., []];
f = [a..., []]
}
}


Line 5,366: Line 6,388:
...
...
. .
. .
Ht.. ......</lang>
Ht.. ......</syntaxhighlight>


=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
Line 5,372: Line 6,394:


=={{header|Standard ML}}==
=={{header|Standard ML}}==
<lang sml>(* Maximilian Wuttke 12.04.2016 *)
<syntaxhighlight lang="sml">(* Maximilian Wuttke 12.04.2016 *)


type world = char vector vector
type world = char vector vector
Line 5,417: Line 6,439:
" ... ",
" ... ",
". . ",
". . ",
"Ht.. ......"]</lang>
"Ht.. ......"]</syntaxhighlight>


=={{header|Tcl}}==
=={{header|Tcl}}==
Line 5,427: Line 6,449:
to construct a two dimensional 3 by 3 sliding window.
to construct a two dimensional 3 by 3 sliding window.
The rule function maps a pair (cell,neighborhood) to a new cell.
The rule function maps a pair (cell,neighborhood) to a new cell.
<lang Ursala>#import std
<syntaxhighlight lang="ursala">#import std


rule = case~&l\~&l {`H: `t!, `t: `.!,`.: @r ==`H*~; {'H','HH'}?</`H! `.!}
rule = case~&l\~&l {`H: `t!, `t: `.!,`.: @r ==`H*~; {'H','HH'}?</`H! `.!}
Line 5,433: Line 6,455:
neighborhoods = ~&thth3hthhttPCPthPTPTX**K7S+ swin3**+ swin3@hNSPiCihNCT+ --<0>*+ 0-*
neighborhoods = ~&thth3hthhttPCPthPTPTX**K7S+ swin3**+ swin3@hNSPiCihNCT+ --<0>*+ 0-*


evolve "n" = @iNC ~&x+ rep"n" ^C\~& rule**+ neighborhoods@h</lang>
evolve "n" = @iNC ~&x+ rep"n" ^C\~& rule**+ neighborhoods@h</syntaxhighlight>
test program:
test program:
<lang Ursala>diode =
<syntaxhighlight lang="ursala">diode =


<
<
Line 5,444: Line 6,466:
#show+
#show+


example = mat0 evolve13 diode</lang>
example = mat0 evolve13 diode</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:15ex;overflow:scroll">
<pre style="height:15ex;overflow:scroll">
Line 5,502: Line 6,524:
......... ...
......... ...
..
..
</pre>

=={{header|Wren}}==
{{trans|Go}}
{{libheader|wren-fmt}}
{{libheader|Wren-ioutil}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
import "./ioutil" for FileUtil, Stdin

var rows = 0 // extent of input configuration
var cols = 0 // """
var rx = 0 // grid extent (includes border)
var cx = 0 // """
var mn = [] // offsets of Moore neighborhood

var print = Fn.new { |grid|
System.print("__" * cols)
System.print()
for (r in 1..rows) {
for (c in 1..cols) Fmt.write(" $s", grid[r*cx+c])
System.print()
}
}

var step = Fn.new { |dst, src|
for (r in 1..rows) {
for (c in 1..cols) {
var x = r*cx + c
dst[x] = src[x]
if (dst[x] == "H") {
dst[x] = "t"
} else if (dst[x] == "t") {
dst[x] = "."
} else if (dst[x] == ".") {
var nn = 0
for (n in mn) {
if (src[x+n] == "H") nn = nn + 1
}
if (nn == 1 || nn == 2) dst[x] = "H"
}
}
}
}

var srcRows = FileUtil.readLines("ww.config")
rows = srcRows.count
for (r in srcRows) {
if (r.count > cols) cols = r.count
}
rx = rows + 2
cx = cols + 2
mn = [-cx-1, -cx, -cx+1, -1, 1, cx-1, cx, cx+1]

// allocate two grids and copy input into first grid
var odd = List.filled(rx*cx, " ")
var even = List.filled(rx*cx, " ")

var ri = 0
for (r in srcRows) {
for (i in 0...r.count) {
odd[(ri+1)*cx+1+i] = r[i]
}
ri = ri + 1
}

// run
while (true) {
print.call(odd)
step.call(even, odd)
Stdin.readLine() // wait for enter to be pressed

print.call(even)
step.call(odd, even)
Stdin.readLine() // ditto
}</syntaxhighlight>

{{out}}
<pre>
Although not shown, same as Go output.
</pre>
</pre>


=={{header|XPL0}}==
=={{header|XPL0}}==
[[File:WireXPL0.gif|right]]
[[File:WireXPL0.gif|right]]
<lang XPL0>include c:\cxpl\codes; \intrinsic 'code' declarations
<syntaxhighlight lang="xpl0">include c:\cxpl\codes; \intrinsic 'code' declarations
char New(53,40), Old(53,40);
char New(53,40), Old(53,40);


Line 5,553: Line 6,654:
until KeyHit; \keystroke terminates program
until KeyHit; \keystroke terminates program
SetVid(3); \restore normal text mode
SetVid(3); \restore normal text mode
]</lang>
]</syntaxhighlight>


=={{header|Yabasic}}==
=={{header|Yabasic}}==
<lang Yabasic>open window 230,130
<syntaxhighlight lang="yabasic">open window 230,130
backcolor 0,0,0
backcolor 0,0,0
clear window
clear window
Line 5,617: Line 6,718:
wait .5
wait .5
loop
loop
</syntaxhighlight>
</lang>

Revision as of 10:10, 17 February 2024

Task
Wireworld
You are encouraged to solve this task according to the task description, using any language you may know.

Wireworld is a cellular automaton with some similarities to Conway's Game of Life.

It is capable of doing sophisticated computations with appropriate programs (it is actually Turing complete), and is much simpler to program for.

A Wireworld arena consists of a Cartesian grid of cells, each of which can be in one of four states. All cell transitions happen simultaneously.

The cell transition rules are this:

Input State Output State Condition
empty empty
electron head  electron tail 
electron tail  conductor
conductor electron head  if 1 or 2 cells in the neighborhood of the cell are in the state “electron head
conductor conductor otherwise


Task

Create a program that reads a Wireworld program from a file and displays an animation of the processing. Here is a sample description file (using "H" for an electron head, "t" for a tail, "." for a conductor and a space for empty) you may wish to test with, which demonstrates two cycle-3 generators and an inhibit gate:

tH.........
.   .
   ...
.   .
Ht.. ......

While text-only implementations of this task are possible, mapping cells to pixels is advisable if you wish to be able to display large designs. The logic is not significantly more complex.

11l

Translation of: Python
V allstates = ‘Ht. ’
V head      = allstates[0]
V tail      = allstates[1]
V conductor = allstates[2]
V empty     = allstates[3]

V w =
|‘tH.........
  .   .
     ...
  .   .
  Ht.. ......’

T WW
   [[Char]] world
   Int w
   Int h
   F (world, w, h)
      .world = world
      .w = w
      .h = h

F readfile(f)
   V world = f.map(row -> row.rtrim(Array[Char]("\r\n")))
   V height = world.len
   V width = max(world.map(row -> row.len))
   V nonrow = [‘ ’(‘ ’ * width)‘ ’]
   V world2 = nonrow [+] world.map(row -> ‘ ’String(row).ljust(@width)‘ ’) [+] nonrow
   V world3 = world2.map(row -> Array(row))
   R WW(world3, width, height)

F newcell(currentworld, x, y)
   V istate = currentworld[y][x]
   assert(istate C :allstates, ‘Wireworld cell set to unknown value "#."’.format(istate))
   V ostate = :empty
   I istate == :head
      ostate = :tail
   E I istate == :tail
      ostate = :conductor
   E I istate == :empty
      ostate = :empty
   E
      V n = sum([(-1, -1), (-1, +0), (-1, +1),
                 (+0, -1),           (+0, +1),
                 (+1, -1), (+1, +0), (+1, +1)].map((dx, dy) -> Int(@currentworld[@y + dy][@x + dx] == :head)))
      ostate = I n C 1..2 {:head} E :conductor
   R ostate

F nextgen(ww)
   V (world, width, height) = ww
   V newworld = copy(world)
   L(x) 1 .. width
      L(y) 1 .. height
         newworld[y][x] = newcell(world, x, y)
   R WW(newworld, width, height)

F world2string(ww)
   R ww.world[1 .< (len)-1].map(row -> (row[1 .< (len)-1]).join(‘’).rtrim((‘ ’, "\t", "\r", "\n"))).join("\n")

V ww = readfile(w.split("\n"))

L(gen) 10
   print(("\n#3 ".format(gen))‘’(‘=’ * (ww.w - 4))"\n")
   print(world2string(ww))
   ww = nextgen(ww)
Output:

  0 =======

tH.........
.   .
   ...
.   .
Ht.. ......

  1 =======

.tH........
H   .
   ...
H   .
t... ......

  2 =======

H.tH.......
t   .
   ...
t   .
.H.. ......

  3 =======

tH.tH......
.   H
   ...
.   .
HtH. ......

  4 =======

.tH.tH.....
H   t
   HHH
H   .
t.tH ......

  5 =======

H.tH.tH....
t   .
   ttt
t   .
.H.t ......

  6 =======

tH.tH.tH...
.   H
   ...
.   .
HtH. ......

  7 =======

.tH.tH.tH..
H   t
   HHH
H   .
t.tH ......

  8 =======

H.tH.tH.tH.
t   .
   ttt
t   .
.H.t ......

  9 =======

tH.tH.tH.tH
.   H
   ...
.   .
HtH. ......

Ada

with Ada.Text_IO;  use Ada.Text_IO;

procedure Test_Wireworld is
   type Cell is (' ', 'H', 't', '.');
   type Board is array (Positive range <>, Positive range <>) of Cell;
      -- Perform one transition of the cellular automation
   procedure Wireworld (State : in out Board) is
      function "abs" (Left : Cell) return Natural is
      begin
         if Left = 'H' then
            return 1;
         else
            return 0;
         end if;
      end "abs";
      Above   : array (State'Range (2)) of Cell := (others => ' ');
      Left    : Cell := ' '; 
      Current : Cell;
   begin
      for I in State'First (1) + 1..State'Last (1) - 1 loop
         for J in State'First (2) + 1..State'Last (2) - 1 loop
            Current := State (I, J);
            case Current is
               when ' ' =>
                  null;
               when 'H' =>
                  State (I, J) := 't';
               when 't' =>
                  State (I, J) := '.';
               when '.' =>
                  if abs Above (       J - 1) + abs Above (       J) + abs Above (       J + 1) +
                     abs Left                                        + abs State (I,     J + 1) + 
                     abs State (I + 1, J - 1) + abs State (I + 1, J) + abs State (I + 1, J + 1)
                  in 1..2 then
                     State (I, J) := 'H';
                  else
                     State (I, J) := '.';
                  end if;
            end case;
            Above (J - 1) := Left;
            Left := Current;
         end loop;
      end loop;
   end Wireworld;
      -- Print state of the automation
   procedure Put (State : Board) is
   begin
      for I in State'First (1) + 1..State'Last (1) - 1 loop
         for J in State'First (2) + 1..State'Last (2) - 1 loop
            case State (I, J) is
               when ' ' => Put (' ');
               when 'H' => Put ('H');
               when 't' => Put ('t');
               when '.' => Put ('.');
            end case;
         end loop;
         New_Line;
      end loop;
   end Put;
   Oscillator : Board := ("         ", "  tH     ", " .  .... ", "  ..     ", "         ");
begin
   for Step in 0..9 loop
      Put_Line ("Step" & Integer'Image (Step) & " ---------"); Put (Oscillator);
      Wireworld (Oscillator);
   end loop;
end Test_Wireworld;

The solution assumes that the border of the board is empty. When transition is performed these cells are not changed. Automation transition is an in-place operation that allocates memory for to keep one row of the board size.

Step 0 ---------
 tH
.  ....
 ..
Step 1 ---------
 .t
.  H...
 ..
Step 2 ---------
 ..
.  tH..
 .H
Step 3 ---------
 ..
.  .tH.
 Ht
Step 4 ---------
 ..
H  ..tH
 t.
Step 5 ---------
 H.
t  ...t
 ..
Step 6 ---------
 tH
.  ....
 ..
Step 7 ---------
 .t
.  H...
 ..
Step 8 ---------
 ..
.  tH..
 .H
Step 9 ---------
 ..
.  .tH.
 Ht

ALGOL 68

Translation of: python

- note: This specimen retains the original python coding style.

Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
CO
Wireworld implementation.
CO
 
PROC exception = ([]STRING args)VOID:(
  putf(stand error, ($"Exception"$, $", "g$, args, $l$));
  stop
);

PROC assertion error = (STRING message)VOID:exception(("assertion error", message));

MODE CELL = CHAR;
MODE WORLD = FLEX[0, 0]CELL;
CELL head="H", tail="t", conductor=".", empty = " ";
STRING all states := empty;

BOOL wrap = FALSE; # is the world round? #

STRING nl := REPR 10;
 
STRING in string := 
  "tH........."+nl+
  ".   ."+nl+
  "   ..."+nl+
  ".   ."+nl+
  "Ht.. ......"+nl
;
 
OP +:= = (REF FLEX[]FLEX[]CELL lines, FLEX[]CELL line)VOID:(
      [UPB lines + 1]FLEX[0]CELL new lines;
      new lines[:UPB lines]:=lines;
      lines := new lines;
      lines[UPB lines]:=line
);

PROC read file = (REF FILE in file)WORLD: (
    # file > initial world configuration" #
    FLEX[0]CELL line;
    FLEX[0]FLEX[0]CELL lines;
    INT upb x:=0, upb y := 0;
    BEGIN 
      # on physical file end(in file, exit read line); #
      make term(in file, nl);
      FOR x TO 5 DO
        get(in file, (line, new line));
        upb x := x;
        IF UPB line > upb y THEN upb y := UPB line FI;
        lines +:= line
      OD;
    exit read line: SKIP
    END;
    [upb x, upb y]CELL out;
    FOR x TO UPB out DO
      out[x,]:=lines[x]+" "*(upb y-UPB lines[x])
    OD;
    out
);
 
PROC new cell = (WORLD current world, INT x, y)CELL: (
    CELL istate := current world[x, y];
    IF INT pos; char in string (istate, pos, all states); pos IS REF INT(NIL) THEN 
        assertion error("Wireworld cell set to unknown value "+istate) FI;
    IF istate = head THEN
        tail
    ELIF istate = tail THEN
        conductor
    ELIF istate = empty THEN
        empty
    ELSE # istate = conductor #
        [][]INT dxy list = ( (-1,-1), (-1,+0), (-1,+1),
                             (+0,-1),          (+0,+1),
                             (+1,-1), (+1,+0), (+1,+1) );
        INT n := 0;
        FOR enum dxy TO UPB dxy list DO
          []INT dxy = dxy list[enum dxy];
          IF wrap THEN
            INT px = ( x + dxy[1] - 1 ) MOD 1 UPB current world + 1;
            INT py = ( y + dxy[2] - 1 ) MOD 2 UPB current world + 1;
            n +:= ABS (current world[px, py] = head)
          ELSE
            INT px = x + dxy[1];
            INT py = y + dxy[2];
            IF px >= 1 LWB current world AND px <= 1 UPB current world AND
               py >= 2 LWB current world AND py <= 2 UPB current world THEN
                 n +:= ABS (current world[px, py] = head)
            FI
          FI
        OD;
        IF 1 <= n AND n <= 2 THEN head ELSE conductor FI
    FI
);
 
PROC next gen = (WORLD world)WORLD:(
    # compute next generation of wireworld #
    WORLD new world := world;
    FOR x TO 1 UPB world DO
        FOR y TO 2 UPB world DO
            new world[x,y] := new cell(world, x, y)
        OD
    OD;
    new world
);
 
PROC world2string = (WORLD world) STRING:(
    STRING out:="";
    FOR x TO UPB world DO
      out +:= world[x,]+nl
    OD;
    out
);
 
FILE in file;
associate(in file, in string);

WORLD ww := read file(in file);
close(in file);
 
FOR gen TO 10 DO
    printf ( ($lg(-3)" "$, gen-1,  $g$,"="* (2 UPB ww-4), $l$));
    print ( world2string(ww) );
    ww := next gen(ww)
OD
Output:
  0 =======
tH.........
.   .      
   ...     
.   .      
Ht.. ......

  1 =======
.tH........
H   .      
   ...     
H   .      
t... ......

  2 =======
H.tH.......
t   .      
   ...     
t   .      
.H.. ......

  3 =======
tH.tH......
.   H      
   ...     
.   .      
HtH. ......

  4 =======
.tH.tH.....
H   t      
   HHH     
H   .      
t.tH ......

  5 =======
H.tH.tH....
t   .      
   ttt     
t   .      
.H.t ......

  6 =======
tH.tH.tH...
.   H      
   ...     
.   .      
HtH. ......

  7 =======
.tH.tH.tH..
H   t      
   HHH     
H   .      
t.tH ......

  8 =======
H.tH.tH.tH.
t   .      
   ttt     
t   .      
.H.t ......

  9 =======
tH.tH.tH.tH
.   H      
   ...     
.   .      
HtH. ......

AutoHotkey

Demo gif - Link, since uploads seem to be disabled currently.

Works with: AutoHotkey_L
Library: GDIP
#SingleInstance, Force
#NoEnv
SetBatchLines, -1
File := "Wireworld.txt"
CellSize := 20
CellSize2 := CellSize - 2
C1 := 0xff000000
C2 := 0xff0066ff
C3 := 0xffd40055
C4 := 0xffffcc00

if (!FileExist(File)) {
	MsgBox, % "File(" File ") is not present."
	ExitApp
}

; Uncomment if Gdip.ahk is not in your standard library
; #Include, Gdip.ahk
If !pToken := Gdip_Startup(){
	MsgBox, 48, Gdiplus error!, Gdiplus failed to start. Please ensure you have Gdiplus on your system.
	ExitApp
}
OnExit, Exit

A := [], Width := 0
Loop, Read, % File
{
	Row := A_Index
	Loop, Parse, A_LoopReadLine
	{
		if (A_Index > Width)
			Width := A_Index
		if (A_LoopField = A_Space)
			continue
		A[Row, A_Index] := A_LoopField
	}
}

Width := Width * CellSize + 2 * CellSize
, Height := Row * CellSize + 2 * CellSize
, Row := ""
, TopLeftX := (A_ScreenWidth - Width) // 2
, TopLeftY := (A_ScreenHeight - Height) // 2

Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA

hwnd1 := WinExist()
, hbm := CreateDIBSection(Width, Height)
, hdc := CreateCompatibleDC()
, obm := SelectObject(hdc, hbm)
, G := Gdip_GraphicsFromHDC(hdc)
, Gdip_SetSmoothingMode(G, 4)

Loop {
	pBrush := Gdip_BrushCreateSolid(C1)
	, Gdip_FillRectangle(G, pBrush, 0, 0, Width, Height)
	, Gdip_DeleteBrush(pBrush)

	for RowNum, Row in A
		for CellNum, Cell in Row
			C := Cell = "H" ? C2 : Cell = "t" ? C3 : C4
			, pBrush := Gdip_BrushCreateSolid(C)
			, Gdip_FillRectangle(G, pBrush, CellNum * CellSize + 1, RowNum * CellSize - 2, CellSize2, CellSize2)
			, Gdip_DeleteBrush(pBrush)
	

	UpdateLayeredWindow(hwnd1, hdc, TopLeftX, TopLeftY, Width, Height)
	, Gdip_GraphicsClear(G)
	, A := NextState(A)
	Sleep, 600
}

NextState(A) {
	B := {}
	for RowNum, Row in A {
		for CellNum, Cell in Row {
			if (Cell = "H")
				B[RowNum, CellNum] := "t"
			else if (Cell = "t")
				B[RowNum, CellNum] := "."
			else if (Cell = ".") {
				H_Count := 0
				Loop 3 {
					Y := RowNum - 2 + A_Index
					Loop, 3 {
						X := CellNum - 2 + A_Index
						if (A[Y, X] = "H")
							H_Count++
					}
				}
				if (H_Count = 1 || H_Count = 2)
					B[RowNum, CellNum] := "H"
				else
					B[RowNum, CellNum] := "."
			}
		}
	}
	return B
}

p::Pause

Esc::
Exit:
Gdip_Shutdown(pToken)
ExitApp

AutoIt

$ww = ""
$ww &= "tH........." & @CR
$ww &= ".   .      " & @CR
$ww &= "   ...     " & @CR
$ww &= ".   .      " & @CR
$ww &= "Ht.. ......"
$rows = StringSplit($ww, @CR)
$cols = StringSplit($rows[1], "")
Global $Wireworldarray[$rows[0]][$cols[0]]
For $I = 1 To $rows[0]
	$cols = StringSplit($rows[$I], "")
	For $k = 1 To $cols[0]
		$Wireworldarray[$I - 1][$k - 1] = $cols[$k]
	Next
Next
Wireworld($Wireworldarray)
Func Wireworld($array)
	Local $labelarray = $array
	Local $Top = 0, $Left = 0
	$hFui = GUICreate("Wireworld", UBound($array, 2) * 25, UBound($array) * 25)
	For $I = 0 To UBound($array) - 1
		For $k = 0 To UBound($array, 2) - 1
			Switch $array[$I][$k]
				Case "t" ; Tail
					$labelarray[$I][$k] = GUICtrlCreateButton("", $Left, $Top, 25, 25)
					GUICtrlSetBkColor($labelarray[$I][$k], 0xFF0000)
				Case "h" ; Head
					$labelarray[$I][$k] = GUICtrlCreateButton("", $Left, $Top, 25, 25)
					GUICtrlSetBkColor($labelarray[$I][$k], 0x0000FF)
				Case "." ; Conductor
					$labelarray[$I][$k] = GUICtrlCreateButton("", $Left, $Top, 25, 25)
					GUICtrlSetBkColor($labelarray[$I][$k], 0xFFFF00)
				Case " " ; Empty
					$labelarray[$I][$k] = GUICtrlCreateButton("", $Left, $Top, 25, 25)
					GUICtrlSetBkColor($labelarray[$I][$k], 0x000000)
			EndSwitch
			$Left += 25
		Next
		$Left = 0
		$Top += 25
	Next
	GUISetState()
	Local $nextsteparray = $array
	While 1
		$msg = GUIGetMsg()
		$array = $nextsteparray
		Sleep(250)
		For $I = 0 To UBound($array) - 1
			For $k = 0 To UBound($array, 2) - 1
				If $array[$I][$k] = " " Then ContinueLoop
				If $array[$I][$k] = "h" Then $nextsteparray[$I][$k] = "t"
				If $array[$I][$k] = "t" Then $nextsteparray[$I][$k] = "."
				If $array[$I][$k] = "." Then
					$counter = 0
					If $I - 1 >= 0 Then ; Top
						If $array[$I - 1][$k] = "h" Then $counter += 1
					EndIf
					If $k - 1 >= 0 Then ; left
						If $array[$I][$k - 1] = "h" Then $counter += 1
					EndIf
					If $I + 1 <= UBound($array) - 1 Then ; Bottom
						If $array[$I + 1][$k] = "h" Then $counter += 1
					EndIf
					If $k + 1 <= UBound($array, 2) - 1 Then ;Right
						If $array[$I][$k + 1] = "h" Then $counter += 1
					EndIf
					If $I - 1 >= 0 And $k - 1 >= 0 Then ; left Top
						If $array[$I - 1][$k - 1] = "h" Then $counter += 1
					EndIf
					If $I + 1 <= UBound($array) - 1 And $k + 1 <= UBound($array, 2) - 1 Then ; Right Bottom
						If $array[$I + 1][$k + 1] = "h" Then $counter += 1
					EndIf
					If $I + 1 <= UBound($array) - 1 And $k - 1 >= 0 Then ;Left Bottom
						If $array[$I + 1][$k - 1] = "h" Then $counter += 1
					EndIf
					If $I - 1 >= 0 And $k + 1 <= UBound($array, 2) - 1 Then ; Top Right
						If $array[$I - 1][$k + 1] = "h" Then $counter += 1
					EndIf
					If $counter = 1 Or $counter = 2 Then $nextsteparray[$I][$k] = "h"
				EndIf
			Next
		Next
		For $I = 0 To UBound($nextsteparray) - 1
			For $k = 0 To UBound($nextsteparray, 2) - 1
				Switch $nextsteparray[$I][$k]
					Case "t" ; Tail
						GUICtrlSetBkColor($labelarray[$I][$k], 0xFF0000)
					Case "h" ; Head
						GUICtrlSetBkColor($labelarray[$I][$k], 0x0000FF)
					Case "." ; Conductor
						GUICtrlSetBkColor($labelarray[$I][$k], 0xFFFF00)
					Case " " ; Empty
						GUICtrlSetBkColor($labelarray[$I][$k], 0x000000)
				EndSwitch
				$Left += 25
			Next
			$Left = 0
			$Top += 25
		Next
		If $msg = -3 Then Exit
	WEnd
EndFunc   ;==>Wireworld

BBC BASIC

      Size% = 20
      DIM P&(Size%-1,Size%-1), Q&(Size%-1,Size%-1)
      
      VDU 23,22,Size%*8;Size%*8;64,64,16,0
      OFF
      
      DATA "tH........."
      DATA ".   .      "
      DATA "   ...     "
      DATA ".   .      "
      DATA "Ht.. ......"
      
      FOR Y% = 12 TO 8 STEP -1
        READ A$
        FOR X% = 1 TO LEN(A$)
          P&(X%+4, Y%) = ASCMID$(A$, X%, 1) AND 15
        NEXT
      NEXT Y%
      
      COLOUR  8,0,0,255 : REM Electron head = blue
      COLOUR  4,255,0,0 : REM Electron tail = red
      COLOUR 14,255,200,0 : REM Conductor orange
      
      REPEAT
        FOR Y% = 1 TO Size%-2
          FOR X% = 1 TO Size%-2
            IF P&(X%,Y%)<>Q&(X%,Y%) GCOL P&(X%,Y%) : PLOT X%*16, Y%*16
            CASE P&(X%,Y%) OF
              WHEN 0: Q&(X%,Y%) = 0
              WHEN 8: Q&(X%,Y%) = 4
              WHEN 4: Q&(X%,Y%) = 14
              WHEN 14:
                T% = (P&(X%+1,Y%)=8) + (P&(X%+1,Y%+1)=8) + (P&(X%+1,Y%-1)=8) + \
                \    (P&(X%-1,Y%)=8) + (P&(X%-1,Y%+1)=8) + (P&(X%-1,Y%-1)=8) + \
                \    (P&(X%,Y%-1)=8) + (P&(X%,Y%+1)=8)
                IF T%=-1 OR T%=-2 THEN Q&(X%,Y%) = 8 ELSE Q&(X%,Y%) = 14
            ENDCASE
          NEXT
        NEXT Y%
        SWAP P&(), Q&()
        WAIT 50
      UNTIL FALSE

C

For big graphics version, see: Wireworld/C


Text version with optional animation on POSIX systems:

Library: POSIX
Works with: VT100

Compile with -D_POSIX_C_SOURCE=199309L or greater to make nanosleep visible in <time.h>.

/* 2009-09-27 <kaz@kylheku.com> */
#define ANIMATE_VT100_POSIX
#include <stdio.h>
#include <string.h>
#ifdef ANIMATE_VT100_POSIX
#include <time.h>
#endif

char world_7x14[2][512] = {
  {
    "+-----------+\n"
    "|tH.........|\n"
    "|.   .      |\n"
    "|   ...     |\n"
    "|.   .      |\n"
    "|Ht.. ......|\n"
    "+-----------+\n"
  }
};

void next_world(const char *in, char *out, int w, int h)
{
  int i;

  for (i = 0; i < w*h; i++) {
    switch (in[i]) {
    case ' ': out[i] = ' '; break;
    case 't': out[i] = '.'; break;
    case 'H': out[i] = 't'; break;
    case '.': {
      int hc = (in[i-w-1] == 'H') + (in[i-w] == 'H') + (in[i-w+1] == 'H') +
               (in[i-1]   == 'H')                    + (in[i+1]   == 'H') +
               (in[i+w-1] == 'H') + (in[i+w] == 'H') + (in[i+w+1] == 'H');
      out[i] = (hc == 1 || hc == 2) ? 'H' : '.';
      break;
    }
    default:
      out[i] = in[i];
    }
  }
  out[i] = in[i];
}

int main()
{
  int f;

  for (f = 0; ; f = 1 - f) {
    puts(world_7x14[f]);
    next_world(world_7x14[f], world_7x14[1-f], 14, 7);
#ifdef ANIMATE_VT100_POSIX
    printf("\x1b[%dA", 8);
    printf("\x1b[%dD", 14);
    {
      static const struct timespec ts = { 0, 100000000 };
      nanosleep(&ts, 0);
    }
#endif
  }

  return 0;
}

C#

See: Wireworld/C sharp

C++

Library: libggi

(for graphics)

Library: POSIX

(for usleep)

#include <ggi/ggi.h>
#include <set>
#include <map>
#include <utility>
#include <iostream>
#include <fstream>
#include <string>

#include <unistd.h> // for usleep

enum cell_type { none, wire, head, tail };

// *****************
// * display class *
// *****************

// this is just a small wrapper for the ggi interface

class display
{
public:
  display(int sizex, int sizey, int pixsizex, int pixsizey,
          ggi_color* colors);
  ~display()
  {
    ggiClose(visual);
    ggiExit();
  }

  void flush();
  bool keypressed() { return ggiKbhit(visual); }
  void clear();
  void putpixel(int x, int y, cell_type c);
private:
  ggi_visual_t visual;
  int size_x, size_y;
  int pixel_size_x, pixel_size_y;
  ggi_pixel pixels[4];
};

display::display(int sizex, int sizey, int pixsizex, int pixsizey,
                 ggi_color* colors):
  pixel_size_x(pixsizex),
  pixel_size_y(pixsizey)
{
  if (ggiInit() < 0)
  {
    std::cerr << "couldn't open ggi\n";
    exit(1);
  }

  visual = ggiOpen(NULL);
  if (!visual)
  {
    ggiPanic("couldn't open visual\n");
  }

  ggi_mode mode;
  if (ggiCheckGraphMode(visual, sizex, sizey,
                        GGI_AUTO, GGI_AUTO, GT_4BIT,
                        &mode) != 0)
  {
    if (GT_DEPTH(mode.graphtype) < 2) // we need 4 colors!
      ggiPanic("low-color displays are not supported!\n");
  }
  if (ggiSetMode(visual, &mode) != 0)
  {
    ggiPanic("couldn't set graph mode\n");
  }
  ggiAddFlags(visual, GGIFLAG_ASYNC);

  size_x = mode.virt.x;
  size_y = mode.virt.y;

  for (int i = 0; i < 4; ++i)
    pixels[i] = ggiMapColor(visual, colors+i);
}

void display::flush()
{
  // set the current display frame to the one we have drawn to
  ggiSetDisplayFrame(visual, ggiGetWriteFrame(visual));

  // flush the current visual
  ggiFlush(visual);

  // try to set a different frame for drawing (errors are ignored; if
  // setting the new frame fails, the current one will be drawn upon,
  // with the only adverse effect being some flickering).
  ggiSetWriteFrame(visual, 1-ggiGetDisplayFrame(visual));
}

void display::clear()
{
  ggiSetGCForeground(visual, pixels[0]);
  ggiDrawBox(visual, 0, 0, size_x, size_y);
}

void display::putpixel(int x, int y, cell_type cell)
{
  // this draws a logical pixel (i.e. a rectangle of size pixel_size_x
  // times pixel_size_y), not a physical pixel
  ggiSetGCForeground(visual, pixels[cell]);
  ggiDrawBox(visual,
             x*pixel_size_x, y*pixel_size_y,
             pixel_size_x, pixel_size_y);
}

// *****************
// * the wireworld *
// *****************

// initialized to an empty wireworld
class wireworld
{
public:
  void set(int posx, int posy, cell_type type);
  void draw(display& destination);
  void step();
private:
  typedef std::pair<int, int> position;
  typedef std::set<position> position_set;
  typedef position_set::iterator positer;
  position_set wires, heads, tails;
};

void wireworld::set(int posx, int posy, cell_type type)
{
  position p(posx, posy);
  wires.erase(p);
  heads.erase(p);
  tails.erase(p);
  switch(type)
  {
  case head:
    heads.insert(p);
    break;
  case tail:
    tails.insert(p);
    break;
  case wire:
    wires.insert(p);
    break;
  }
}

void wireworld::draw(display& destination)
{
  destination.clear();
  for (positer i = heads.begin(); i != heads.end(); ++i)
    destination.putpixel(i->first, i->second, head);
  for (positer i = tails.begin(); i != tails.end(); ++i)
    destination.putpixel(i->first, i->second, tail);
  for (positer i = wires.begin(); i != wires.end(); ++i)
    destination.putpixel(i->first, i->second, wire);
  destination.flush();
}

void wireworld::step()
{
  std::map<position, int> new_heads;
  for (positer i = heads.begin(); i != heads.end(); ++i)
    for (int dx = -1; dx <= 1; ++dx)
      for (int dy = -1; dy <= 1; ++dy)
      {
        position pos(i->first + dx, i->second + dy);
        if (wires.count(pos))
          new_heads[pos]++;
      }
  wires.insert(tails.begin(), tails.end());
  tails.swap(heads);
  heads.clear();
  for (std::map<position, int>::iterator i = new_heads.begin();
       i != new_heads.end();
       ++i)
  {
//     std::cout << i->second;
    if (i->second < 3)
    {
      wires.erase(i->first);
      heads.insert(i->first);
    }
  }
}

ggi_color colors[4] =
  {{ 0x0000, 0x0000, 0x0000 },  // background: black
   { 0x8000, 0x8000, 0x8000 },  // wire: white
   { 0xffff, 0xffff, 0x0000 },  // electron head: yellow
   { 0xffff, 0x0000, 0x0000 }}; // electron tail: red

int main(int argc, char* argv[])
{
  int display_x = 800;
  int display_y = 600;
  int pixel_x = 5;
  int pixel_y = 5;

  if (argc < 2)
  {
    std::cerr << "No file name given!\n";
    return 1;
  }

  // assume that the first argument is the name of a file to parse
  std::ifstream f(argv[1]);
  wireworld w;
  std::string line;
  int line_number = 0;
  while (std::getline(f, line))
  {
    for (int col = 0; col < line.size(); ++col)
    {
      switch (line[col])
      {
      case 'h': case 'H':
        w.set(col, line_number, head);
        break;
      case 't': case 'T':
        w.set(col, line_number, tail);
        break;
      case 'w': case 'W': case '.':
        w.set(col, line_number, wire);
        break;
      default:
        std::cerr << "unrecognized character: " << line[col] << "\n";
        return 1;
      case ' ':
        ; // no need to explicitly set this, so do nothing
      }
    }
    ++line_number;
  }

  display d(display_x, display_y, pixel_x, pixel_y, colors);

  w.draw(d);

  while (!d.keypressed())
  {
    usleep(100000);
    w.step();
    w.draw(d);
  }
  std::cout << std::endl;
}

Ceylon

abstract class Cell(shared Character char) of emptyCell | head | tail | conductor {

    shared Cell output({Cell*} neighbors) =>
            switch (this)
            case (emptyCell) emptyCell
            case (head) tail
            case (tail) conductor
            case (conductor) (neighbors.count(head.equals) in 1..2 then head else conductor);

    string => char.string;
}

object emptyCell extends Cell(' ') {}

object head extends Cell('H') {}

object tail extends Cell('t') {}

object conductor extends Cell('.') {}

Map<Character,Cell> cellsByChar = map { for (cell in `Cell`.caseValues) cell.char->cell };

class Wireworld(String data) {

    value lines = data.lines;

    value width = max(lines*.size);
    value height = lines.size;

    function toIndex(Integer x, Integer y) => x + y * width;

    variable value currentState = Array.ofSize(width * height, emptyCell);
    variable value nextState = Array.ofSize(width * height, emptyCell);

    for (j->line in lines.indexed) {
        for (i->char in line.indexed) {
            currentState[toIndex(i, j)] = cellsByChar[char] else emptyCell;
        }
    }

    value emptyGrid = Array.ofSize(width * height, emptyCell);
    void clear(Array<Cell> cells) => emptyGrid.copyTo(cells);

    shared void update() {
        clear(nextState);
        for(j in 0:height) {
            for(i in 0:width) {
                if(exists cell = currentState[toIndex(i, j)]) {
                    value nextCell = cell.output(neighborhood(currentState, i, j));
                    nextState[toIndex(i, j)] = nextCell;
                }
            }
        }
        value temp = currentState;
        currentState = nextState;
        nextState = temp;
    }

    shared void display() {
        for (row in currentState.partition(width)) {
            print("".join(row));
        }
    }

    shared {Cell*} neighborhood(Array<Cell> grid, Integer x, Integer y) => {
                for (j in y - 1..y + 1)
                for (i in x - 1..x + 1)
                if(i in 0:width && j in 0:height)
                grid[toIndex(i, j)]
            }.coalesced;

}

shared void run() {
    value data = "tH.........
                  .   .
                     ...
                  .   .
                  Ht.. ......";

    value world = Wireworld(data);

    variable value generation = 0;

    void display() {
        print("generation: ``generation``");
        world.display();
    }

    display();

    while (true) {
        if (exists input = process.readLine(), input.lowercased == "q") {
            return;
        }
        world.update();
        generation++;
        display();

    }
}

Common Lisp

(defun electron-neighbors (wireworld row col)
  (destructuring-bind (rows cols) (array-dimensions wireworld)
    (loop   for off-row from (max 0 (1- row)) to (min (1- rows) (1+ row)) sum
      (loop for off-col from (max 0 (1- col)) to (min (1- cols) (1+ col)) count
        (and (not (and (= off-row row) (= off-col col)))
             (eq 'electron-head (aref wireworld off-row off-col)))))))

(defun wireworld-next-generation (wireworld)
  (destructuring-bind (rows cols) (array-dimensions wireworld)
    (let ((backing (make-array (list rows cols))))
      (do ((c 0 (if (= c (1- cols)) 0 (1+ c)))
           (r 0 (if (= c (1- cols)) (1+ r) r)))
          ((= r rows))
        (setf (aref backing r c) (aref wireworld r c)))
      (do ((c 0 (if (= c (1- cols)) 0 (1+ c)))
           (r 0 (if (= c (1- cols)) (1+ r) r)))
          ((= r rows))
        (setf (aref wireworld r c)
              (case (aref backing r c)
                (electron-head 'electron-tail)
                (electron-tail 'conductor)
                (conductor (case (electron-neighbors backing r c)
                             ((1 2) 'electron-head)
                             (otherwise 'conductor)))
                (otherwise nil)))))))

(defun print-wireworld (wireworld)
  (destructuring-bind (rows cols) (array-dimensions wireworld)
    (do ((r 0 (1+ r)))
        ((= r rows))
      (do ((c 0 (1+ c)))
          ((= c cols))
        (format t "~C" (case (aref wireworld r c)
                         (electron-head #\H)
                         (electron-tail #\t)
                         (conductor #\.)
                         (otherwise #\Space))))
      (format t "~&"))))

(defun wireworld-show-gens (wireworld n)
  (dotimes (m n)
    (terpri)
    (wireworld-next-generation wireworld)
    (print-wireworld wireworld)))

(defun ww-char-to-symbol (char)
  (ecase char
    (#\Space 'nil)
    (#\.     'conductor)
    (#\t     'electron-tail)
    (#\H     'electron-head)))

(defun make-wireworld (image)
  "Make a wireworld grid from a list of strings (rows) of equal length
(columns), each character being ' ', '.', 'H', or 't'."
  (make-array (list (length image) (length (first image)))
              :initial-contents
              (mapcar (lambda (s) (map 'list #'ww-char-to-symbol s)) image)))

(defun make-rosetta-wireworld ()
  (make-wireworld '("tH........."
                    ".   .      "
                    "   ...     "
                    ".   .      "
                    "Ht.. ......")))
Output:
CL-USER> (wireworld-show-gens (make-rosetta-wireworld) 12)

.tH........
H   .      
   ...     
H   .      
t... ......

H.tH.......
t   .      
   ...     
t   .      
.H.. ......

tH.tH......
.   H      
   ...     
.   .      
HtH. ......

.tH.tH.....
H   t      
   HHH     
H   .      
t.tH ......

H.tH.tH....
t   .      
   ttt     
t   .      
.H.t ......

tH.tH.tH...
.   H      
   ...     
.   .      
HtH. ......

.tH.tH.tH..
H   t      
   HHH     
H   .      
t.tH ......

H.tH.tH.tH.
t   .      
   ttt     
t   .      
.H.t ......

tH.tH.tH.tH
.   H      
   ...     
.   .      
HtH. ......

.tH.tH.tH.t
H   t      
   HHH     
H   .      
t.tH ......

H.tH.tH.tH.
t   .      
   ttt     
t   .      
.H.t ......

tH.tH.tH.tH
.   H      
   ...     
.   .      
HtH. ......

D

import std.stdio, std.algorithm;

void wireworldStep(char[][] W1, char[][] W2) pure nothrow @safe @nogc {
    foreach (immutable r; 1 .. W1.length - 1)
        foreach (immutable c; 1 .. W1[0].length - 1)
            switch (W1[r][c]) {
                case 'H': W2[r][c] = 't'; break;
                case 't': W2[r][c] = '.'; break;
                case '.':
                    int nH = 0;
                    foreach (sr; -1 .. 2)
                        foreach (sc; -1 .. 2)
                            nH += W1[r + sr][c + sc] == 'H';
                    W2[r][c] = (nH == 1 || nH == 2) ? 'H' : '.';
                    break;
                default:
            }
}

void main() {
    auto world = ["         ".dup,
                  "  tH     ".dup,
                  " .  .... ".dup,
                  "  ..     ".dup,
                  "         ".dup];

    char[][] world2;
    foreach (row; world)
        world2 ~= row.dup;

    foreach (immutable step; 0 .. 7) {
        writefln("\nStep %d: ------------", step);
        foreach (row; world[1 .. $ - 1])
            row[1 .. $ - 1].writeln;
        wireworldStep(world, world2);
        swap(world, world2);
    }
}
Output:
Step 0: ------------
 tH    
.  ....
 ..    

Step 1: ------------
 .t    
.  H...
 ..    

Step 2: ------------
 ..    
.  tH..
 .H    

Step 3: ------------
 ..    
.  .tH.
 Ht    

Step 4: ------------
 ..    
H  ..tH
 t.    

Step 5: ------------
 H.    
t  ...t
 ..    

Step 6: ------------
 tH    
.  ....
 ..    

Delphi

Translation of: Go
program Wireworld;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.IOUtils;

var
  rows, cols: Integer;
  rx, cx: Integer;
  mn: TArray<Integer>;

procedure Print(grid: TArray<byte>);
begin
  writeln(string.Create('_', cols * 2), #10);

  for var r := 1 to rows do
  begin
    for var c := 1 to cols do
    begin
      if grid[r * cx + c] = 0 then
        write(' ')
      else
        write(' ', chr(grid[r * cx + c]));
    end;
    writeln;
  end;
end;

procedure Step(var dst: TArray<byte>; src: TArray<byte>);
begin
  for var r := 1 to rows do
  begin
    for var c := 1 to cols do
    begin
      var x := r * cx + c;
      dst[x] := src[x];

      case chr(dst[x]) of
        'H':
          dst[x] := ord('t');
        't':
          dst[x] := ord('.');
        '.':
          begin
            var nn := 0;
            for var n in mn do
              if src[x + n] = ord('H') then
                inc(nn);
            if (nn = 1) or (nn = 2) then
              dst[x] := ord('H');
          end;
      end;
    end;
  end;
end;

procedure Main();
const
  CONFIG_FILE = 'ww.config';
begin

  if not FileExists(CONFIG_FILE) then
  begin
    Writeln(CONFIG_FILE, ' not exist');
    exit;
  end;

  var srcRows := TFile.ReadAllLines(CONFIG_FILE);

  rows := length(srcRows);

  cols := 0;
  for var r in srcRows do
  begin
    if Length(r) > cols then
      cols := length(r);
  end;

  rx := rows + 2;
  cx := cols + 2;

  mn := [-cx - 1, -cx, -cx + 1, -1, 1, cx - 1, cx, cx + 1];

  var _odd: TArray<byte>;
  var _even: TArray<byte>;

  SetLength(_odd, rx * cx);
  SetLength(_even, rx * cx);

  FillChar(_odd[0], rx * cx, 0);
  FillChar(_even[0], rx * cx, 0);

  for var i := 0 to High(srcRows) do
  begin
    var r := srcRows[i];

    var offset := (i + 1) * cx + 1;
    for var j := 1 to length(r) do
      _odd[offset + j - 1] := ord(r[j]);
  end;

  while True do
  begin
    print(_odd);
    step(_even, _odd);
    Readln;

    print(_even);
    step(_odd, _even);
    Readln;
  end;
end;

begin
  Main;

  {$IFNDEF UNIX} readln; {$ENDIF}
end.
Output:
__________________


     t H
   .     . . . .
     . .


__________________


     . t
   .     H . . .
     . .


__________________


     . .
   .     t H . .
     . H


__________________


     . .
   .     . t H .
     H t


__________________


     . .
   H     . . t H
     t .


__________________


     H .
   t     . . . t
     . .


__________________


     t H
   .     . . . .
     . .


__________________


     . t
   .     H . . .
     . .

EasyLang

Run it

sys topleft
global m[] nc .
background 777
# 
proc show . .
   clear
   scale = 100 / nc
   sz = scale * 0.95
   for i to len m[]
      x = (i - 1) mod nc
      y = (i - 1) div nc
      move x * scale y * scale
      if m[i] = 0
         color 000
      elif m[i] = 1
         color 980
      elif m[i] = 2
         color 338
      else
         color 833
      .
      rect sz sz
   .
.
proc read . .
   s$ = input
   nc = len s$ + 2
   for i to nc
      m[] &= 0
   .
   repeat
      m[] &= 0
      for c$ in strchars s$
         if c$ = "."
            m[] &= 1
         elif c$ = "H"
            m[] &= 2
         elif c$ = "t"
            m[] &= 3
         else
            m[] &= 0
         .
      .
      for i to nc - len s$ - 1
         m[] &= 0
      .
      s$ = input
      until s$ = ""
   .
   for i to nc
      m[] &= 0
   .
.
read
# 
len mn[] len m[]
# 
proc update . .
   for i to len m[]
      if m[i] = 2
         mn[i] = 3
      elif m[i] = 3
         mn[i] = 1
      elif m[i] = 1
         s = 0
         for dx = -1 to 1
            for dy = -1 to 1
               ix = i + dy * nc + dx
               s += if m[ix] = 2
            .
         .
         if s = 2 or s = 1
            mn[i] = 2
         else
            mn[i] = 1
         .
      .
   .
   swap mn[] m[]
.
on timer
   update
   show
   timer 0.5
.
show
timer 0.5
# 
input_data
tH.........
.   .
   ...
.   .
Ht.. ......


Elena

ELENA 6.x, using cellular library

import system'routines;
import extensions;
import cellular;
 
const string sample = 
" tH......
.        ......
 ...Ht...      .
              ....
              .  .....
              ....
 ......tH      .
.        ......
 ...Ht...";
 
const string conductorLabel = ".";
const string headLabel = "H";
const string tailLabel = "t";
const string emptyLabel = " ";
 
const int empty = 0;
const int conductor = 1;
const int electronHead = 2;
const int electronTail = 3;
 
wireWorldRuleSet = new RuleSet
{
    int proceed(Space s, int x, int y)
    {
        int cell := s.at(x, y);
 
        cell =>
            conductor 
            {
                int number := s.LiveCell(x, y, electronHead);
                if (number == 1 || number == 2)
                {
                    ^ electronHead
                }
                else
                {
                    ^ conductor
                }                
            }
            electronHead 
            {
                ^ electronTail
            }
            electronTail
            {
                ^ conductor
            }
            !{
                ^ cell
            }
    }
};
 
sealed class Model
{
    Space   theSpace;
 
    constructor load(string stateString, int maxX, int maxY)
    {
        var strings := stateString.splitBy(newLineConstant).selectBy::(s => s.toArray()).toArray();
 
        theSpace := IntMatrixSpace.allocate(maxX, maxY, RuleSet
        {
            int proceed(Space s, int x, int y)
            {
                int retVal := 0;
                if (x < strings.Length)
                {
                    var l := strings[x];
                    if (y < l.Length)
                    {
                        (l[y]) =>
                            conductorLabel { retVal := conductor }
                            headLabel      { retVal := electronHead }
                            tailLabel      { retVal := electronTail }
                            emptyLabel     { retVal := empty }
                    }
                    else
                    {
                        retVal := empty
                    }                 
                }
                else
                {
                    retVal := empty
                };
 
                ^ retVal
            }
        })
    }
 
    run()
    {
        theSpace.update(wireWorldRuleSet)
    }    
 
    print()
    {
        int columns := theSpace.Columns;
        int rows := theSpace.Rows;
 
        int i := 0;
        int j := 0;
        while (i < rows)
        {
            j := 0;
 
            while (j < columns)
            {
                var label := emptyLabel;
                int cell := theSpace.at(i, j);
 
                cell =>
                    conductor    { label := conductorLabel }
                    electronHead { label := headLabel }
                    electronTail { label := tailLabel };
 
                console.write(label);
 
                j := j + 1
            };
 
            i := i + 1;
            console.writeLine()
        }
    }
}
 
public program()
{
    Model model := Model.load(sample,10,30);
    for(int i := 0; i < 10; i += 1)
    {
        console.printLineFormatted("Iteration {0}",i);
        model.print().run()
    }    
}
Output:
Iteration 0
 tH......                     
.        ......               
 ...Ht...      .              
              ....            
              .  .....        
              ....            
 ......tH      .              
.        ......               
 ...Ht...                     
                              
Iteration 1
 .tH.....                     
.        ......               
 ..Ht....      .              
              ....            
              .  .....        
              ....            
 .......t      .              
.        H.....               
 ..Ht....                     
                              
Iteration 2
 ..tH....                     
.        ......               
 .Ht.....      .              
              ....            
              .  .....        
              ....            
 ........      .              
.        tH....               
 .Ht....H                     
                              
Iteration 3
 ...tH...                     
.        ......               
 Ht......      .              
              ....            
              .  .....        
              ....            
 ........      .              
.        .tH...               
 Ht....Ht                     

/* ... */
                              
Iteration 9
 ...tH...                     
.        .tH...               
 ......Ht      .              
              ....            
              H  H....        
              tttH            
 ...tH...      .              
.        ......               
 Ht......                     

Elixir

Translation of: Ruby
defmodule Wireworld do
  @empty      " "
  @head       "H"
  @tail       "t"
  @conductor  "."
  @neighbours (for x<- -1..1, y <- -1..1, do: {x,y}) -- [{0,0}]
  
  def set_up(string) do
    lines = String.split(string, "\n", trim: true)
    grid = Enum.with_index(lines)
           |> Enum.flat_map(fn {line,i} ->
                String.codepoints(line)
                |> Enum.with_index
                |> Enum.map(fn {char,j} -> {{i, j}, char} end)
              end)
           |> Enum.into(Map.new)
    width = Enum.map(lines, fn line -> String.length(line) end) |> Enum.max
    height = length(lines)
    {grid, width, height}
  end
  
  # to string
  defp to_s(grid, width, height) do
    Enum.map_join(0..height-1, fn i ->
      Enum.map_join(0..width-1, fn j -> Map.get(grid, {i,j}, @empty) end) <> "\n"
    end)
  end
 
  # transition all cells simultaneously
  defp transition(grid) do
    Enum.into(grid, Map.new, fn {{x, y}, state} ->
      {{x, y}, transition_cell(grid, state, x, y)}
    end)
  end
  
  # how to transition a single cell
  defp transition_cell(grid, current, x, y) do
    case current do
      @empty -> @empty
      @head  -> @tail
      @tail  -> @conductor
      _      -> if neighbours_with_state(grid, x, y) in 1..2, do: @head, else: @conductor
    end
  end
  
  # given a position in the grid, find the neighbour cells with a particular state
  def neighbours_with_state(grid, x, y) do
    Enum.count(@neighbours, fn {dx,dy} -> Map.get(grid, {x+dx, y+dy}) == @head end)
  end
  
  # run a simulation up to a limit of transitions, or until a recurring
  # pattern is found
  # This will print text to the console
  def run(string, iterations\\25) do
    {grid, width, height} = set_up(string)
    Enum.reduce(0..iterations, {grid, %{}}, fn count,{grd, seen} ->
      IO.puts "Generation : #{count}"
      IO.puts to_s(grd, width, height)
 
      if seen[grd] do
        IO.puts "I've seen this grid before... after #{count} iterations"
        exit(:normal)
      else
        {transition(grd), Map.put(seen, grd, count)}
      end
    end)
    IO.puts "ran through #{iterations} iterations"
  end
end

# this is the "2 Clock generators and an XOR gate" example from the wikipedia page
text = """
 ......tH
.        ......
 ...Ht...      .
              ....
              .  .....
              ....
 tH......      .
.        ......
 ...Ht...
"""
 
Wireworld.run(text)
Output:
Generation : 0
 ......tH             
.        ......       
 ...Ht...      .      
              ....    
              .  .....
              ....    
 tH......      .      
.        ......       
 ...Ht...             

Generation : 1
 .......t             
.        H.....       
 ..Ht....      .      
              ....    
              .  .....
              ....    
 .tH.....      .      
.        ......       
 ..Ht....             

Generation : 2
 ........             
.        tH....       
 .Ht....H      .      
              ....    
              .  .....
              ....    
 ..tH....      .      
.        ......       
 .Ht.....             

Generation : 3
 ........             
.        .tH...       
 Ht....Ht      .      
              ....    
              .  .....
              ....    
 ...tH...      .      
.        ......       
 Ht......             

Generation : 4
 ........             
H        ..tH..       
 t....Ht.      .      
              ....    
              .  .....
              ....    
 ....tH..      .      
H        ......       
 t.......             

Generation : 5
 H.......             
t        ...tH.       
 ....Ht..      .      
              ....    
              .  .....
              ....    
 H....tH.      .      
t        ......       
 ........             

Generation : 6
 tH......             
.        ....tH       
 ...Ht...      .      
              ....    
              .  .....
              ....    
 tH....tH      .      
.        ......       
 ........             

Generation : 7
 .tH.....             
.        .....t       
 ..Ht....      H      
              ....    
              .  .....
              ....    
 .tH....t      .      
.        H.....       
 ........             

Generation : 8
 ..tH....             
.        ......       
 .Ht.....      t      
              HHH.    
              .  .....
              ....    
 ..tH....      .      
.        tH....       
 .......H             

Generation : 9
 ...tH...             
.        ......       
 Ht......      .      
              tttH    
              H  H....
              ....    
 ...tH...      .      
.        .tH...       
 ......Ht             

Generation : 10
 ....tH..             
H        ......       
 t.......      .      
              ...t    
              t  tH...
              HHHH    
 ....tH..      .      
.        ..tH..       
 .....Ht.             

Generation : 11
 H....tH.             
t        ......       
 ........      .      
              ....    
              .  .tH..
              tttt    
 .....tH.      .      
.        ...tH.       
 ....Ht..             

Generation : 12
 tH....tH             
.        ......       
 ........      .      
              ....    
              .  ..tH.
              ....    
 ......tH      .      
.        ....tH       
 ...Ht...             

Generation : 13
 .tH....t             
.        H.....       
 ........      .      
              ....    
              .  ...tH
              ....    
 .......t      H      
.        H....t       
 ..Ht....             

Generation : 14
 ..tH....             
.        tH....       
 .......H      .      
              ....    
              .  ....t
              HHH.    
 ........      t      
.        tH....       
 .Ht....H             

Generation : 15
 ...tH...             
.        .tH...       
 ......Ht      .      
              ....    
              H  H....
              tttH    
 ........      .      
.        .tH...       
 Ht....Ht             

Generation : 16
 ....tH..             
.        ..tH..       
 .....Ht.      .      
              HHHH    
              t  tH...
              ...t    
 ........      .      
H        ..tH..       
 t....Ht.             

Generation : 17
 .....tH.             
.        ...tH.       
 ....Ht..      .      
              tttt    
              .  .tH..
              ....    
 H.......      .      
t        ...tH.       
 ....Ht..             

Generation : 18
 ......tH             
.        ....tH       
 ...Ht...      .      
              ....    
              .  ..tH.
              ....    
 tH......      .      
.        ....tH       
 ...Ht...             

Generation : 19
 .......t             
.        H....t       
 ..Ht....      H      
              ....    
              .  ...tH
              ....    
 .tH.....      H      
.        .....t       
 ..Ht....             

Generation : 20
 ........             
.        tH....       
 .Ht....H      t      
              HHH.    
              .  ....t
              HHH.    
 ..tH....      t      
.        ......       
 .Ht.....             

Generation : 21
 ........             
.        .tH...       
 Ht....Ht      .      
              tttH    
              .  H....
              tttH    
 ...tH...      .      
.        ......       
 Ht......             

Generation : 22
 ........             
H        ..tH..       
 t....Ht.      .      
              ...t    
              .  t....
              ...t    
 ....tH..      .      
H        ......       
 t.......             

Generation : 23
 H.......             
t        ...tH.       
 ....Ht..      .      
              ....    
              .  .....
              ....    
 H....tH.      .      
t        ......       
 ........             

I've seen this grid before... after 23 iterations

F#

// Wireworld. Nigel Galloway: January 22nd., 2024
type Cell= |E |T |H |C
let n=array2D [[T;H;C;C;C;C;C;C;C;C;C];
               [C;E;E;E;C;E;E;E;E;E;E];
               [E;E;E;C;C;C;E;E;E;E;E];
               [C;E;E;E;C;E;E;E;E;E;E];
               [H;T;C;C;E;C;C;C;C;C;C]]
let fG n g=match n|>Seq.sumBy(fun n->match Array2D.get g (fst n) (snd n) with H->1 |_->0) with 1 |2->H |_->C
let fX i=i|>Array2D.mapi(fun n g->function |E->E |H->T |T->C |C->fG (Seq.allPairs [max 0 (n-1)..min (n+1) (Array2D.length1 i-1)] [max 0 (g-1)..min (g+1) (Array2D.length2 i-1)]) i)
Seq.unfold(fun n->Some(n,fX n))n|>Seq.take 15|>Seq.iteri(fun n g->printfn "%d:\n%A\n" n g)
Output:

after 7: 8,9,10 are repeated as 11,12,13 then 14,15,16 etc

0:
[[T; H; C; C; C; C; C; C; C; C; C]
 [C; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [C; E; E; E; C; E; E; E; E; E; E]
 [H; T; C; C; E; C; C; C; C; C; C]]

1:
[[C; T; H; C; C; C; C; C; C; C; C]
 [H; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [H; E; E; E; C; E; E; E; E; E; E]
 [T; C; C; C; E; C; C; C; C; C; C]]

2:
[[H; C; T; H; C; C; C; C; C; C; C]
 [T; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [T; E; E; E; C; E; E; E; E; E; E]
 [C; H; C; C; E; C; C; C; C; C; C]]

3:
[[T; H; C; T; H; C; C; C; C; C; C]
 [C; E; E; E; H; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [C; E; E; E; C; E; E; E; E; E; E]
 [H; T; H; C; E; C; C; C; C; C; C]]

4:
[[C; T; H; C; T; H; C; C; C; C; C]
 [H; E; E; E; T; E; E; E; E; E; E]
 [E; E; E; H; H; H; E; E; E; E; E]
 [H; E; E; E; C; E; E; E; E; E; E]
 [T; C; T; H; E; C; C; C; C; C; C]]

5:
[[H; C; T; H; C; T; H; C; C; C; C]
 [T; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; T; T; T; E; E; E; E; E]
 [T; E; E; E; C; E; E; E; E; E; E]
 [C; H; C; T; E; C; C; C; C; C; C]]

6:
[[T; H; C; T; H; C; T; H; C; C; C]
 [C; E; E; E; H; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [C; E; E; E; C; E; E; E; E; E; E]
 [H; T; H; C; E; C; C; C; C; C; C]]

7:
[[C; T; H; C; T; H; C; T; H; C; C]
 [H; E; E; E; T; E; E; E; E; E; E]
 [E; E; E; H; H; H; E; E; E; E; E]
 [H; E; E; E; C; E; E; E; E; E; E]
 [T; C; T; H; E; C; C; C; C; C; C]]

8:
[[H; C; T; H; C; T; H; C; T; H; C]
 [T; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; T; T; T; E; E; E; E; E]
 [T; E; E; E; C; E; E; E; E; E; E]
 [C; H; C; T; E; C; C; C; C; C; C]]

9:
[[T; H; C; T; H; C; T; H; C; T; H]
 [C; E; E; E; H; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [C; E; E; E; C; E; E; E; E; E; E]
 [H; T; H; C; E; C; C; C; C; C; C]]

10:
[[C; T; H; C; T; H; C; T; H; C; T]
 [H; E; E; E; T; E; E; E; E; E; E]
 [E; E; E; H; H; H; E; E; E; E; E]
 [H; E; E; E; C; E; E; E; E; E; E]
 [T; C; T; H; E; C; C; C; C; C; C]]

11:
[[H; C; T; H; C; T; H; C; T; H; C]
 [T; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; T; T; T; E; E; E; E; E]
 [T; E; E; E; C; E; E; E; E; E; E]
 [C; H; C; T; E; C; C; C; C; C; C]]

12:
[[T; H; C; T; H; C; T; H; C; T; H]
 [C; E; E; E; H; E; E; E; E; E; E]
 [E; E; E; C; C; C; E; E; E; E; E]
 [C; E; E; E; C; E; E; E; E; E; E]
 [H; T; H; C; E; C; C; C; C; C; C]]

13:
[[C; T; H; C; T; H; C; T; H; C; T]
 [H; E; E; E; T; E; E; E; E; E; E]
 [E; E; E; H; H; H; E; E; E; E; E]
 [H; E; E; E; C; E; E; E; E; E; E]
 [T; C; T; H; E; C; C; C; C; C; C]]

14:
[[H; C; T; H; C; T; H; C; T; H; C]
 [T; E; E; E; C; E; E; E; E; E; E]
 [E; E; E; T; T; T; E; E; E; E; E]
 [T; E; E; E; C; E; E; E; E; E; E]
 [C; H; C; T; E; C; C; C; C; C; C]]

Forth

16 constant w
 8 constant h

: rows    w * 2* ;
1 rows constant row
h rows constant size

create world size allot
world   value old
old w + value new

: init   world size erase ;
: age    new old to new to old ;

: foreachrow ( xt -- )
  size 0 do  I over execute  row +loop drop ;

0 constant EMPTY
1 constant          HEAD
2 constant                    TAIL
3 constant                              WIRE
create cstate bl c, char H c, char t c, char . c,

: showrow ( i -- ) cr
  old + w over + swap do I c@ cstate + c@ emit loop ;
: show  ['] showrow foreachrow  ;


: line ( row addr len -- )
  bounds do
    i c@
    case
    bl of EMPTY over c! endof
    'H of HEAD  over c! endof
    't of TAIL  over c! endof
    '. of WIRE  over c! endof
    endcase
    1+
  loop drop ;

: load ( filename -- )
  r/o open-file throw
  init  old row + 1+  ( file row )
  begin  over pad 80 rot read-line throw
  while  over pad rot line
         row +
  repeat
  2drop close-file throw
  show cr ;


: +head ( sum i -- sum )
  old + c@ HEAD = if 1+ then ;
: conductor ( i WIRE -- i HEAD|WIRE )
  drop 0
  over 1- row - +head
  over    row - +head
  over 1+ row - +head
  over 1-       +head
  over 1+       +head
  over 1- row + +head
  over    row + +head
  over 1+ row + +head
  1 3 within if HEAD else WIRE then ;

\ before:          empty    head   tail   wire

create transition  ' noop , ' 1+ , ' 1+ , ' conductor ,

\ after:           empty    tail   wire   head|wire

: new-state ( i -- )
  dup  old + c@
  dup cells transition + @ execute
  swap new + c! ;

: newrow ( i -- )
  w over + swap do I new-state loop ;
: gen  ['] newrow foreachrow  age ;

: wireworld begin gen 0 0 at-xy show key? until ;
Output:
s" wireworld.diode" load
                
        ..      
 tH...... .Ht   
        ..      
                
                
                
                
 ok
gen show                
                
        ..      
 .tH..... Ht.   
        ..      
                
                
                
                 ok
gen show 
                
        .H      
 ..tH.... t..   
        .H      
                
                
                
                 ok
gen show 
                
        Ht      
 ...tH..H ...   
        Ht      
                
                
                
                 ok
gen show 
                
        t.      
 ....tH.t ...   
        t.      
                
                
                
                 ok
gen show 
                
        ..      
 .....tH. ...   
        ..      
                
                
                
                 ok
gen show 
                
        H.      
 ......tH ...   
        H.      
                
                
                
                 ok
gen show 
                
        tH      
 .......t ...   
        tH      
                
                
                
                 ok
gen show 
                
        .t      
 ........ H..   
        .t      
                
                
                
                 ok
gen show 
                
        ..      
 ........ tH.   
        ..      
                
                
                
                 ok
gen show 
                
        ..      
 ........ .tH   
        ..      
                
                
                
                 ok
gen show 
                
        ..      
 ........ ..t   
        ..      
                
                
                
                 ok
gen show 
                
        ..      
 ........ ...   
        ..      
                
                
                
                 ok

Fortran

Works with: Fortran version 95 and later
program Wireworld
  implicit none
 
  integer, parameter :: max_generations = 12
  integer :: nrows = 0, ncols = 0, maxcols = 0
  integer :: gen, ierr = 0
  integer :: i, j
  character(1), allocatable :: cells(:,:)
  character(10) :: form, sub
  character(80) :: buff

! open input file
  open(unit=8, file="wwinput.txt")
    
! find numbers of rows and columns in data
  do 
    read(8, "(a)", iostat=ierr) buff
    if(ierr /= 0) exit
    nrows = nrows + 1
    ncols = len_trim(buff)
    if(ncols > maxcols) maxcols = ncols
  end do

! allcate enough space to hold the data  
  allocate(cells(0:nrows+1, 0:maxcols+1))
  cells = " "

! load data
  rewind(8)
  do i = 1, nrows
    read(8, "(a)", iostat=ierr) buff
    if(ierr /= 0) exit
    do j = 1, maxcols
      cells(i, j) = buff(j:j)
    end do
  end do
  close(8)

! calculate format string for write statement
  write(sub, "(i8)") maxcols
  form = "(" // trim(adjustl(sub)) // "a1)"
       
  do gen = 0, max_generations
    write(*, "(/a, i0)") "Generation ", gen
    do i = 1, nrows
      write(*, form) cells(i, 1:maxcols)
    end do
    call nextgen(cells)
  end do
  deallocate(cells)
  
 contains
  
  subroutine Nextgen(cells)
    character, intent(in out) :: cells(0:,0:)
    character :: buffer(0:size(cells, 1)-1, 0:size(cells, 2)-1)
    integer :: i, j, h
   
     buffer = cells   ! Store current status
     do i = 1, size(cells, 1)-2
        do j = 1, size(cells, 2)-2
          select case (buffer(i, j))
            case(" ")
              ! no Change
                
            case("H")
              ! If a head change to tail  
              cells(i, j) = "t"
   
            case("t")
              ! if a tail change to conductor
              cells(i, j) = "."
   
            case (".")
              ! Count number of electron heads in surrounding eight cells.
              ! We can ignore that fact that we count the centre cell as
              ! well because we already know it contains a conductor.
              ! If surrounded by 1 or 2 heads change to a head
              h = sum(count(buffer(i-1:i+1, j-1:j+1) == "H", 1)) 
              if(h == 1 .or. h == 2) cells(i, j) = "H"
          end select       
        end do
     end do
  end subroutine Nextgen
end program Wireworld
Output:
Generation 0
  tH...
 .     .
....... ......
 .     .
  tH...
 
Generation 1
  .tH..
 .     .
....... ......
 .     .
  .tH..
 
Generation 2
  ..tH.
 .     .
....... ......
 .     .
  ..tH.
 
Generation 3
  ...tH
 .     .
....... ......
 .     .
  ...tH
 
Generation 4
  ....t
 .     H
....... ......
 .     H
  ....t
 
Generation 5
  .....
 .     t
......H H.....
 .     t
  .....
 
Generation 6
  .....
 .     .
.....Ht tH....
 .     .
  .....
 
Generation 7
  .....
 .     .
....Ht. .tH...
 .     .
  .....
 
Generation 8
  .....
 .     .
...Ht.. ..tH..
 .     .
  .....
 
Generation 9
  .....
 .     .
..Ht... ...tH.
 .     .
  .....
 
Generation 10
  .....
 H     .
.Ht.... ....tH
 H     .
  .....
 
Generation 11
  H....
 t     .
.t..... .....t
 t     .
  H....
 
Generation 12
  tH...
 .     .
....... ......
 .     .
  tH...

FreeBASIC

#define MAXX 319
#define MAXY 199

enum state
   E=0, C=8, H=9, T=4   'doubles as colours: black, grey, bright blue, red
end enum

dim as uinteger world(0 to 1, 0 to MAXX, 0 to MAXY), active = 0, buffer = 1
dim as double rate = 1./3.   'seconds per frame
dim as double tick
dim as uinteger x, y

function turn_on( world() as unsigned integer, x as uinteger, y as uinteger, a as uinteger ) as boolean
    dim as ubyte n = 0
    dim as integer qx, qy
    for qx = -1 to 1
        for qy = -1 to 1
            if qx=0 andalso qy=0 then continue for
            if world(a,(x+qx+MAXX+1) mod (MAXX+1), (y+qy+MAXY+1) mod (MAXY+1))=H then n=n+1  'handles wrap-around
        next qy
    next qx
    if n=1 then return true
    if n=2 then return true
    return false
end function

'generate sample map

for x=20 to 30
    world(active, x, 20) = C
    world(active, x, 24) = C
next x
world(active, 24, 24 ) = E
world(active, 20, 21 ) = C
world(active, 20, 23 ) = C
world(active, 24, 21 ) = C
world(active, 23, 22 ) = C
world(active, 24, 22 ) = C
world(active, 25, 22 ) = C
world(active, 24, 23 ) = C
world(active, 20, 20 ) = T
world(active, 21, 20 ) = H
world(active, 21, 24 ) = T
world(active, 20, 24 ) = H

screen 12

do
    tick = timer
    for x = 0 to 319
        for y = 0 to 199
            pset (x,y), world(active, x, y)
            if world(active,x,y) = E then world(buffer,x,y) = E   'empty cells stay empty
            if world(active,x,y) = H then world(buffer,x,y) = T   'electron heads turn into electron tails
            if world(active,x,y) = T then world(buffer,x,y) = C   'electron tails revert to conductors
            if world(active,x,y) = C then 
                if turn_on(world(),x,y,active) then 
                    world(buffer,x,y) = H                         'maybe electron heads spread
                else  
                    world(buffer,x,y) = C                         'otherwise condutor remains conductor
                end if
            end if
        next y
    next x
    while tick + rate > timer
    wend
    cls
    buffer = 1 - buffer
    active = 1 - buffer
loop

GML

Only visual output. Not an all-out simulator, but has some functions not on by default.

//Create event
/*
Wireworld first declares constants and then reads a wireworld from a textfile.
In order to implement wireworld in GML a single array is used.
To make it behave properly, there need to be states that are 'in-between' two states:
0 = empty
1 = conductor from previous state
2 = electronhead from previous state
5 = electronhead that was a conductor in the previous state
3 = electrontail from previous state
4 = electrontail that was a head in the previous state
*/
empty = 0;
conduc = 1;
eHead = 2;
eTail = 3;
eHead_to_eTail = 4;
coduc_to_eHead = 5;
working = true;//not currently used, but setting it to false stops wireworld. (can be used to pause)
toroidalMode = false;
factor = 3;//this is used for the display. 3 means a single pixel is multiplied by three in size.

var tempx,tempy ,fileid, tempstring, gridid, listid, maxwidth, stringlength;
tempx = 0;
tempy = 0;
tempstring = "";
maxwidth = 0;

//the next piece of code loads the textfile containing a wireworld.
//the program will not work correctly if there is no textfile.
if file_exists("WW.txt")
{
fileid = file_text_open_read("WW.txt");
gridid = ds_grid_create(0,0);
listid = ds_list_create();
    while !file_text_eof(fileid)
    {
    tempstring = file_text_read_string(fileid);
    stringlength = string_length(tempstring);
    ds_list_add(listid,stringlength);
        if maxwidth < stringlength
        {
        ds_grid_resize(gridid,stringlength,ds_grid_height(gridid) + 1)
        maxwidth = stringlength
        }
        else
        {
        ds_grid_resize(gridid,maxwidth,ds_grid_height(gridid) + 1)
        }
        
        for (i = 1; i <= stringlength; i +=1)
        {
            switch (string_char_at(tempstring,i))
            {
            case ' ': ds_grid_set(gridid,tempx,tempy,empty); break;
            case '.': ds_grid_set(gridid,tempx,tempy,conduc); break;
            case 'H': ds_grid_set(gridid,tempx,tempy,eHead); break;
            case 't': ds_grid_set(gridid,tempx,tempy,eTail); break;
            default: break;
            }
        tempx += 1;
        }
    file_text_readln(fileid);
    tempy += 1;
    tempx = 0;
    }
file_text_close(fileid);
//fill the 'open' parts of the grid
tempy = 0;
    repeat(ds_list_size(listid))
    {
    tempx = ds_list_find_value(listid,tempy);
        repeat(maxwidth - tempx)
        {
        ds_grid_set(gridid,tempx,tempy,empty);
        tempx += 1;
        }
    tempy += 1;
    }
boardwidth = ds_grid_width(gridid);
boardheight = ds_grid_height(gridid);
//the contents of the grid are put in a array, because arrays are faster.
//the grid was needed because arrays cannot be resized properly.
tempx = 0;
tempy = 0;
    repeat(boardheight)
    {
        repeat(boardwidth)
        {
        board[tempx,tempy] = ds_grid_get(gridid,tempx,tempy);
        tempx += 1;
        }
    tempy += 1;
    tempx = 0;
    }
//the following code clears memory
ds_grid_destroy(gridid);
ds_list_destroy(listid);
}

Now the step event

//Step event
/*
This step event executes each 1/speed seconds.
It checks everything on the board using an x and a y through two repeat loops.
The variables westN,northN,eastN,southN, resemble the space left, up, right and down respectively, 
seen from the current x & y.
1 -> 5 (conductor is changing to head)
2 -> 4 (head is changing to tail)
3 -> 1 (tail became conductor)
*/

var tempx,tempy,assignhold,westN,northN,eastN,southN,neighbouringHeads,T;
tempx = 0;
tempy = 0;
westN = 0;
northN = 0;
eastN = 0;
southN = 0;
neighbouringHeads = 0;
T = 0;

if working = 1
{
    repeat(boardheight)
    {
        repeat(boardwidth)
        {
            switch board[tempx,tempy]
            {
            case empty: assignhold = empty; break;
            case conduc:
                neighbouringHeads = 0;
                if toroidalMode = true //this is disabled, but otherwise lets wireworld behave toroidal.
                {
                    if tempx=0
                    {
                    westN = boardwidth -1;
                    }
                    else 
                    {
                    westN = tempx-1;
                    }
                    if tempy=0
                    {
                    northN = boardheight -1;
                    }
                    else 
                    {
                    northN = tempy-1;
                    }
                    if tempx=boardwidth -1
                    {
                    eastN = 0;
                    }
                    else 
                    {
                    eastN = tempx+1;
                    }
                    if tempy=boardheight -1
                    {
                    southN = 0;
                    }
                    else 
                    {
                    southN = tempy+1;
                    }

                T=board[westN,northN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[tempx,northN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[eastN,northN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[westN,tempy];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[eastN,tempy];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[westN,southN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[tempx,southN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                T=board[eastN,southN];
                    if T=eHead or T=eHead_to_eTail
                    {
                    neighbouringHeads += 1;
                    }
                }
                else//this is the default mode that works for the provided example.
                {//the next code checks whether coordinates fall outside the array borders.
                //and counts all the neighbouring electronheads.
                    if tempx=0
                    {
                    westN = -1;
                    }
                    else 
                    {
                    westN = tempx - 1;
                    T=board[westN,tempy];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if tempy=0
                    {
                    northN = -1;
                    }
                    else 
                    {
                    northN = tempy - 1;
                    T=board[tempx,northN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if tempx = boardwidth -1
                    {
                    eastN = -1;
                    }
                    else 
                    {
                    eastN = tempx + 1;
                    T=board[eastN,tempy];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if tempy = boardheight -1
                    {
                    southN = -1;
                    }
                    else 
                    {
                    southN = tempy + 1;
                    T=board[tempx,southN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    
                    if westN != -1 and northN != -1
                    {
                    T=board[westN,northN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if eastN != -1 and northN != -1
                    {
                    T=board[eastN,northN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if westN != -1 and southN != -1
                    {
                    T=board[westN,southN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                    if eastN != -1 and southN != -1
                    {
                    T=board[eastN,southN];
                        if T=eHead or T=eHead_to_eTail
                        {
                        neighbouringHeads += 1;
                        }
                    }
                }
                    if neighbouringHeads = 1 or neighbouringHeads = 2
                    {
                    assignhold = coduc_to_eHead;
                    }
                    else 
                    {
                    assignhold = conduc;
                    }
                break;
                
            case eHead: assignhold = eHead_to_eTail; break;
            case eTail: assignhold = conduc; break;
            default: break;
            }
        board[tempx,tempy] = assignhold;
        tempx += 1;
        }
    tempy += 1;
    tempx = 0;
    }
}

Now the draw event

//Draw event
/*
This event occurs whenever the screen is refreshed.
It checks everything on the board using an x and a y through two repeat loops and draws it.
It is an important step, because all board values are changed to the normal versions:
5 -> 2 (conductor changed to head)
4 -> 3 (head changed to tail)
*/
//draw sprites and text first

//now draw wireworld
var tempx,tempy;
tempx = 0;
tempy = 0;

repeat(boardheight)
{
    repeat(boardwidth)
    {
        switch board[tempx,tempy]
            {
            case empty: 
            //draw_point_color(tempx,tempy,c_black); 
            draw_set_color(c_black);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            break;
            case conduc: 
            //draw_point_color(tempx,tempy,c_yellow); 
            draw_set_color(c_yellow);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            break;
            case eHead:
            //draw_point_color(tempx,tempy,c_red);
            draw_set_color(c_blue);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            draw_rectangle_color(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,c_red,c_red,c_red,c_red,false);
            break;
            case eTail: 
            //draw_point_color(tempx,tempy,c_blue);
            draw_set_color(c_red);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            break;
            case coduc_to_eHead:
            //draw_point_color(tempx,tempy,c_red);
            draw_set_color(c_blue);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            board[tempx,tempy] = eHead;
            break;
            case eHead_to_eTail: 
            //draw_point_color(tempx,tempy,c_blue);
            draw_set_color(c_red);
            draw_rectangle(tempx*factor,tempy*factor,(tempx+1)*factor-1,(tempy+1)*factor-1,false);
            board[tempx,tempy] = eTail; 
            break;
            default: break;
            }
    tempx += 1
    }
tempy += 1;
tempx = 0;
}
draw_set_color(c_black);

Go

Text output. Press Enter to compute and display successive generations.

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "strings"
)

var rows, cols int // extent of input configuration
var rx, cx int     // grid extent (includes border)
var mn []int       // offsets of moore neighborhood

func main() {
    // read input configuration from file
    src, err := ioutil.ReadFile("ww.config")
    if err != nil {
        fmt.Println(err)
        return
    }
    srcRows := bytes.Split(src, []byte{'\n'})

    // compute package variables
    rows = len(srcRows)
    for _, r := range srcRows {
        if len(r) > cols {
            cols = len(r)
        }
    }
    rx, cx = rows+2, cols+2
    mn = []int{-cx-1, -cx, -cx+1, -1, 1, cx-1, cx, cx+1}

    // allocate two grids and copy input into first grid
    odd := make([]byte, rx*cx)
    even := make([]byte, rx*cx)
    for ri, r := range srcRows {
        copy(odd[(ri+1)*cx+1:], r)
    }

    // run
    for {
        print(odd)
        step(even, odd)
        fmt.Scanln()

        print(even)
        step(odd, even)
        fmt.Scanln()
    }
}

func print(grid []byte) {
    fmt.Println(strings.Repeat("__", cols))
    fmt.Println()
    for r := 1; r <= rows; r++ {
        for c := 1; c <= cols; c++ {
            if grid[r*cx+c] == 0 {
                fmt.Print("  ")
            } else {
                fmt.Printf(" %c", grid[r*cx+c])
            }
        }
        fmt.Println()
    }
}

func step(dst, src []byte) {
    for r := 1; r <= rows; r++ {
        for c := 1; c <= cols; c++ {
            x := r*cx + c
            dst[x] = src[x]
            switch dst[x] {
            case 'H':
                dst[x] = 't'
            case 't':
                dst[x] = '.'
            case '.':
                var nn int
                for _, n := range mn {
                    if src[x+n] == 'H' {
                        nn++
                    }
                }
                if nn == 1 || nn == 2 {
                    dst[x] = 'H'
                }
            }
        }
    }
}

Haskell

import Data.List
import Control.Monad
import Control.Arrow
import Data.Maybe

states=" Ht."
shiftS=" t.."

borden bc xs = bs: (map (\x -> bc:(x++[bc])) xs) ++ [bs]
   where r = length $ head xs
         bs = replicate (r+2) bc

take3x3 = ap ((.). taken. length) (taken. length. head) `ap` borden '*'
   where taken n =  transpose. map (take n.map (take 3)).map tails

nwState xs | e =='.' && noH>0 && noH<3 = 'H' 
           | otherwise = shiftS !! (fromJust $ elemIndex e states) 
   where e = xs!!1!!1
         noH = length $ filter (=='H') $ concat xs

runCircuit = iterate (map(map nwState).take3x3)

Example executed in GHCi:

oscillator= [" tH    ",
             ".  ....",
             " ..    "
            ]

example = mapM_ (mapM_ putStrLn) .map (borden ' ').take 9 $ runCircuit oscillator
Output:
*Main> example

  tH
 .  ....
  ..


  .t
 .  H...
  ..


  ..
 .  tH..
  .H


  ..
 .  .tH.
  Ht


  ..
 H  ..tH
  t.


  H.
 t  ...t
  ..


  tH
 .  ....
  ..


  .t
 .  H...
  ..


  ..
 .  tH..
  .H

(0.01 secs, 541764 bytes)

Icon and Unicon

Animated GIF enlarged 10x

This simulation starts in single step mode and can be switched to run uninterrupted. The window can be saved at any point in single step mode. This uses 1 pixel per cell so this animation looks tiny. Also the orientation has been flipped.

link graphics

$define EDGE  -1
$define EMPTY 0
$define HEAD 1
$define TAIL 2
$define COND 3

global Colours,Width,Height,World,oldWorld

procedure main()             # wire world modified from forestfire

    Height := 400            # Window height 
    Width  := 400            # Window width
    Rounds := 500            # max Rounds
    Delay  := 5              # Runout Delay
    
    setup_world(read_world())  
    every round := 1 to Rounds do {   
       show_world()
       if \runout then 
          delay(Delay) 
       else 
          case Event() of {
             "q" : break                            # q = quit
             "r" : runout := 1                      # r = run w/o stepping
             "s" : WriteImage("Wireworld-"||round)  # save
              }
       evolve_world()
       }
    WDone()
end  

procedure read_world()  #: for demo in place of reading
   return [ "tH.........",
            ".   .",
            "   ...",
            ".   .",
            "Ht.. ......"]
end 
    
procedure setup_world(L)     #: setup the world

    Colours := table()       # define colours
    Colours[EDGE]  := "grey"
    Colours[EMPTY] := "black"
    Colours[HEAD]  := "blue"
    Colours[TAIL]  := "red"
    Colours[COND]  := "yellow"
    
    States := table()
    States["t"] := TAIL
    States["H"] := HEAD
    States[" "] := EMPTY
    States["."] := COND
    
    WOpen("label=Wireworld", "bg=black",
          "size=" || Width+2 || "," || Height+2) | # add for border
             stop("Unable to open Window")
    every !(World := list(Height)) := list(Width,EMPTY)  # default
    every ( World[1,1 to Width]  | World[Height,1 to Width] | 
            World[1 to Height,1] | World[1 to Height,Width] ) := EDGE
            
    every r := 1 to *L & c := 1 to *L[r] do {      # setup read in program
       World[r+1, c+1] :=  States[L[r,c]]
       }
end

procedure show_world()      #: show World - drawn changes only
   every r := 2 to *World-1 & c := 2 to *World[r]-1 do
      if /oldWorld | oldWorld[r,c] ~= World[r,c] then {
         WAttrib("fg=" || Colours[tr := World[r,c]]) 
         DrawPoint(r,c)
      }
end

procedure evolve_world()    #: evolve world
    old := oldWorld := list(*World)     # freeze copy 
    every old[i := 1 to *World] := copy(World[i])  # deep copy

    every r := 2 to *World-1 & c := 2 to *World[r]-1 do 
       World[r,c] := case old[r,c] of {   # apply rules 
        # EMPTY : EMPTY
          HEAD  : TAIL
          TAIL  : COND
          COND  : {
              i := 0
              every HEAD = ( old[r-1,c-1 to c+1] | old[r,c-1|c+1] | old[r+1,c-1 to c+1] ) do i +:= 1
              if i := 1 | 2 then HEAD
          }
       }          
end

graphics.icn provides graphics

J

The example circuit:

circ0=:}: ] ;. _1 LF, 0 : 0
tH........
.   .     
   ...    
.   .     
Ht.. .....
)

A 'boarding' verb board and the next cell state verb nwS:

board=: ' ' ,.~ ' ' ,. ' ' , ' ' ,~ ]

nwS=: 3 : 0
  e=. (<1 1){y
  if. ('.'=e)*. e.&1 2 +/'H'=,y do. 'H' return. end.
  ' t..' {~ ' Ht.' i. e
)

The 'most' powerful part is contained in the following iterating sentence, namely the dyad cut ;. [1]. In this way verb nwS can work on all the 3x3 matrices containing each cell surrounded by its 8 relevant neighbors.

 process=: (3 3 nwS;. _3 board)^:
(<10) process circuit

Example run:

   (<10) process circ0
tH........
.   .     
   ...    
.   .     
Ht.. .....

.tH.......
H   .     
   ...    
H   .     
t... .....

H.tH......
t   .     
   ...    
t   .     
.H.. .....

tH.tH.....
.   H     
   ...    
.   .     
HtH. .....

.tH.tH....
H   t     
   HHH    
H   .     
t.tH .....

H.tH.tH...
t   .     
   ttt    
t   .     
.H.t .....

tH.tH.tH..
.   H     
   ...    
.   .     
HtH. .....

.tH.tH.tH.
H   t     
   HHH    
H   .     
t.tH .....

H.tH.tH.tH
t   .     
   ttt    
t   .     
.H.t .....

tH.tH.tH.t
.   H     
   ...    
.   .     
HtH. .....

Note also that a graphical presentation can be achieved using viewmat. For example:

require'viewmat'
viewmat"2 ' .tH'i. (<10) process circ0

(This example opens 10 windows, one for each generation.)

Java

See: Wireworld/Java

JavaScript

You have to search and open the file manually.
This is the HTML you need to test.

<!DOCTYPE html><html><head><meta charset="UTF-8">
<title>Wireworld</title>
<script src="wireworld.js"></script></head><body>
<input type='file' accept='text/plain' onchange='openFile( event )' />
<br /></body></html>
var ctx, sizeW, sizeH, scl = 10, map, tmp;
function getNeighbour( i, j ) {
    var ii, jj, c = 0;
    for( var b = -1; b < 2; b++ ) {
        for( var a = -1; a < 2; a++ ) {
            ii = i + a; jj = j + b;
            if( ii < 0 || ii >= sizeW || jj < 0 || jj >= sizeH ) continue;
            if( map[ii][jj] == 1 ) c++;
        }
    }
    return ( c == 1 || c == 2 );
}
function simulate() {
    drawWorld();
    for( var j = 0; j < sizeH; j++ ) {
        for( var i = 0; i < sizeW; i++ ) {
            switch( map[i][j] ) {
                case 0: tmp[i][j] = 0; break;
                case 1: tmp[i][j] = 2; break;
                case 2: tmp[i][j] = 3; break;
                case 3: 
                    if( getNeighbour( i, j ) ) tmp[i][j] = 1;
                    else tmp[i][j] = 3;
                break;
            }
        }
    }
    [tmp, map] = [map, tmp]; 
    setTimeout( simulate, 200 );
}
function drawWorld() {
    ctx.fillStyle = "#000"; ctx.fillRect( 0, 0, sizeW * scl, sizeH * scl );
    for( var j = 0; j < sizeH; j++ ) {
        for( var i = 0; i < sizeW; i++ ) {
            switch( map[i][j] ) {
                case 0: continue;
                case 1: ctx.fillStyle = "#03f"; break;
                case 2: ctx.fillStyle = "#f30"; break;
                case 3: ctx.fillStyle = "#ff3"; break;
            }
            ctx.fillRect( i, j, 1, 1 );
        }
    }
}
function openFile( event ) {
    var input = event.target;
    var reader = new FileReader();
    reader.onload = function() {
        createWorld( reader.result );
    };
    reader.readAsText(input.files[0]);
}
function createWorld( txt ) {
    var l = txt.split( "\n" );
    sizeW = parseInt( l[0] );
    sizeH = parseInt( l[1] );
    map = new Array( sizeW );
    tmp = new Array( sizeW );
    for( var i = 0; i < sizeW; i++ ) {
        map[i] = new Array( sizeH );
        tmp[i] = new Array( sizeH );
        for( var j = 0; j < sizeH; j++ ) {
            map[i][j] = tmp[i][j] = 0;
        }
    }
    var t;
    for( var j = 0; j < sizeH; j++ ) {
        for( var i = 0; i < sizeW; i++ ) {
            switch( l[j + 2][i] ) {
                case " ": t = 0; break;
                case "H": t = 1; break;
                case "t": t = 2; break;
                case ".": t = 3; break;
            }
            map[i][j] = t;
        }
    }
    init();
}
function init() {
    var canvas = document.createElement( "canvas" );
    canvas.width = sizeW * scl;
    canvas.height = sizeH * scl;
    ctx = canvas.getContext( "2d" );
    ctx.scale( scl, scl );
    document.body.appendChild( canvas );
    simulate();
}

jq

Works with: jq version 1.4

In this implementation, a "world" is simply a string as illustrated by world9 and world11 below. The "game" can be played either by creating separate frames (using frames(n)), or by calling animation(n; sleep) with sleep approximately equal to the number of milliseconds between refreshes.

"Animation" is based on the ANSI escape sequence for "clear screen".

Notes on the implementation:

  • For efficiency, the implementation requires that the world has boundaries, as illustrated by world11 below.
  • For speed, the simulation uses the exploded string (an array).
  • The ASCII values of the symbols used to display the state are hardcoded.
def lines: split("\n")|length;

def cols: split("\n")[0]|length + 1;  # allow for the newline

# Is there an "H" at [x,y] relative to position i, assuming the width is w?
# Input is an array; 72 is "H"
def isH(x; y; i; w): if .[i+ w*y + x] == 72 then 1 else 0 end;

def neighborhood(i;w):
  isH(-1; -1; i; w) + isH(0; -1; i; w) + isH(1; -1; i; w) +
  isH(-1;  0; i; w)                    + isH(1;  0; i; w) +
  isH(-1;  1; i; w) + isH(0;  1; i; w) + isH(1;  1; i; w) ;

# The basic rules:
# Input: a world
# Output: the next state of .[i]
def evolve(i; width) : 
  # "Ht. " | explode => [ 72,  116,  46,  32 ]
  .[i] as $c
  | if   $c ==  32 then $c           # " " => " "
    elif $c == 116 then 46           # "t" => "."
    elif $c ==  72 then 116          # "H" => "t"
    elif $c ==  46 then              # "."
      # updates are "simultaneous" i.e. relative to $world
      neighborhood(i; width) as $sum
      | (if [1,2]|index($sum) then 72 else . end)  # "H"
    else $c
    end ;

# [world, lines, cols] | next(w) => [world, lines, cols]
def next:
  .[0] as $world | .[1] as $lines | .[2] as $w
  | reduce range(0; $world|length) as $i
    ($world;
      $world | evolve($i; $w) as $next
      | if  .[$i] == $next then . else .[$i] = $next end )
  | [., $lines, $w] ; #

Animation

# "clear screen":
def cls: "\u001b[2J";

# Input: an integer; 1000 ~ 1 sec
def spin:
  reduce range(1; 500 * .) as $i
    (0; . + ($i|cos)*($i|cos) + ($i|sin)*($i|sin) )
  |  "" ;

# Animate n steps;
# if "sleep" is non-negative then cls and 
# sleep about "sleep" ms between frames.
def animate(n; sleep):
  if n == 0 then empty
  else (if sleep >= 0 then cls else "" end),
       (.[0]|implode), n, "\n",
       (sleep|spin),
       ( next|animate(n-1; sleep) )
  end ;

# Input: a string representing the initial state
def animation(n; sleep):
  [ explode, lines, cols] | animate(n; sleep) ;

# Input: a string representing the initial state
def frames(n):  animation(n; -1);#

Examples:

def world11:
"+-----------+\n" +
"|tH.........|\n" +
"|.   .      |\n" +
"|   ...     |\n" +
"|.   .      |\n" +
"|Ht.. ......|\n" +
"+-----------+\n" ;

def world9:
"         \n" +
"  tH     \n" +
" .  .... \n" +
"  ..     \n" +
"         \n" ;

Illustration 1:

# Ten-step animation with about 1 sec between frames
world9 | animation(10; 1000)

Illustration 2:

# Ten frames in sequence:
world11 | frames(10)

To run: jq -n -r -f wireworld.rc

Julia

function surround2D(b, i, j)
    h, w = size(b)
    [b[x,y] for x in i-1:i+1, y in j-1:j+1 if (0 < x <= h && 0 < y <= w)]
end

surroundhas1or2(b, i, j) = 0 < sum(map(x->Char(x)=='H', surround2D(b, i, j))) <= 2 ? 'H' : '.'
  
function boardstep!(currentboard, nextboard)
    x, y = size(currentboard)
    for j in 1:y, i in 1:x
        ch = Char(currentboard[i, j])
        if ch == ' '
            continue
        else
            nextboard[i, j] = (ch == 'H') ? 't' : (ch == 't' ? '.' : 
                   surroundhas1or2(currentboard, i, j))
        end
    end
end

const b1 = "         " * 
           "  tH     " * 
           " .  .... " *
           "  ..     " *
           "         "
const mat = reshape(map(x->UInt8(x[1]), split(b1, "")), (9, 5))'
const mat2 = copy(mat)

function printboard(mat)
    for i in 1:size(mat)[1]
        println("\t", join([Char(c) for c in mat[i,:]], ""))
    end
end

println("Starting Wireworld board:")
printboard(mat)
for step in 1:8
    boardstep!(mat, mat2)
    println(" Step $step:")
    printboard(mat2)
    mat .= mat2
end
Output:

Starting Wireworld board:

         tH
        .  ....
         ..
Step 1:
         .t
        .  H...
         ..
Step 2:
         ..
        .  tH..
         .H
Step 3:
         ..
        .  .tH.
         Ht
Step 4:
         ..
        H  ..tH
         t.
Step 5:
         H.
        t  ...t
         ..
Step 6:
         tH
        .  ....
         ..
Step 7:
         .t
        .  H...
         ..
Step 8:
         ..
        .  tH..
         .H

Liberty BASIC

WindowWidth  = 840
WindowHeight = 600

dim p$( 40, 25), q$( 40, 25)

empty$     = " "    '   white
tail$      = "t"    '   yellow
head$      = "H"    '   black
conductor$ = "."    '   red

jScr       = 0

nomainwin

menu #m, "File", "Load", [load], "Quit", [quit]

open "wire world" for graphics_nf_nsb as #m
  #m "trapclose [quit]"
  'timer 1000, [tmr]
  wait

end

[quit]
  close #m
  end

[load]
  'timer 0
  filedialog "Open WireWorld File", "*.ww", file$
  open file$ for input as #in
    y =0
    while not( eof( #in))
      line input #in, lijn$
      ' print "|"; lijn$; "|"
      for x =0 to len( lijn$) -1
        p$( x, y) =mid$( lijn$, x +1, 1)

        select case p$( x, y)
            case " "
                clr$ ="white"
            case "t"
                clr$ ="yellow"
            case "H"
                clr$ ="black"
            case "."
                clr$ ="red"
        end select

        #m "goto " ; 4 +x *20; " "; 4 +y *20
        #m "backcolor "; clr$
        #m "down"
        #m "boxfilled "; 4 +x *20 +19; " "; 4 +y *20 +19
        #m "up ; flush"
      next x
      y =y +1
    wend
  close #in
  'notice "Ready to run."
  timer 1000, [tmr]
  wait

[tmr]
  timer 0
  scan

  for x =0 to 40                                '   copy temp array /current array
    for y =0 to 25
      q$( x, y) =p$( x, y)
    next y
  next x

  for y =0 to 25
    for x =0 to 40
      select case q$( x, y)
        case head$                              '   heads ( black) become tails ( yellow)
          p$( x, y ) =tail$
          clr$ ="yellow"

        case tail$                              '   tails ( yellow) become conductors ( red)
          p$( x, y ) =conductor$
          clr$ ="red"

        case conductor$                         '
          hCnt =0

          xL =x -1: if xL < 0 then xL =40       '   wrap-round edges at all four sides
          xR =x +1: if xR >40 then xR = 0
          yA =y -1: if yA < 0 then yA =25
          yB =y +1: if yB >40 then yB = 0

          if q$( xL, y ) =head$ then hCnt =hCnt +1  '   Moore environment- 6 neighbours
          if q$( xL, yA) =head$ then hCnt =hCnt +1  '   count all neighbours currently heads
          if q$( xL, yB) =head$ then hCnt =hCnt +1

          if q$( xR, y ) =head$ then hCnt =hCnt +1
          if q$( xR, yA) =head$ then hCnt =hCnt +1
          if q$( xR, yB) =head$ then hCnt =hCnt +1

          if q$( x,  yA) =head$ then hCnt =hCnt +1
          if q$( x,  yB) =head$ then hCnt =hCnt +1

          if ( hCnt =1) or ( hCnt =2) then       '      conductor ( red) becomes head ( yellow) in this case only
            p$( x, y ) =head$                    '          otherwise stays conductor ( red).
            clr$ ="black"
          else
            p$( x, y ) =conductor$
            clr$ ="red"
          end if

        case else
          clr$ ="white"
      end select

      #m "goto " ; 4 +x *20; " "; 4 +y *20
      #m "backcolor "; clr$
      #m "down"
      #m "boxfilled "; 4 +x *20 +19; " "; 4 +y *20 +19
      #m "up"
    next x
  next y
  #m "flush"
  #m "getbmp scr 0 0 400 300"

  'bmpsave "scr", "R:\scrJHF" +right$( "000" +str$( jScr), 3) +".bmp"
  jScr =jScr+1
  if jScr >20 then wait
  timer 1000, [tmr]
wait

Works with: MSWlogo

(The wireworld given in the file must be bounded by spaces for the program to work. Also it is notable that the program takes the width as the longest of the lines.)

to wireworld :filename :speed ;speed in n times per second, approximated
Make "speed 60/:speed
wireworldread :filename
Make "bufferfield (mdarray (list :height :width) 0)
for [i 0 :height-1] [for [j 0 :width-1] [mdsetitem (list :i :j) :bufferfield mditem (list :i :j) :field]]
pu ht
Make "gen 0
while ["true] [ ;The user will have to halt it :P
    ;clean
    seth 90
    setxy 0 20
    ;label :gen
    sety 0
    for [i 0 :height-1] [for [j 0 :width-1] [mdsetitem (list :i :j) :field mditem (list :i :j) :bufferfield]]
    for [i 0 :height-1] [
        for [j 0 :width-1] [
            if (mditem (list :i :j) :field)=[] [setpixel [255 255 255]] ;blank
            if (mditem (list :i :j) :field)=1 [setpixel [0 0 0] if wn :j :i 2 [mdsetitem (list :i :j) :bufferfield 2]] ;wire
            if (mditem (list :i :j) :field)=2 [setpixel [0 0 255] mdsetitem (list :i :j) :bufferfield 3] ;head
            if (mditem (list :i :j) :field)=3 [setpixel [255 0 0] mdsetitem (list :i :j) :bufferfield 1] ;tail
            setx xcor+1
        ]
        setxy 0 ycor-1
    ]
    Make "gen :gen+1
    wait :speed
]
end

to wireworldread :filename
local [line]
openread :filename
setread :filename
Make "width 0
Make "height 0
; first pass, take dimensions
while [not eofp] [
    Make "line readword
    if (count :line)>:width [Make "width count :line]
    Make "height :height+1
]
; second pass, load data
setreadpos 0
Make "field (mdarray (list :height :width) 0)
for [i 0 :height-1] [
    Make "line readword
    foreach :line [
        if ?=char 32 [mdsetitem (list :i #-1) :field []]
        if ?=".      [mdsetitem (list :i #-1) :field 1]
        if ?="H      [mdsetitem (list :i #-1) :field 2]
        if ?="t      [mdsetitem (list :i #-1) :field 3]
    ]
]
setread []
close :filename
end

to wn :x :y :thing ;WireNeighbourhood
Make "neighbours 0
if (mditem (list :y-1 :x) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y-1 :x+1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y :x+1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y+1 :x+1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y+1 :x) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y+1 :x-1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y :x-1) :field)=:thing [Make "neighbours :neighbours+1]
if (mditem (list :y-1 :x-1) :field)=:thing [Make "neighbours :neighbours+1]
ifelse OR :neighbours=1 :neighbours=2 [op "true] [op "false]
end

Lua

If ran using LÖVE, it will animate the simulation on a window. Otherwise it will print the first 10 steps on the console.

local map = {{'t', 'H', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
             {'.', ' ', ' ', ' ', '.'},
             {' ', ' ', ' ', '.', '.', '.'},
             {'.', ' ', ' ', ' ', '.'},
             {'H', 't', '.', '.', ' ', '.', '.', '.', '.', '.', '.'}}

function step(map)
    local next = {}
    for i = 1, #map do
        next[i] = {}
        for j = 1, #map[i] do
            next[i][j] = map[i][j]
            if map[i][j] == "H" then
                next[i][j] = "t"
            elseif map[i][j] == "t" then
                next[i][j] = "."
            elseif map[i][j] == "." then
                local count = 	((map[i-1] or {})[j-1] == "H" and 1 or 0) +
                                ((map[i-1] or {})[j] == "H" and 1 or 0) +
                                ((map[i-1] or {})[j+1] == "H" and 1 or 0) +
                                ((map[i] or {})[j-1] == "H" and 1 or 0) +
                                ((map[i] or {})[j+1] == "H" and 1 or 0) +
                                ((map[i+1] or {})[j-1] == "H" and 1 or 0) +
                                ((map[i+1] or {})[j] == "H" and 1 or 0) +
                                ((map[i+1] or {})[j+1] == "H" and 1 or 0)
                if count == 1 or count == 2 then
                    next[i][j] = "H"
                else
                    next[i][j] = "."
                end
            end
        end
    end
    return next
end

if not not love then
    local time, frameTime, size = 0, 0.25, 20
    local colors = {["."] = {255, 200, 0},
                    ["t"] = {255, 0, 0},
                    ["H"] = {0, 0, 255}}
    function love.update(dt)
        time = time + dt
        if time > frameTime then
            time = time - frameTime
            map = step(map)
        end
    end

    function love.draw()
        for i = 1, #map do
            for j = 1, #map[i] do
                love.graphics.setColor(colors[map[i][j]] or {0, 0, 0})
                love.graphics.rectangle("fill", j*size, i*size, size, size)
            end
        end
    end
else
    for iter = 1, 10 do
        print("\nstep "..iter.."\n")
        for i = 1, #map do
            for j = 1, #map[i] do
                io.write(map[i][j])
            end
            io.write("\n")
        end
        map = step(map)
    end
end

Mathematica/Wolfram Language

DynamicModule[{data = 
   ArrayPad[PadRight[Characters /@ StringSplit["tH.........
        .   .
           ...
        .   .
        Ht.. ......", "\n"]] /. {" " -> 0, "t" -> 2, "H" -> 1, 
      "." -> 3}, 1]}, 
 Dynamic@ArrayPlot[
   data = CellularAutomaton[{{{_, _, _}, {_, 0, _}, {_, _, _}} -> 
       0, {{_, _, _}, {_, 1, _}, {_, _, _}} -> 
       2, {{_, _, _}, {_, 2, _}, {_, _, _}} -> 
       3, {{a_, b_, c_}, {d_, 3, e_}, {f_, g_, h_}} :> 
       Switch[Count[{a, b, c, d, e, f, g, h}, 1], 1, 1, 2, 1, _, 3]}, 
     data], ColorRules -> {1 -> Yellow, 2 -> Red}]]

MiniScript

This GUI implementation is for use with Mini Micro.

colors = [color.black, color.yellow, color.aqua, color.red]
deltas = [[-1,-1], [-1,0], [-1,1],
          [ 0,-1],         [ 0,1],
          [ 1,-1], [ 1,0], [ 1,1]]

displayGrid = function(grid, td)
	for y in range(0, grid.len - 1)
		for x in range(0, grid[0].len - 1)
			td.setCell x,y, grid[y][x]
		end for
	end for
end function

buildGrid = function(s)
	lines = s.split(char(13))
	nRows = lines.len
	nCols = 0
	for line in lines
		if line.len > nCols then nCols = line.len
	end for
	
	grid = []
	emptyRow = []
	for c in range(1,nCols)
		emptyRow.push(0)
	end for
	
	for line in lines
		row = emptyRow[:]
		for i in range(0, line.len - 1)
			row[i] = " .Ht".indexOf(line[i])
		end for
		grid.push(row)
	end for
	return grid
end function

getNewState = function(td, x, y)
	cellState = td.cell(x, y)
	if cellState == 3 then
		return 1
	else if cellState == 2 then
		return 3
	else if cellState == 1 then
		sum = 0
		for delta in deltas
			x1 = x + delta[0]
			y1 = y + delta[1]
			if td.cell(x1, y1) == 2 then sum += 1
		end for
		if sum == 1 or sum == 2 then
			return 2
		else
			return 1
		end if
	end if
	return cellState
end function

clear

wireWorldProgram = "tH........." + char(13)
wireWorldProgram += ".   ." + char(13)
wireWorldProgram += "   ..." + char(13)
wireWorldProgram += ".   ." + char(13)
wireWorldProgram += "Ht.. ......"
grid = buildGrid(wireWorldProgram)

// Prepare a tile display
// Generate image used for the tiles from the colors defined above.
img = Image.create(colors.len, 1); 
for i in range(0, colors.len - 1)
	img.setPixel(i, 0, colors[i])
end for

cols = grid[0].len
rows = grid.len
display(4).mode = displayMode.tile
td = display(4)
cSize = 25
td.cellSize = cSize   // size of cells on screen
td.scrollX = -(960 - cols * (cSize + 1)) / 2
td.scrollY = -(640 - rows * (cSize + 1)) / 2
td.extent = [cols, rows]
td.overlap = -1   // adds a small gap between cells
td.tileSet = img; td.tileSetTileSize = 1
td.clear 0

while true
	displayGrid(grid, td)
	for y in range(0, rows - 1)
		for x in range(0, cols - 1)
			grid[y][x] = getNewState(td, x, y)
		end for
	end for
	wait 0.5
end while

Nim

Translation of: C
import strutils, os

var world, world2 = """
+-----------+
|tH.........|
|.   .      |
|   ...     |
|.   .      |
|Ht.. ......|
+-----------+"""

let h = world.splitLines.len
let w = world.splitLines[0].len

template isH(x, y): int = int(s[i + w * y + x] == 'H')

proc next(o: var string, s: string, w: int) =
  for i, c in s:
    o[i] = case c
      of ' ': ' '
      of 't': '.'
      of 'H': 't'
      of '.':
        if (isH(-1, -1) + isH(0, -1) + isH(1, -1) +
            isH(-1,  0)              + isH(1,  0) +
            isH(-1,  1) + isH(0,  1) + isH(1,  1)
           ) in 1..2: 'H' else: '.'
      else: c

while true:
  echo world
  stdout.write "\x1b[",h,"A"
  stdout.write "\x1b[",w,"D"
  sleep 100

  world2.next(world, w)
  swap world, world2

OCaml

let w = [|
    "  ......tH              ";
    " .        ......        ";
    "  ...Ht...      .       ";
    "               ....     ";
    "               .  ..... ";
    "               ....     ";
    "  tH......      .       ";
    " .        ......        ";
    "  ...Ht...              ";
  |]

let is_head w x y =
  try if w.(x).[y] = 'H' then 1 else 0
  with _ -> 0

let neighborhood_heads w x y =
  let n = ref 0 in
  for _x = pred x to succ x do
    for _y = pred y to succ y do
      n := !n + (is_head w _x _y)
    done;
  done;
  (!n)

let step w =
  let n = Array.init (Array.length w) (fun i -> String.copy w.(i)) in
  let width = Array.length w
  and height = String.length w.(0)
  in
  for x = 0 to pred width do
    for y = 0 to pred height do
      n.(x).[y] <- (
        match w.(x).[y] with
        | ' ' -> ' '
        | 'H' -> 't'
        | 't' -> '.'
        | '.' ->
            (match neighborhood_heads w x y with
            | 1 | 2 -> 'H'
            | _ -> '.')
        | _ -> assert false)
    done;
  done;
  (n)

let print = (Array.iter print_endline)

let () =
  let rec aux w =
    Unix.sleep 1;
    let n = step w in
    print n;
    aux n
  in
  aux w

Oz

Includes a simple animation, using a text widget.

declare
  Rules =
  [rule(&  & )
   rule(&H &t)
   rule(&t &.)
   rule(&. &H when:fun {$ Neighbours}
                      fun {IsHead X} X == &H end
                      Hs = {Filter Neighbours IsHead}
                      Len = {Length Hs}
                   in
                      Len == 1 orelse Len == 2
                   end)
   rule(&. &.)]

  Init = ["tH........."
          ".   .      "
          "   ...     "
          ".   .      "
          "Ht.. ......"]

  MaxGen = 100

  %% G(i) -> G(i+1)
  fun {Evolve Gi}
     fun {Get X#Y}
        Row = {CondSelect Gi Y unit}
     in
        {CondSelect Row X & } %% cells beyond boundaries are empty
     end
     fun {GetNeighbors X Y}
        {Map [X-1#Y-1  X#Y-1  X+1#Y-1
              X-1#Y           X+1#Y
              X-1#Y+1  X#Y+1  X+1#Y+1]
         Get}
     end
  in
     {Record.mapInd Gi
      fun {$ Y Row}
         {Record.mapInd Row
          fun {$ X C}
             for Rule in Rules return:Return do
                if C == Rule.1 then
		   When = {CondSelect Rule when {Const true}}
		in
		   if {When {GetNeighbors X Y}} then
		      {Return Rule.2}
		   end
		end
	     end
          end}
      end}
  end

  %% Create an arena from a list of strings.
  fun {ReadArena LinesList}
     {List.toTuple '#'
      {Map LinesList
       fun {$ Line}
          {List.toTuple row Line}
       end}}
  end
 
  %% Converts an arena to a virtual string
  fun {ShowArena G}
     {Record.map G
      fun {$ L} {Record.toList L}#"\n" end}
  end

  %% helpers
  fun lazy {Iterate F V} V|{Iterate F {F V}} end
  fun {Const X} fun {$ _} X end end
  
  %% prepare GUI
  [QTk]={Module.link ["x-oz://system/wp/QTk.ozf"]}
  GenDisplay
  Field
  GUI = td(label(handle:GenDisplay)
           label(handle:Field font:{QTk.newFont font(family:'Courier')})
          )
  {{QTk.build GUI} show}

  G0 = {ReadArena Init}
  Gn = {Iterate Evolve G0}
in
  for
     Gi in Gn
     I in 0..MaxGen
  do
     {GenDisplay set(text:"Gen. "#I)}
     {Field set(text:{ShowArena Gi})}
     {Delay 500}
  end

PARI/GP

\\ 0 = conductor, 1 = tail, 2 = head, 3 = empty
wireworldStep(M)={
	my(sz=matsize(M),t);
	matrix(sz[1],sz[2],x,y,
		t=M[x,y];
		if(t,
			[0,1,3][t]
		,
			t=sum(i=max(x-1,1),min(x+1,sz[1]),
				sum(j=max(y-1,1),min(y+1,sz[2]),
					M[i,j]==2
				)
			);
			if(t==1|t==2,2,3)
		)
	)
};
animate(M)={
	while(1,display(M=wireworldStep(M)))
};
display(M)={
	my(sz=matsize(M),t);
	for(i=1,sz[1],
		for(j=1,sz[2],
			t=M[i,j];
			print1([".","t","H"," "][t+1])
		);
		print
	)
};
animate(read("wireworld.gp"))

Perl

Read the initial World from stdin and print 10 steps to stdout

my @f = ([],(map {chomp;['',( split // ),'']} <>),[]);

for (1 .. 10) {
	print join "", map {"@$_\n"} @f;
	my @a = ([]);
	for my $y (1 .. $#f-1) {
		my $r = $f[$y];
		my $rr = [''];
		for my $x (1 .. $#$r-1) {
			my $c = $r->[$x];
			push @$rr,
				$c eq 'H' ? 't' :
				$c eq 't' ? '.' :
				$c eq '.' ? (join('', map {"@{$f[$_]}[$x-1 .. $x+1]"=~/H/g} ($y-1 .. $y+1)) =~ /^H{1,2}$/ ? 'H' : '.') :
				$c;
		}
		push @$rr, '';
		push @a, $rr;
	}
	@f = (@a,[]);
}

Input:

tH.........
.   .
   ...
.   .
Ht.. ......
Output:
 t H . . . . . . . . . 
 .       . 
       . . . 
 .       . 
 H t . .   . . . . . . 


 . t H . . . . . . . . 
 H       . 
       . . . 
 H       . 
 t . . .   . . . . . . 


 H . t H . . . . . . . 
 t       . 
       . . . 
 t       . 
 . H . .   . . . . . . 


 t H . t H . . . . . . 
 .       H 
       . . . 
 .       . 
 H t H .   . . . . . . 


 . t H . t H . . . . . 
 H       t 
       H H H 
 H       . 
 t . t H   . . . . . . 


 H . t H . t H . . . . 
 t       . 
       t t t 
 t       . 
 . H . t   . . . . . . 


 t H . t H . t H . . . 
 .       H 
       . . . 
 .       . 
 H t H .   . . . . . . 


 . t H . t H . t H . . 
 H       t 
       H H H 
 H       . 
 t . t H   . . . . . . 


 H . t H . t H . t H . 
 t       . 
       t t t 
 t       . 
 . H . t   . . . . . . 


 t H . t H . t H . t H 
 .       H 
       . . . 
 .       . 
 H t H .   . . . . . . 

Phix

Library: Phix/pGUI
Library: Phix/online

You can run this online here.

--
-- demo\rosetta\Wireworld.exw
-- ==========================
--
--  Invoke with file to read, or let it read the one below (if compiled assumes source is in the same directory)
--
--  Note that tabs in description files are not supported - where necessary spaces can be replaced with _ chars.
--  (tab chars in text files should technically always represent (to-next) 8 spaces, but not many editors respect 
--   that, and instead assume the file will only ever be read by the same program/with matching settings. </rant>)
--  (see also demo\edix\src\tabs.e\ExpandTabs() for what you'd need if you knew what the tab chars really meant.)
--
with javascript_semantics
constant default_description = """
tH.........
.___.
___...
.___.
Ht.. ......
"""
sequence lines, counts
integer longest

function valid_line(string line, integer l=0)
    if length(line)=0 then return 0 end if
    for i=1 to length(line) do
        integer ch = line[i]
        if not find(ch," _.tH") then
            if l and ch='\t' then
                -- as above
                printf(1,"error: tab char on line %d\n",{l})
                {} = wait_key()
                abort(0)
            end if
            return 0
        end if
    end for
    return 1
end function

procedure load_desc()
    sequence text
    if platform()=JS then
        text = split(default_description,"\n")
    else
        string filename = substitute(command_line()[$],".exe",".exw")
        integer fn = open(filename,"r")
        if fn=-1 then
            printf(1,"error opening %s\n",{filename})
            {} = wait_key()
            abort(0)
        end if
        text = get_text(fn,GT_LF_STRIPPED)
        close(fn)
    end if
    lines = {}
    for i=1 to length(text) do
        string line = text[i]
        if valid_line(line) then
            lines = {line}
            longest = length(line)
            for j=i+1 to length(text) do
                line = text[j]
                if not valid_line(line,j) then exit end if
                lines = append(lines,line)
                if longest<length(line) then
                    longest = length(line)
                end if
            end for
            exit
        end if
    end for
    counts = deep_copy(lines)
end procedure

constant dxy = {{-1,-1}, {-1,+0}, {-1,+1},
                {+0,-1},          {+0,+1},
                {+1,-1}, {+1,+0}, {+1,+1}}

procedure set_counts()
    for y=1 to length(lines) do
        for x=1 to length(lines[y]) do
            if lines[y][x]='.' then
                integer count = 0
                for k=1 to length(dxy) do
                    integer {cx,cy} = sq_add({x,y},dxy[k])
                    if cy>=1 and cy<=length(lines)
                    and cx>=1 and cx<=length(lines[cy])
                    and lines[cy][cx]='H' then
                        count += 1
                    end if
                end for
                counts[y][x] = (count=1 or count=2)
            end if
        end for
    end for
end procedure

include pGUI.e

constant title = "Wireworld"
Ihandle dlg, canvas, timer
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*ih*/)
    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
    integer dx = floor(w/(longest+2))
    integer dy = floor(h/(length(lines)+2))
    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    set_counts()
    for y=1 to length(lines) do
        for x=1 to length(lines[y]) do
            integer c = lines[y][x], colour
            if find(c," _") then
                colour = CD_BLACK
            elsif c='.' then
                colour = CD_YELLOW
                if counts[y][x] then
                    lines[y][x] = 'H'
                end if
            elsif c='H' then
                colour = CD_BLUE
                lines[y][x] = 't'
            elsif c='t' then
                colour = CD_RED
                lines[y][x] = '.'
            end if
            cdCanvasSetForeground(cddbuffer, colour)
            cdCanvasBox(cddbuffer,x*dx,x*dx+dx,h-y*dy,h-(y*dy+dy))
        end for
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function timer_cb(Ihandle /*ih*/)
    IupUpdate(canvas)
    return IUP_IGNORE
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_BLACK)
    return IUP_DEFAULT
end function

procedure main()
    load_desc()
    IupOpen()

    canvas = IupCanvas("RASTERSIZE=300x180")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})

    timer = IupTimer(Icallback("timer_cb"), 500)

    dlg = IupDialog(canvas,`TITLE="%s"`, {title})

    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

PHP

$desc = 'tH.........
.   .
  ........
.   .
Ht.. ......

      ..
tH.... .......
      ..

      ..
tH..... ......
      ..';

$steps = 30;

//fill in the world with the cells
$world = array(array());
$row = 0;
$col = 0;
foreach(str_split($desc) as $i){
    switch($i){
        case "\n":
            $row++;
            //if($col > $width) $width = $col;
            $col = 0;
            $world[] = array();
            break;
        case '.':
            $world[$row][$col] = 1;//conductor
            $col++;
            break;
        case 'H':
            $world[$row][$col] = 2;//head
            $col++;
            break;
        case 't':
            $world[$row][$col] = 3;//tail
            $col++;
            break;
        default:
            $world[$row][$col] = 0;//insulator/air
            $col++;
            break;
    };
};
function draw_world($world){
    foreach($world as $rowc){
        foreach($rowc as $cell){
            switch($cell){
                case 0:
                    echo ' ';
                    break;
                case 1:
                    echo '.';
                    break;
                case 2:
                    echo 'H';
                    break;
                case 3:
                    echo 't';
            };
        };
        echo "\n";
    };
    //var_export($world);
};
echo "Original world:\n";
draw_world($world);
for($i = 0; $i < $steps; $i++){
    $old_world = $world; //backup to look up where was an electron head
    foreach($world as $row => &$rowc){
        foreach($rowc as $col => &$cell){
            switch($cell){
                case 2:
                    $cell = 3;
                    break;
                case 3:
                    $cell = 1;
                    break;
                case 1:
                    $neigh_heads = (int) @$old_world[$row - 1][$col - 1] == 2;
                    $neigh_heads += (int) @$old_world[$row - 1][$col] == 2;
                    $neigh_heads += (int) @$old_world[$row - 1][$col + 1] == 2;
                    $neigh_heads += (int) @$old_world[$row][$col - 1] == 2;
                    $neigh_heads += (int) @$old_world[$row][$col + 1] == 2;
                    $neigh_heads += (int) @$old_world[$row + 1][$col - 1] == 2;
                    $neigh_heads += (int) @$old_world[$row + 1][$col] == 2;
                    if($neigh_heads == 1 || $neigh_heads == 2){
                        $cell = 2;
                    };
            };
        };
        unset($cell); //just to be safe
    };
    unset($rowc); //just to be safe
    echo "\nStep " . ($i + 1) . ":\n";
    draw_world($world);
};

PicoLisp

This example uses 'grid' from "lib/simul.l", which maintains a two-dimensional structure.

(load "@lib/simul.l")

(let
   (Data (in "wire.data" (make (while (line) (link @))))
      Grid (grid (length (car Data)) (length Data)) )
   (mapc
      '((G D) (mapc put G '(val .) D))
      Grid
      (apply mapcar (flip Data) list) )
   (loop
      (disp Grid T
         '((This) (pack " " (: val) " ")) )
      (wait 1000)
      (for Col Grid
         (for This Col
            (case (=: next (: val))
               ("H" (=: next "t"))
               ("t" (=: next "."))
               ("."
                  (when
                     (>=
                        2
                        (cnt # Count neighbors
                           '((Dir) (= "H" (get (Dir This) 'val)))
                           (quote
                              west east south north
                              ((X) (south (west X)))
                              ((X) (north (west X)))
                              ((X) (south (east X)))
                              ((X) (north (east X))) ) )
                        1 )
                     (=: next "H") ) ) ) ) )
      (for Col Grid  # Update
         (for This Col
            (=: val (: next)) ) )
      (prinl) ) )
Output:
   +---+---+---+---+---+---+---+---+---+---+---+
 5 | t | H | . | . | . | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
 4 | . |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 3 |   |   |   | . | . | . |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 2 | . |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 1 | H | t | . | . |   | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
     a   b   c   d   e   f   g   h   i   j   k

   +---+---+---+---+---+---+---+---+---+---+---+
 5 | . | t | H | . | . | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
 4 | H |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 3 |   |   |   | . | . | . |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 2 | H |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 1 | t | . | . | . |   | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
     a   b   c   d   e   f   g   h   i   j   k

   +---+---+---+---+---+---+---+---+---+---+---+
 5 | H | . | t | H | . | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
 4 | t |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 3 |   |   |   | . | . | . |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 2 | t |   |   |   | . |   |   |   |   |   |   |
   +---+---+---+---+---+---+---+---+---+---+---+
 1 | . | H | . | . |   | . | . | . | . | . | . |
   +---+---+---+---+---+---+---+---+---+---+---+
     a   b   c   d   e   f   g   h   i   j   k

PureBasic

Standalone version

Enumeration 
   #Empty     
   #Electron_head
   #Electron_tail
   #Conductor
EndEnumeration

#Delay=100
#XSize=23
#YSize=12

Procedure Limit(n, min, max)
  If n<min
    n=min
  ElseIf n>max
    n=max
  EndIf
  ProcedureReturn n
EndProcedure

Procedure Moore_neighborhood(Array World(2),x,y)
  Protected cnt=0, i, j
  For i=Limit(x-1, 0, #XSize) To Limit(x+1, 0, #XSize)
    For j=Limit(y-1, 0, #YSize) To Limit(y+1, 0, #YSize) 
      If World(i,j)=#Electron_head
        cnt+1
      EndIf
    Next
  Next
  ProcedureReturn cnt
EndProcedure

Procedure PresentWireWorld(Array World(2))
  Protected x,y
  ;ClearConsole()
  For y=0 To #YSize
    For x=0 To #XSize
      ConsoleLocate(x,y)
      Select World(x,y)
        Case #Electron_head
          ConsoleColor(12,0): Print("#")
        Case #Electron_tail
          ConsoleColor(4,0): Print("#")
        Case #Conductor
          ConsoleColor(6,0): Print("#")
        Default
          ConsoleColor(15,0): Print(" ")
      EndSelect
    Next
    PrintN("")
  Next
EndProcedure

Procedure UpdateWireWorld(Array World(2))
  Dim NewArray(#XSize,#YSize)
  Protected i, j
  For i=0 To #XSize
    For j=0 To #YSize
      Select World(i,j)
        Case #Electron_head
          NewArray(i,j)=#Electron_tail
        Case #Electron_tail
          NewArray(i,j)=#Conductor
        Case #Conductor
          Define m=Moore_neighborhood(World(),i,j)
          If m=1 Or m=2
            NewArray(i,j)=#Electron_head
          Else
            NewArray(i,j)=#Conductor
          EndIf
        Default ; e.g. should be Empty
          NewArray(i,j)=#Empty
      EndSelect
    Next
  Next
  CopyArray(NewArray(),World())
EndProcedure

If OpenConsole()
  EnableGraphicalConsole(#True)
  ConsoleTitle("XOR() WireWorld")
  ;- Set up the WireWorld
  Dim WW.i(#XSize,#YSize)
  Define x, y
  Restore StartWW
  For y=0 To #YSize
    For x=0 To #XSize
      Read.i WW(x,y)
    Next
  Next
  
  ;- Start the WireWorld simulation
  Repeat
    PresentWireWorld(WW())
    UpdateWireWorld(WW())
    Delay(#Delay)
  ForEver
EndIf 

DataSection
  StartWW:
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  Data.i  0,0,0,3,3,3,3,2,1,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0
  Data.i  0,0,1,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0
  Data.i  0,0,0,2,3,3,3,3,3,3,3,0,0,0,0,0,0,3,0,0,0,0,0,0
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,3,3,3,3,3
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0
  Data.i  0,0,0,3,3,3,3,3,3,3,3,0,0,0,0,0,0,3,0,0,0,0,0,0
  Data.i  0,0,1,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0
  Data.i  0,0,0,2,3,3,3,3,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  Data.i  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
EndDataSection

Load from external source, graphical presentations

CompilerIf #PB_Compiler_Unicode
  CompilerError "The file handling in this small program is only in ASCII."
CompilerEndIf

Enumeration 
  #Empty     
  #Electron_head
  #Electron_tail
  #Conductor
  #COL_Empty          = $000000
  #COL_Electron_head  = $5100FE
  #COL_Electron_tail  = $6A3595
  #COL_Conductor      = $62C4FF
  #WW_Window  = 0
  #WW_IGadget = 0
  #WW_Timer   = 0
  #WW_Image   = 0
EndEnumeration

#Delay=100
Global XSize, YSize

Procedure Limit(n, min, max)
  If     n<min: n=min
  ElseIf n>max: n=max
  EndIf
  ProcedureReturn n
EndProcedure

Procedure Moore_neighborhood(Array World(2),x,y)
  Protected cnt=0, i, j
  For i=Limit(x-1, 0, XSize) To Limit(x+1, 0, XSize)
    For j=Limit(y-1, 0, YSize) To Limit(y+1, 0, YSize) 
      If World(i,j)=#Electron_head
        cnt+1
      EndIf
    Next
  Next
  ProcedureReturn cnt
EndProcedure

Procedure PresentWireWorld(Array World(2))
  Protected x,y
  StartDrawing(ImageOutput(#WW_Image))
  For y=0 To YSize-1
    For x=0 To XSize-1
      Select World(x,y)
        Case #Electron_head
          Plot(x,y,#COL_Electron_head)
        Case #Electron_tail
          Plot(x,y,#COL_Electron_tail)
        Case #Conductor
          Plot(x,y,#COL_Conductor)
        Default
          Plot(x,y,#COL_Empty)
      EndSelect
    Next
  Next
  StopDrawing()
  ImageGadget(#WW_IGadget,0,0,XSize,YSize,ImageID(#WW_Image))
EndProcedure

Procedure UpdateWireWorld(Array World(2))
  Dim NewArray(XSize,YSize)
  Protected i, j
  For i=0 To XSize
    For j=0 To YSize
      Select World(i,j)
        Case #Electron_head
          NewArray(i,j)=#Electron_tail
        Case #Electron_tail
          NewArray(i,j)=#Conductor
        Case #Conductor
          Define m=Moore_neighborhood(World(),i,j)
          If m=1 Or m=2
            NewArray(i,j)=#Electron_head
          Else
            NewArray(i,j)=#Conductor
          EndIf
        Default ; e.g. should be Empty
          NewArray(i,j)=#Empty
      EndSelect
    Next
  Next
  CopyArray(NewArray(),World())
EndProcedure

Procedure LoadDataFromFile(File$,Array A(2))
  Define Line$, x, y, *c.Character
  If OpenFile(0,File$)
    ;
    ; Count non-commented lines & length of the first line, e.g. get Array(x,y)
    While Not Eof(0)
      Line$=Trim(ReadString(0))
      *c=@Line$
      If Not PeekC(*c)=';'
        y+1
        If Not x
          While PeekC(*c)>='0' And PeekC(*c)<='3'
            x+1:  *c+1
          Wend
        EndIf
      EndIf 
    Wend
    XSize=x:  YSize=y
    Dim A(XSize,YSize)
    ;
    ; Read in the Wire-World
    y=0
    FileSeek(0,0)
    While Not Eof(0)
      Line$=Trim(ReadString(0))
      *c=@Line$
      If Not PeekC(*c)=';'
        x=0
        While x<XSize
          A(x,y)=PeekC(*c)-'0'
          x+1: *c+1
        Wend
        y+1
      EndIf
    Wend
    CloseFile(0)
  EndIf
EndProcedure

#Title="WireWorld, PureBasic"
If OpenWindow(#WW_Window,0,0,XSize,YSize,#Title,#PB_Window_SystemMenu)
  Dim WW.i(0,0)
  Define Pattern$ = "Text (*.txt)|*.txt", Pattern = 0
  Define DefFile$ = "WireWorld.txt", Event
  Define Title$   = "Please choose file To load"
  Define File$ = OpenFileRequester(Title$, DefFile$, Pattern$, Pattern)
  AddWindowTimer(#WW_Window,#WW_Timer,#Delay)
  LoadDataFromFile(File$,WW())
  ResizeWindow(#WW_Window,0,0,XSize,YSize)  
  CreateImage(#WW_Image,XSize,YSize)
  Repeat
    Event=WaitWindowEvent()
    If Event=#PB_Event_Timer
      PresentWireWorld(WW())
      UpdateWireWorld (WW())
    EndIf
  Until Event=#PB_Event_CloseWindow  
EndIf

Example of data file to load

; Save as "WireWorld.txt"
; 
; ;=Comment
; 0=Empty Cell
; 1=Electron Head
; 2=Electron Tail
; 3=Conductor
;
; All lines nees to be of the same length,
; and containing only the defined values.
;
;
; Start of World
;
000000000000000000000000000000000000000000030030000000000000000000000000
000000000000000000000000000000000000000000300030000000000000000000000000
000333321330000000000000000000000033330003000030000000000000000000000000
001000000003333330000000000000000030030030000030000000000000000000000000
000233333330000003000000000000000030003300033330000000000000000000000000
000000000000000033330000333000000030000000030003330000000000000000000000
000000000000000030033333300333333333333333333333003333333333333333333333
000000000000000033330000333000000000000000000003330000030000000000000000
000333333330000003000000000000000000000000000000000000030000000000000000
001000000003333330000000033333330033333330000000000000030000000000000000
000233331230000000000000030000030030000030000000000033333333300000000000
000000000000000000000000030000030030000300000000000300000003000000000000
000000000000000000000000033333330033333000000000000003000033000000000000
000000000000000000000000030000000030000300000000000000333030000000000000
000000000000000000000000030000000030000030000000000000300033333333333330
000333321330000000000000030000000030000030003330000000333000000000000000
001000000003333330000000030000000003333300003330000000000000000000000000
000233333330000003000000300000000003000000003000000000000000000000000000
000000000000000033330003000033000030000000030000000000000000000000000000
000000000000000030033333333330333333333333333333333333333333333333333333
000000000000000033330000000033003000000000000000300000000000000000000000
000333333330000003000000000000003000000000000000300000000000000000000000
001000000003333330000000000000003000000000000000300000000000000000000000
000233331230000000000000000000003330000000000000300000000000000000000000
000000000000000000000000000000000030000000000000300000000000000000000000
000000000000000000000000000000000030000000000003333000000000000000000000
000000000000000000000000000000000030000000000003003333333333333333333333
000000000000000000000000000000000030000000000003333000000000000000000000
000333321330000000000000000000000003333000000000300000000000000000000000
001000000003333330000000000000000003003000000000300000000000000000000000
000233333330000003000000000000000003003333333333300000000000000000000000
000000000000000033330000330000000003000000000000000000000000000000000000
000000000000000030033333303333333333333333333333333333333333333333333333
000000000000000033330000330000000000000000000000000000000000000000000003
000333333330000003000000000000000000000000000000000000000000000000000003
001000000003333330000000003333333333333333333333333333333333333333333003
000233331230000000000000030000000000000000000000000000000000000000000003
000000000000000333333333333333333333333333333333333333333333333333333333
000000000000000300000000000000000000000000000000000000000000000000000000

Python

'''
Wireworld implementation.
'''

from io import StringIO
from collections import namedtuple
from pprint import pprint as pp
import copy

WW = namedtuple('WW', 'world, w, h')
head, tail, conductor, empty = allstates = 'Ht. '


infile = StringIO('''\
tH.........
.   .
   ...
.   .
Ht.. ......\
''')

def readfile(f):
    '''file > initial world configuration'''
    world  = [row.rstrip('\r\n') for row in f]
    height = len(world)
    width  = max(len(row) for row in world)
    # fill right and frame in empty cells
    nonrow = [ " %*s " % (-width, "") ]
    world  = nonrow + \
               [ " %*s " % (-width, row) for row in world ] + \
               nonrow   
    world = [list(row) for row in world]
    return WW(world, width, height)

def newcell(currentworld, x, y):
    istate = currentworld[y][x]
    assert istate in allstates, 'Wireworld cell set to unknown value "%s"' % istate
    if istate == head:
        ostate = tail
    elif istate == tail:
        ostate = conductor
    elif istate == empty:
        ostate = empty
    else: # istate == conductor
        n = sum( currentworld[y+dy][x+dx] == head
                 for dx,dy in ( (-1,-1), (-1,+0), (-1,+1),
                                (+0,-1),          (+0,+1),
                                (+1,-1), (+1,+0), (+1,+1) ) )
        ostate = head if 1 <= n <= 2 else conductor
    return ostate

def nextgen(ww):
    'compute next generation of wireworld'
    world, width, height = ww
    newworld = copy.deepcopy(world)
    for x in range(1, width+1):
        for y in range(1, height+1):
            newworld[y][x] = newcell(world, x, y)
    return WW(newworld, width, height)

def world2string(ww):
    return '\n'.join( ''.join(row[1:-1]).rstrip() for row in ww.world[1:-1] )

ww = readfile(infile)
infile.close()

for gen in range(10):
    print ( ("\n%3i " % gen) + '=' * (ww.w-4) + '\n' )
    print ( world2string(ww) )
    ww = nextgen(ww)
Output:
  0 =======

tH.........
.   .
   ...
.   .
Ht.. ......

  1 =======

.tH........
H   .
   ...
H   .
t... ......

  2 =======

H.tH.......
t   .
   ...
t   .
.H.. ......

  3 =======

tH.tH......
.   H
   ...
.   .
HtH. ......

  4 =======

.tH.tH.....
H   t
   HHH
H   .
t.tH ......

  5 =======

H.tH.tH....
t   .
   ttt
t   .
.H.t ......

  6 =======

tH.tH.tH...
.   H
   ...
.   .
HtH. ......

  7 =======

.tH.tH.tH..
H   t
   HHH
H   .
t.tH ......

  8 =======

H.tH.tH.tH.
t   .
   ttt
t   .
.H.t ......

  9 =======

tH.tH.tH.tH
.   H
   ...
.   .
HtH. ......

Racket

#lang racket
(require 2htdp/universe)
(require 2htdp/image)
(require racket/fixnum)

; see the forest fire task, from which this is derived...
(define-struct wire-world (width height cells) #:prefab)

(define state:_ 0)
(define state:. 1)
(define state:H 2)
(define state:t 3)

(define (char->state c)
  (case c
    ((#\_ #\space) state:_)
    ((#\.) state:.)
    ((#\H) state:H)
    ((#\t) state:t)))

(define (initial-world l)
  (let ((h (length l))
        (w (string-length (first l))))
    (make-wire-world w h
                     (for*/fxvector
                      #:length (* h w)
                      ((row (in-list l))
                       (cell (in-string row)))
                      (char->state cell)))))

(define initial-list
  '("tH........."
    ".   .      "
    "   ...     "
    ".   .      "
    "Ht.. ......"))

(define-syntax-rule (count-neighbours-in-state ww wh wc r# c# state-to-match)
  (for/sum
      ((r (in-range (- r# 1) (+ r# 2)))
       #:when (< -1 r wh)
       (c (in-range (- c# 1) (+ c# 2)))
       #:when (< -1 c ww)
       ;; note, this will check cell at (r#, c#), too but it's not
       ;; worth checking that r=r# and c=c# each time in
       ;; this case, we know that (r#, c#) is a conductor:
       ; #:unless (and (= r# r) (= c# c))
       (i (in-value (+ (* r ww) c)))
       #:when (= state-to-match (fxvector-ref wc i)))
    1))

(define (cell-new-state ww wh wc row col)
  (let ((cell (fxvector-ref wc (+ col (* row ww)))))
    (cond
      ((= cell state:_) cell) ; empty -> empty
      ((= cell state:t) state:.) ; tail -> empty
      ((= cell state:H) state:t) ; head -> tail
      ((<= 1 (count-neighbours-in-state ww wh wc row col state:H) 2) state:H)
      (else cell))))

(define (wire-world-tick world)
  (define ww (wire-world-width world))
  (define wh (wire-world-height world))
  (define wc (wire-world-cells world))
  
  (define (/w x) (quotient x ww))
  (define (%w x) (remainder x ww))
  
  (make-wire-world
   ww wh
  (for/fxvector
   #:length (* ww wh)
   ((cell (in-fxvector wc))
    (r# (sequence-map /w (in-naturals)))
    (c# (sequence-map %w (in-naturals))))
   (cell-new-state ww wh wc r# c#))))

(define colour:_ (make-color   0   0   0))  ; black
(define colour:. (make-color  128 128 128)) ; grey
(define colour:H (make-color  128 255 255)) ; bright cyan
(define colour:t (make-color    0 128 128)) ; dark cyan

(define colour-vector (vector colour:_ colour:. colour:H colour:t))
(define (cell-state->colour state) (vector-ref colour-vector state))

(define render-scaling 20)
(define (render-world W)
  (define ww (wire-world-width W))
  (define wh (wire-world-height W))
  (define wc (wire-world-cells W))
   (let* ((flat-state
           (for/list ((cell (in-fxvector wc)))
             (cell-state->colour cell))))
     (place-image (scale render-scaling (color-list->bitmap flat-state ww wh))
                  (* ww (/ render-scaling 2))
                  (* wh (/ render-scaling 2))
                  (empty-scene (* render-scaling ww) (* render-scaling wh)))))

(define (run-wire-world #:initial-state W)
  (big-bang
   (initial-world W) ;; initial state
   [on-tick wire-world-tick
            1/8 ; tick time (seconds)
            ]
   [to-draw render-world]))

(run-wire-world #:initial-state initial-list)

Raku

(formerly Perl 6)

Works with: Rakudo version 2018.03
class Wireworld {
    has @.line;
    method height returns Int { @!line.elems }
    method width  returns Int { max @!line».chars }

    multi method new(@line) { samewith :@line }
    multi method new($str ) { samewith $str.lines }

    method gist { join "\n", @.line }

    method !neighbors($i where ^$.height, $j where ^$.width)
    {
        my @i = grep ^$.height, $i «+« (-1, 0, 1);
        my @j = grep ^$.width,  $j «+« (-1, 0, 1);
        gather for @i X @j -> (\i, \j) {
            next if [ i, j ] ~~ [ $i, $j ];
            take @!line[i].comb[j];
        }
    }
    method succ {
        my @succ;
        for ^$.height X ^$.width -> ($i, $j) {
            @succ[$i] ~=
            do given @.line[$i].comb[$j] {
                when 'H' { 't' }
                when 't' { '.' }
                when '.' {
                    grep('H', self!neighbors($i, $j)) == 1|2 ?? 'H' !! '.'
                }
                default { ' ' }
            }
        }
        return self.new: @succ;
    }
}

my %*SUB-MAIN-OPTS;
%*SUB-MAIN-OPTS<named-anywhere> = True;

multi sub MAIN (
    IO()      $filename,
    Numeric:D :$interval = 1/4,
    Bool      :$stop-on-repeat,
) {
    run-loop :$interval, :$stop-on-repeat, Wireworld.new: $filename.slurp;
}

#| run a built-in example
multi sub MAIN (
    Numeric:D :$interval = 1/4,
    Bool      :$stop-on-repeat,
) {
    run-loop
      :$interval,
      :$stop-on-repeat,
      Wireworld.new:
	Q:to/§/
	tH.........
	.   .
	   ...
	.   .
	Ht.. ......
	§
}

sub run-loop (
    Wireworld:D     $initial,
    Real:D(Numeric) :$interval = 1/4,
    Bool            :$stop-on-repeat
){
    my %seen is SetHash;

    print "\e7";                # save cursor position
    for $initial ...^ * eqv * { # generate a sequence (uses .succ)
      print "\e8";              # restore cursor position
      .say;
      last if $stop-on-repeat and %seen{ .gist }++;
      sleep $interval;
    }
}

When run with --stop-on-repeat

Output:
H.tH.tH.tH.
t   .      
   ttt     
t   .      
.H.t ......

REXX

/*REXX program  displays a   wire world   Cartesian grid   of  four─state  cells.       */
parse arg  iFID .  '('  generations  rows  cols  bare  head  tail  wire  clearScreen  reps
if iFID==''  then iFID= "WIREWORLD.TXT"          /*should default input file  be used?  */
        bla = 'BLANK'                            /*the "name" for a blank.              */
generations = p(generations     100   )          /*number generations that are allowed. */
       rows = p(rows            3     )          /*the number of cell  rows.            */
       cols = p(cols            3     )          /* "     "    "   "   columns.         */
       bare = pickChar(bare     bla   )          /*character used to show an empty cell.*/
clearScreen = p(clearScreen     0     )          /*1    means to clear the screen.      */
       head = pickChar(head     'H'   )          /*pick the character for the  head.    */
       tail = pickChar(tail     't'   )          /*  "   "      "      "   "   tail.    */
       wire = pickChar(wire     .     )          /*  "   "      "      "   "   wire.    */
       reps = p(reps            2     )          /*stop program  if there are 2 repeats.*/
fents= max(cols, linesize() - 1)                 /*the fence width used after displaying*/
#reps= 0;     $.= bare;   gens= abs(generations) /*at start, universe is new and barren.*/
                                                 /* [↓]     read the input file.        */
       do r=1  while lines(iFID)\==0             /*keep reading until the  End─Of─File. */
       q= strip( linein(iFID), 'T')              /*get a line from input file.          */
       L= length(q);      cols= max(cols, L)     /*calculate maximum number of columns. */
          do c=1  for L;  $.r.c= substr(q, c, 1) /*assign the cells for the   R   row.  */
          end   /*c*/
       end      /*r*/
!.= 0;                      signal on halt       /*initial state of cells;  handle halt.*/
rows= r - 1;   life= 0;     call showCells       /*display initial state of the cells.  */
                                                 /*watch cells evolve, 4 possible states*/
  do   life=1  for gens;    @.= bare             /*perform for the number of generations*/
     do   r=1  for rows                          /*process each of the rows.            */
       do c=1  for cols;    ?= $.r.c;    ??= ?   /*   "      "   "  "  columns.         */
                 select                          /*determine the type of cell.          */
                 when ?==head  then ??= tail
                 when ?==tail  then ??= wire
                 when ?==wire  then do;  #= hood();   if #==1 | #==2  then ??= head;   end
                 otherwise     nop
                 end   /*select*/
       @.r.c= ??                                 /*possible assign a  cell  a new state.*/
       end             /*c*/
     end               /*r*/

  call assign$                                   /*assign alternate cells ──► real world*/
  if generations>0 | life==gens  then call showCells
  end   /*life*/
                                                 /*stop watching the universe (or life).*/
halt: if life-1\==gens  then say 'The  ───Wireworld───  program was interrupted by user.'
done: exit 0                                     /*stick a fork in it,  we are all done.*/
/*───────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
$:         parse arg _row,_col;                  return  $._row._col==head
assign$:   do r=1  for rows;   do c=1  for cols;   $.r.c= @.r.c;   end;   end;      return
hood:      return  $(r-1,c-1)  + $(r-1,c)  + $(r-1,c+1)  + $(r,c-1)  + $(r,c+1)  + $(r+1,c-1)  + $(r+1,c)  + $(r+1,c+1)
p:         return word(arg(1), 1)                           /*pick the 1st word in list.*/
pickChar:  parse arg _ .;arg U .;L=length(_);if U==bla then _=' '; if L==3 then _=d2c(_);if L==2 then _=x2c(_);return _
showRows:  _=;  do r=1  for rows; z=;  do c=1 for cols; z= z||$.r.c; end;  z= strip(z,'T'); say z; _= _||z; end; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
showCells: if clearScreen  then 'CLS'                       /*◄──change CLS for the host*/
           call showRows                                    /*show rows in proper order.*/
           say right( copies('═', fents)life, fents)        /*display a title for cells.*/
           if _==''                   then signal done      /*No life?   Then stop run. */
           if !._                     then #reps= #reps + 1 /*detected repeated pattern.*/
           !._= 1                                           /*it is now an extant state.*/
           if reps\==0 & #reps<=reps  then return           /*so far, so good,  no reps.*/
           say '"Wireworld" repeated itself'    reps    "times,  the program is stopping."
           signal done                                      /*jump to this pgm's "exit".*/

Programming note:   the   hood   subroutine (above) could be optimized for speed by setting some short-circuit values   (r-1, c-1, r+1, and c+1)   and using those values in the subsequent expressions.

This REXX program makes use of the   linesize   REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).

The   LINESIZE.REX   REXX program is included here   ──►   LINESIZE.REX.

output   when using the default input file:

(Cycle   0   (zero)   is essentially a copy of the input file.)

tH.........
.   .
   ...
.   .
Ht.. ......
════════════════════════════════════════════════════════════════════════════════════════0
.tH........
H   .
   ...
H   .
t... ......
════════════════════════════════════════════════════════════════════════════════════════1
H.tH.......
t   .
   ...
t   .
.H.. ......
════════════════════════════════════════════════════════════════════════════════════════2
tH.tH......
.   H
   ...
.   .
HtH. ......
════════════════════════════════════════════════════════════════════════════════════════3
.tH.tH.....
H   t
   HHH
H   .
t.tH ......
════════════════════════════════════════════════════════════════════════════════════════4
H.tH.tH....
t   .
   ttt
t   .
.H.t ......
════════════════════════════════════════════════════════════════════════════════════════5
tH.tH.tH...
.   H
   ...
.   .
HtH. ......
════════════════════════════════════════════════════════════════════════════════════════6
.tH.tH.tH..
H   t
   HHH
H   .
t.tH ......
════════════════════════════════════════════════════════════════════════════════════════7
H.tH.tH.tH.
t   .
   ttt
t   .
.H.t ......
════════════════════════════════════════════════════════════════════════════════════════8
tH.tH.tH.tH
.   H
   ...
.   .
HtH. ......
════════════════════════════════════════════════════════════════════════════════════════9
.tH.tH.tH.t
H   t
   HHH
H   .
t.tH ......
═══════════════════════════════════════════════════════════════════════════════════════10
H.tH.tH.tH.
t   .
   ttt
t   .
.H.t ......
═══════════════════════════════════════════════════════════════════════════════════════11
tH.tH.tH.tH
.   H
   ...
.   .
HtH. ......
═══════════════════════════════════════════════════════════════════════════════════════12
.tH.tH.tH.t
H   t
   HHH
H   .
t.tH ......
═══════════════════════════════════════════════════════════════════════════════════════13
"Wireworld" repeated itself 2 times,  the program is stopping.

RISC-V Assembly

/* gnu assembler syntax */
wireworld:
/* unsigned int width  (a0) */
/* unsigned int height (a1) */
/*        char* grid   (a2) */

        mv      a4,a2

        li      t4,'.  /* conductor */
        li      t5,'H  /* head */
        li      t6,'t  /* tail */

        addi    t2,a0,-1
        addi    t3,a1,-1

        mv      t1,zero
.yloop: /* outer loop (y) */
        mv      t0,zero
.xloop: /* inner loop (x) */

        lb      a5,0(a4)
        bgt     a5,t4,.torh
        blt     a5,t4,.empty

/* conductor: */
/* unsigned int head_count (a3) */
/*        char* test_ptr   (a6) */
/*         char test       (a7) */

        mv      a3,zero
        sub     a6,a4,a0
        addi    a6,a6,-1

0:      beq     t1,zero,1f      /* bounds up */
        beq     t0,zero,0f      /* bounds left */
        lb      a7,0(a6)
        bne     a7,t6,0f
        addi    a3,a3,1

0:      lb      a7,1(a6)
        bne     a7,t6,0f
        addi    a3,a3,1

0:      beq     t0,t2,0f        /* bounds right */
        lb      a7,2(a6)
        bne     a7,t6,0f
        addi    a3,a3,1

0:1:    add     a6,a6,a0
        beq     t0,zero,0f      /* bounds left */
        lb      a7,0(a6)
        bne     a7,t6,0f
        addi    a3,a3,1

0:      beq     t0,t2,0f        /* bounds right */
        lb      a7,2(a6)
        bne     a7,t5,0f
        addi    a3,a3,1

0:      add     a6,a6,a0

        beq     t1,t3,1f        /* bounds down */
        beq     t0,zero,0f      /* bounds left */
        lb      a7,0(a6)
        bne     a7,t5,0f
        addi    a3,a3,1

0:      lb      a7,1(a6)
        bne     a7,t5,0f
        addi    a3,a3,1

0:      beq     t0,t2,0f        /* bounds right */
        lb      a7,2(a6)
        bne     a7,t5,0f
        addi    a3,a3,1

0:1:    beq     a3,zero,.empty
        addi    a3,a3,-2
        bgt     a3,zero,.empty

        mv      a5,t5           /* convert conductor to electron head */
        j       .save

.torh:  beq     a5,t6,.tail

.head:  mv      a5,t6
        j       .save

.tail:  mv      a5,t4
.save:  sb      a5,0(a4)
.empty: /* do nothing */

/* end x-loop */
        addi    a4,a4,1
        addi    t0,t0,1
        bne     t0,a0,.xloop

/* end y-loop */
        addi    t1,t1,1
        bne     t1,a1,.yloop

        ret

For output, compile the above to an object file and link against the following program:

#include <stdio.h>
#include <string.h>

char init[] = "        tH....tH                                            "
              "       .        ......                                      "
              "        ........      .                                     "
              "  ..                 ....           ..       ..       ..    "
              ".. ...               .  ..tH....tH... .tH..... ....tH.. .tH."
              "  ..                 ....           ..       ..       ..    "
              "        tH......      .                                     "
              "       .        ....tH                                      "
              "        ...Ht...                                            ";
int width = 60;
int height = 9;

void wireworld(unsigned int, unsigned int, char *);

int main() {
  char tmp[width + 1] = {};
  do {
    for (int i = 0; i < height; i++) {
      strncpy(tmp, init + i * width, width);
      puts(tmp);
    }
    wireworld(width, height, init);
  } while (getchar());

  return 0;
}

Example output:

        tH....tH
       .        ......
        ........      .
  ..                 ....           ..       ..       ..
.. ...               .  ..tH....tH... .tH..... ....tH.. .tH.
  ..                 ....           ..       ..       ..
        tH......      .
       .        ....tH
        ...Ht...

        .tH....t
       .        H.....
        ........      .
  ..                 ....           ..       ..       ..
.. ...               .  ...tH....tH.. ..tH.... .....tH. ..tH
  ..                 ....           ..       ..       ..
        .tH.....      H
       .        .....t
        ..Ht....

        ..tH....
       .        tH....
        .......H      .
  ..                 ....           ..       ..       H.
.. ...               .  ....tH....tH. ...tH... ......tH ...t
  ..                 HHH.           ..       ..       H.
        ..tH....      t
       .        ......
        .Ht.....

        ...tH...
       .        .tH...
        ......Ht      .
  ..                 ....           H.       ..       tH
.. ...               H  H....tH....tH ....tH.. .......t ....
  ..                 tttH           H.       ..       tH
        ...tH...      .
       .        ......
        Ht......

        ....tH..
       .        ..tH..
        .....Ht.      .
  ..                 HHHH           tH       ..       .t
.. ...               t  tH....tH....t .....tH. ........ H...
  ..                 ...t           tH       ..       .t
        ....tH..      .
       H        ......
        t.......

        .....tH.
       .        ...tH.
        ....Ht..      .
  ..                 tttt           .t       H.       ..
.. ...               .  .tH....tH.... H.....tH ........ tH..
  ..                 ....           .t       H.       ..
        H....tH.      .
       t        ......
        ........

        ......tH
       .        ....tH
        ...Ht...      .
  ..                 ....           ..       tH       ..
.. ...               .  ..tH....tH... tH.....t ........ .tH.
  ..                 ....           ..       tH       ..
        tH....tH      .
       .        ......
        ........

        .......t
       .        H....t
        ..Ht....      H
  ..                 ....           ..       .t       ..
.. ...               .  ...tH....tH.. .tH..... H....... ..tH
  ..                 ....           ..       .t       ..
        .tH....t      .
       .        H.....
        ........

        ........
       .        tH....
        .Ht....H      t
  ..                 HHH.           ..       ..       ..
.. ...               .  ....tH....tH. ..tH.... tH...... ...t
  ..                 ....           ..       ..       ..
        ..tH....      .
       .        tH....
        .......H

        ........
       .        .tH...
        Ht....Ht      .
  ..                 tttH           H.       ..       ..
.. ...               H  H....tH....tH ...tH... .tH..... ....
  ..                 ....           H.       ..       ..
        ...tH...      .
       .        .tH...
        ......Ht

        ........
       H        ..tH..
        t....Ht.      .
  ..                 ...t           tH       ..       ..
.. ...               t  tH....tH....t ....tH.. ..tH.... ....
  ..                 HHHH           tH       ..       ..
        ....tH..      .
       .        ..tH..
        .....Ht.

        H.......
       t        ...tH.
        ....Ht..      .
  ..                 ....           .t       ..       ..
.. ...               .  .tH....tH.... H....tH. ...tH... ....
  ..                 tttt           .t       ..       ..
        .....tH.      .
       .        ...tH.
        ....Ht..

        tH......
       .        ....tH
        ...Ht...      .
  ..                 ....           ..       H.       ..
.. ...               .  ..tH....tH... tH....tH ....tH.. ....
  ..                 ....           ..       H.       ..
        ......tH      .
       .        ....tH
        ...Ht...

        .tH.....
       .        .....t
        ..Ht....      H
  ..                 ....           ..       tH       ..
.. ...               .  ...tH....tH.. .tH....t .....tH. ....
  ..                 ....           ..       tH       ..
        .......t      H
       .        H....t
        ..Ht....

        ..tH....
       .        ......
        .Ht.....      t
  ..                 HHH.           ..       .t       H.
.. ...               .  ....tH....tH. ..tH.... H.....tH ....
  ..                 HHH.           ..       .t       H.
        ........      t
       .        tH....
        .Ht....H

        ...tH...
       .        ......
        Ht......      .
  ..                 tttH           H.       ..       tH
.. ...               .  H....tH....tH ...tH... tH.....t ....
  ..                 tttH           H.       ..       tH
        ........      .
       .        .tH...
        Ht....Ht

        ....tH..
       H        ......
        t.......      .
  ..                 ...t           tH       ..       .t
.. ...               .  t.....tH....t ....tH.. .tH..... H...
  ..                 ...t           tH       ..       .t
        ........      .
       H        ..tH..
        t....Ht.

        H....tH.
       t        ......
        ........      .
  ..                 ....           .t       ..       ..
.. ...               .  .......tH.... H....tH. ..tH.... tH..
  ..                 ....           .t       ..       ..
        H.......      .
       t        ...tH.
        ....Ht..

        tH....tH
       .        ......
        ........      .
  ..                 ....           ..       H.       ..
.. ...               .  ........tH... tH....tH ...tH... .tH.
  ..                 ....           ..       H.       ..
        tH......      .
       .        ....tH
        ...Ht...

        .tH....t
       .        H.....
        ........      .
  ..                 ....           ..       tH       ..
.. ...               .  .........tH.. .tH....t ....tH.. ..tH
  ..                 ....           ..       tH       ..
        .tH.....      H
       .        .....t
        ..Ht....

Ruby

See: Wireworld/Ruby

Rust

use std::str::FromStr;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum State {
    Empty,
    Conductor,
    ElectronTail,
    ElectronHead,
}

impl State {
    fn next(&self, e_nearby: usize) -> State {
        match self {
            State::Empty => State::Empty,
            State::Conductor => {
                if e_nearby == 1 || e_nearby == 2 {
                    State::ElectronHead
                } else {
                    State::Conductor
                }
            }
            State::ElectronTail => State::Conductor,
            State::ElectronHead => State::ElectronTail,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct WireWorld {
    pub width: usize,
    pub height: usize,
    pub data: Vec<State>,
}

impl WireWorld {
    pub fn new(width: usize, height: usize) -> Self {
        WireWorld {
            width,
            height,
            data: vec![State::Empty; width * height],
        }
    }

    pub fn get(&self, x: usize, y: usize) -> Option<State> {
        if x >= self.width || y >= self.height {
            None
        } else {
            self.data.get(y * self.width + x).copied()
        }
    }

    pub fn set(&mut self, x: usize, y: usize, state: State) {
        self.data[y * self.width + x] = state;
    }

    fn neighbors<F>(&self, x: usize, y: usize, mut f: F) -> usize 
        where F: FnMut(State) -> bool
    {
        let (x, y) = (x as i32, y as i32);
        let neighbors = [(x-1,y-1),(x-1,y),(x-1,y+1),(x,y-1),(x,y+1),(x+1,y-1),(x+1,y),(x+1,y+1)];

        neighbors.iter().filter_map(|&(x, y)| self.get(x as usize, y as usize)).filter(|&s| f(s)).count()
    }

    pub fn next(&mut self) {
        let mut next_state = vec![];
        for y in 0..self.height {
            for x in 0..self.width {
                let e_count = self.neighbors(x, y, |e| e == State::ElectronHead);
                next_state.push(self.get(x, y).unwrap().next(e_count));
            }
        }
        self.data = next_state;
    }
}

impl FromStr for WireWorld {
    type Err = ();
    fn from_str(s: &str) -> Result<WireWorld, ()> {
        let s = s.trim();
        let height = s.lines().count();
        let width = s.lines().map(|l| l.trim_end().len()).max().unwrap_or(0);
        let mut world = WireWorld::new(width, height);

        for (y, line) in s.lines().enumerate() {
            for (x, ch) in line.trim_end().chars().enumerate() {
                let state = match ch {
                    '.' => State::Conductor,
                    't' => State::ElectronTail,
                    'H' => State::ElectronHead,
                    _ => State::Empty,
                };
                world.set(x, y, state);
            }
        }
        Ok(world)
    }
}

graphical output using winit 0.24 and pixels 0.2

use pixels::{Pixels, SurfaceTexture};
use winit::event::*;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
use std::{env, fs};

mod wireworld;
use wireworld::{State, WireWorld};

const EMPTY_COLOR: [u8; 3] = [0x00, 0x00, 0x00];
const WIRE_COLOR: [u8; 3] =  [0xFC, 0xF9, 0xF8];
const HEAD_COLOR: [u8; 3] =  [0xFC, 0x00, 0x00];
const TAIL_COLOR: [u8; 3] =  [0xFC, 0x99, 0x33];

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Error: No Input File");
        std::process::exit(1);
    }

    let input_file = fs::read_to_string(&args[1]).unwrap();
    let mut world: WireWorld = input_file.parse().unwrap();

    let event_loop = EventLoop::new();
    let window = WindowBuilder::new()
        .with_title(format!("Wireworld - {}", args[1]))
        .build(&event_loop).unwrap();
    let size = window.inner_size();
    let texture = SurfaceTexture::new(size.width, size.height, &window);
    let mut image_buffer = Pixels::new(world.width as u32, world.height as u32, texture).unwrap();

    event_loop.run(move |ev, _, flow| {
        match ev {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested, ..
            } => {
                *flow = ControlFlow::Exit;
            }
            Event::WindowEvent {
                event: WindowEvent::KeyboardInput {
                    input: KeyboardInput {
                        state: ElementState::Pressed,
                        virtual_keycode: Some(VirtualKeyCode::Space),
                        ..
                    }, ..
                }, ..
            } => {
                world.next();
                window.request_redraw();
            }
            Event::RedrawRequested(_) => {
                let frame = image_buffer.get_frame();
                for (pixel, state) in frame.chunks_exact_mut(4).zip(world.data.iter()) {
                    let color = match state {
                        State::Empty => EMPTY_COLOR,
                        State::Conductor => WIRE_COLOR,
                        State::ElectronTail => TAIL_COLOR,
                        State::ElectronHead => HEAD_COLOR,
                    };
                    
                    pixel[0] = color[0]; // R
                    pixel[1] = color[1]; // G
                    pixel[2] = color[2]; // B
                    pixel[3] = 0xFF;     // A
                }
                image_buffer.render().unwrap();
            }
            _ => {}
        }
    });
}

Sidef

Translation of: Perl
var f = [[], DATA.lines.map {['', .chars..., '']}..., []]

10.times {
    say f.map { .join(" ") + "\n" }.join
    var a = [[]]
    for y in (1 ..^ f.end) {
        var r = f[y]
        var rr = ['']
        for x in (1 ..^ r.end) {
            var c = r[x]
            rr << (
              given(c) {
                when('H') { 't' }
                when('t') { '.' }
                when('.') { <. H>[[f[y-1 .. y+1]].map{.[x-1 .. x+1]}.count('H') ~~ [1,2]] }
                default   { c }
              }
            )
        }
        rr << ''
        a << rr
    }
    f = [a..., []]
}

__DATA__
tH.........
.   .
   ...
.   .
Ht.. ......

Smalltalk

See: Wireworld/Smalltalk

Standard ML

(* Maximilian Wuttke 12.04.2016 *)

type world = char vector vector

fun getstate (w:world, (x, y)) = (Vector.sub (Vector.sub (w, y), x)) handle Subscript => #" "

fun conductor (w:world, (x, y)) =
	let
	  val s = [getstate (w, (x-1, y-1)) = #"H", getstate (w, (x-1, y)) = #"H", getstate (w, (x-1, y+1)) = #"H",
	           getstate (w, (x,   y-1)) = #"H",                                getstate (w, (x,   y+1)) = #"H",
	           getstate (w, (x+1, y-1)) = #"H", getstate (w, (x+1, y)) = #"H", getstate (w, (x+1, y+1)) = #"H"]
	  (* Count `true` in s *)
	  val count = List.length (List.filter (fn x => x=true) s)
	in
	  if count = 1 orelse count = 2 then #"H" else #"."
	end

fun translate (w:world, (x, y)) =
	case getstate (w, (x, y)) of
	   #" " => #" "
	 | #"H" => #"t"
	 | #"t" => #"."
	 | #"." => conductor (w, (x, y))
	 | s    => s

fun next_world (w : world) = Vector.mapi (fn (y, row) => Vector.mapi (fn (x, _) => translate (w, (x, y))) row) w


(* Test *)

(* makes a list of strings into a world *)
fun make_world (rows : string list) : world =
	Vector.fromList (map (fn (row : string) => Vector.fromList (explode row)) rows)


(* word_str reverses make_world *)
fun vec_str (r:char vector) = implode (List.tabulate (Vector.length r, fn x => Vector.sub (r, x)))
fun world_str (w:world)     = List.tabulate (Vector.length w, fn y => vec_str (Vector.sub (w, y)))
fun print_world (w:world)   = (map (fn row_str => print (row_str ^ "\n")) (world_str w); ())

val test = make_world [
	"tH.........",
	".   .      ",
	"   ...     ",
	".   .      ",
	"Ht.. ......"]

Tcl

See: Wireworld/Tcl

Ursala

The board is represented as a list of character strings, and the neighborhoods function uses the swin library function twice to construct a two dimensional 3 by 3 sliding window. The rule function maps a pair (cell,neighborhood) to a new cell.

#import std

rule          = case~&l\~&l {`H: `t!, `t: `.!,`.: @r ==`H*~; {'H','HH'}?</`H! `.!}

neighborhoods = ~&thth3hthhttPCPthPTPTX**K7S+ swin3**+ swin3@hNSPiCihNCT+ --<0>*+ 0-*

evolve "n"    = @iNC ~&x+ rep"n" ^C\~& rule**+ neighborhoods@h

test program:

diode =

<
   '        ..   ',
   'tH....... .Ht',
   '        ..   '>

#show+

example = mat0 evolve13 diode
Output:
        ..   
tH....... .Ht
        ..   

        ..   
.tH...... Ht.
        ..   

        .H   
..tH..... t..
        .H   

        Ht   
...tH...H ...
        Ht   

        t.   
....tH..t ...
        t.   

        ..   
.....tH.. ...
        ..   

        ..   
......tH. ...
        ..   

        H.   
.......tH ...
        H.   

        tH   
........t ...
        tH   

        .t   
......... H..
        .t   

        ..   
......... tH.
        ..   

        ..   
......... .tH
        ..   

        ..   
......... ..t
        ..   

        ..   
......... ...
        ..   

Wren

Translation of: Go
Library: wren-fmt
Library: Wren-ioutil
import "./fmt" for Fmt
import "./ioutil" for FileUtil, Stdin

var rows = 0     // extent of input configuration
var cols = 0     // """
var rx   = 0     // grid extent (includes border)
var cx   = 0     // """
var mn   = []    // offsets of Moore neighborhood

var print = Fn.new { |grid|
    System.print("__" * cols)
    System.print()
    for (r in 1..rows) {
        for (c in 1..cols) Fmt.write(" $s", grid[r*cx+c])
        System.print()
    }
}

var step = Fn.new { |dst, src|
    for (r in 1..rows) {
        for (c in 1..cols) {
            var x = r*cx + c
            dst[x] = src[x]
            if (dst[x] == "H") {
                dst[x] = "t"
            } else if (dst[x] == "t") {
                dst[x] = "."
            } else if (dst[x] == ".") {
                var nn = 0
                for (n in mn) {
                    if (src[x+n] == "H") nn = nn + 1
                }
                if (nn == 1 || nn == 2) dst[x] = "H"
            }
        }
    }
}

var srcRows = FileUtil.readLines("ww.config")
rows = srcRows.count
for (r in srcRows) {
    if (r.count > cols) cols = r.count
}
rx = rows + 2
cx = cols + 2
mn = [-cx-1, -cx, -cx+1, -1, 1, cx-1, cx, cx+1]

// allocate two grids and copy input into first grid
var odd  = List.filled(rx*cx, " ")
var even = List.filled(rx*cx, " ")

var ri = 0
for (r in srcRows) {
    for (i in 0...r.count) {
        odd[(ri+1)*cx+1+i] = r[i]
    }
    ri = ri + 1
}

// run
while (true) {
    print.call(odd)
    step.call(even, odd)
    Stdin.readLine() // wait for enter to be pressed

    print.call(even)
    step.call(odd, even)
    Stdin.readLine() // ditto
}
Output:
Although not shown, same as Go output.

XPL0

include c:\cxpl\codes;          \intrinsic 'code' declarations
char New(53,40), Old(53,40);

proc Block(X0, Y0, C);          \Display a colored block
int  X0, Y0, C;                 \big (6x5) coordinates, char
int  X, Y;
[case C of                      \convert char to color
  ^H:   C:= $9;                 \blue
  ^t:   C:= $C;                 \red
  ^.:   C:= $E                  \yellow
other   C:= 0;                  \black
for Y:= Y0*5 to Y0*5+4 do       \make square blocks by correcting aspect ratio
    for X:= X0*6 to X0*6+5 do   \ (6x5 = square)
        Point(X,Y,C);
];

int X, Y, C;
[SetVid($13);                   \set 320x200 graphics display
for Y:= 0 to 40-1 do            \initialize New with space (empty) characters
    for X:= 0 to 53-1 do
        New(X, Y):= ^ ;
X:= 1;  Y:= 1;                  \read file from command line, skipping borders
loop    [C:= ChIn(1);
        case C of
          $0D:  X:= 1;          \carriage return
          $0A:  Y:= Y+1;        \line feed
          $1A:  quit            \end of file
        other   [New(X,Y):= C;  X:= X+1];
        ];
repeat  C:= Old;  Old:= New;  New:= C;  \swap arrays, by swapping their pointers
        for Y:= 1 to 39-1 do            \generate New array from Old
            for X:= 1 to 52-1 do        \ (skipping borders)
                [case Old(X,Y) of
                  ^ :   New(X,Y):= ^ ;  \copy empty to empty
                  ^H:   New(X,Y):= ^t;  \convert head to tail
                  ^t:   New(X,Y):= ^.   \convert tail to conductor
                other   [C:= (Old(X-1,Y-1)=^H) + (Old(X+0,Y-1)=^H) + \head count
                             (Old(X+1,Y-1)=^H) + (Old(X-1,Y+0)=^H) + \ in neigh-
                             (Old(X+1,Y+0)=^H) + (Old(X-1,Y+1)=^H) + \ boring
                             (Old(X+0,Y+1)=^H) + (Old(X+1,Y+1)=^H);  \ cells
                        New(X,Y):= if C=-1 or C=-2 then ^H else ^.;  \ (true=-1)
                        ];
                Block(X, Y, New(X,Y));  \display result
                ];
        Sound(0, 6, 1);                 \delay about 1/3 second
until   KeyHit;                         \keystroke terminates program
SetVid(3);                              \restore normal text mode
]

Yabasic

open window 230,130
backcolor 0,0,0
clear window

label circuit
	DATA "             "
	DATA " tH......... "
	DATA " .   .       "
	DATA "    ...      "
	DATA " .   .       "
	DATA " Ht.. ...... "
	DATA "             "
	DATA ""
	
do
	read a$
	if a$ = "" break
	n = n + 1
	redim t$(n)
	t$(n) = a$+a$
loop

size = len(t$(1))/2
E2 = size
first = true
Orig = 0
Dest = E2

do
  for y = 2 to n-1
    for x = 2 to E2-1
      switch mid$(t$(y),x+Orig,1)
        case " ": color 32,32,32 : mid$(t$(y),x+Dest,1) = " " : break
        case "H": color 0,0,255 : mid$(t$(y),x+Dest,1) = "t" : break
        case "t": color 255,0,0 : mid$(t$(y),x+Dest,1) = "." : break
        case ".":
          color 255,200,0
          t = 0
          for y1 = y-1 to y+1
          	for x1 = x-1 to x+1          		
          		t = t + ("H" = mid$(t$(y1),x1+Orig,1))
          	next x1
          next y1
          if t=1 or t=2 then
          	mid$(t$(y),x+Dest,1) = "H"
          else
          	mid$(t$(y),x+Dest,1) = "."
          end if
      end switch
      fill circle x*16, y*16, 8
    next x
    print t$(y),"="
  next y
  first = not first
  if first then
  	Orig = 0 : Dest = E2
  else
  	Orig = E2 : Dest = 0
  end if
  wait .5
loop