QBasic, 309 bytes
Warning: the golfed version is not user-friendly: it has a weird input method, runs as an infinite loop, and doesn't have any delay (thus, runs too fast on some systems). Only run it if you know how to terminate a program in your QBasic environment. The ungolfed version is recommended (see below).
INPUT w,h
SCREEN 9
FOR y=1TO h
FOR x=1TO w
PSET(x,y),VAL(INPUT$(1))
NEXT
NEXT
DO
FOR y=1TO h
FOR x=1TO w
SCREEN,,0
c=POINT(x,y)
d=c
IF c=7THEN d=1
IF c=1THEN d=6
IF c=6THEN
n=0
FOR v=y-1TO y+1
FOR u=x-1TO x+1
n=n-(POINT(u,v)=7)
NEXT
NEXT
d=7+(n=0OR n>2)
END IF
SCREEN,,1,0
PSET(x,y),d
NEXT
NEXT
PCOPY 1,0
LOOP
To run, specify at the input prompt your configuration's width w
and height h
.1 Then type w*h
single-digit codes for the cells (moving left to right, then top to bottom), with
0
= empty
6
= wire
7
= signal head
1
= signal tail
Once you have entered all of the cells, the simulation will begin (and continue forever, until you kill the program).
Ungolfed
A more user-friendly version. To modify the layout, modify the DATA
statements at the end.
The code takes advantage of the POINT
function, which reads the color value of a pixel from the screen. This means we don't have to store the cells separately as an array. To make sure that all cells update simultaneously, we perform the updates on a second "page." We can toggle the active page using a version of the SCREEN
statement, and copy one page's contents to another using the PCOPY
statement.
SCREEN 9
EMPTY = 0 ' Black
HEAD = 7 ' Light gray
TAIL = 1 ' Blue
WIRE = 6 ' Brown/orange
' First two data values are the width and height
READ w, h
' The rest are the initial configuration, row by row
' Read them and plot the appropriately colored pixels
FOR y = 1 TO h
FOR x = 1 TO w
READ state$
IF state$ = "" THEN value = EMPTY
IF state$ = "H" THEN value = HEAD
IF state$ = "T" THEN value = TAIL
IF state$ = "W" THEN value = WIRE
PSET (x, y), value
NEXT x
NEXT y
' Loop the simulation until user presses a key
DO UNTIL INKEY$ <> ""
' Store current time for delay purposes
t# = TIMER
FOR y = 1 TO h
FOR x = 1 TO w
' Active page = display page = 0
SCREEN , , 0
' Get the color value of the pixel at x,y
oldVal = POINT(x, y)
IF oldVal = EMPTY THEN
newVal = EMPTY
ELSEIF oldVal = HEAD THEN
newVal = TAIL
ELSEIF oldVal = TAIL THEN
newVal = WIRE
ELSEIF oldVal = WIRE THEN
neighbors = 0
FOR ny = y - 1 TO y + 1
FOR nx = x - 1 TO x + 1
IF POINT(nx, ny) = HEAD THEN neighbors = neighbors + 1
NEXT nx
NEXT ny
IF neighbors = 1 OR neighbors = 2 THEN
newVal = HEAD
ELSE
newVal = WIRE
END IF
END IF
' Active page = 1, display page = 0
SCREEN , , 1, 0
' Plot the new value on page 1
PSET (x, y), newVal
NEXT x
NEXT y
' Copy page 1 to page 0
PCOPY 1, 0
' Delay
WHILE TIMER >= t# AND t# + 0.2 > TIMER
WEND
LOOP
DATA 8,5
DATA T,H,W,W,W,W,W,W
DATA W, , , ,W, , ,
DATA , , ,W,W,W, ,
DATA W, , , ,W, , ,
DATA H,T,W,W, ,W,W,W
1 The maximum values for width and height depend on which screen mode is used. In SCREEN 9
, width can be up to 638 and height up to 348. SCREEN 7
has a smaller resolution (max configuration size 318 by 198), but the pixels are bigger and thus easier to see (on DOS QBasic or the DOSBox emulator--unfortunately QB64 just gives a smaller window).
Example run
Ungolfed version on archive.org, with screen mode 7:
