Conway's game of life [faster version]
Here is a Conway's Game of Life.
The code of the starting sets is the RLE coding usually found on Internet.
Version 1.0 Time per generation: 5226 ms
The board is 80x80 and with zoom by 3x
The number of neighbors is stored in the color scheme. It avoid the need of other storage.
Optimization:
- Each pixel/cell stores neighbors only horizontally, so each partial count is used in 3 different cells.
But it is still highly unoptimized.
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
Black, White;
LNext()
BEGIN
LOCAL px, py, Clr, Tmp;
// Calcul Voisins
FOR py FROM 1 TO 78 DO
FOR px FROM 1 TO 78 DO
Tmp:= BITAND(GETPIX_P(px-1, py),#800h)+BITAND(GETPIX_P(px, py),#800h)+BITAND(GETPIX_P(px+1, py),#800h);
Tmp:=BITAND(GETPIX_P(px, py),White)+#18h-BITSR(Tmp,8);
PIXON_P(px, py, Tmp);
END;
END;
FOR py FROM 1 TO 78 DO
FOR px FROM 1 TO 78 DO
Tmp:= BITAND(GETPIX_P(px, py-1),#18h)+BITAND(GETPIX_P(px, py),#18h)+BITAND(GETPIX_P(px, py+1),#18h);
IF (Tmp == #18h AND BITAND(GETPIX_P(px, py),#800h) <> 0) OR ((Tmp == #20h OR Tmp == #18h) AND BITAND(GETPIX_P(px, py),#800h) == 0) THEN
Clr:= Black;
ELSE
Clr:= White;
END;
PIXON_P(px, py, Clr+BITAND(GETPIX_P(px, py),#18h));
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,0,79,79);
END;
RLEMap (px, py, RLE, ClrOn)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= 0; Col:= 0; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1); // pour debogage
CASE
IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= 0; Cnt:= 0; END;
IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", MID(RLE, Ptr, 1)) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
PIXON_P(px+Col, py+Row, ClrOn);
END;
Cnt:= 0; END;
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,0,79,79);
END;
EXPORT Life(St)
BEGIN
LOCAL Kb;
Black:= #0h; White:= #F8F8E0h;
RECT_P(0,0,319,239,White);
IF St == 1 THEN
RLEMap (10, 11, "3o!", Black); // Blinker
RLEMap (23, 14, "bo$3o$obo$3o$bo!", Black); // Pulsar
LNext();
RLEMap (10, 16, "b3o$3o!", Black); // Toad
RLEMap (40, 14, "bo$3o$obo$3o$bo!", Black); // Pulsar
RLEMap (10, 26, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!", Black); // Canon
END;
IF St == 2 THEN
RLEMap (27, 18, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!", Black);
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!", Black);
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!", Black); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (50, 60, "bo$3bo$2o2b3o!", Black); // Acorn
END;
REPEAT LNext(); Kb:= GETKEY(); UNTIL Kb==4;
END;
Version 1.1 Time per generation: 2184 ms
Optimizations:
- avoid empty lines recalc.
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
Lignes, Black, White;
LNext()
BEGIN
LOCAL px, py, Clr, Tmp;
// Calcul Voisins
FOR py FROM 1 TO 78 DO
CASE
IF Lignes[py+1] == 1 THEN
LINE_P(0,py,79,py,White);
Lignes[py+1] := 0;
END;
IF Lignes[py+1] == 2 THEN
FOR px FROM 1 TO 78 DO
Tmp:= BITAND(GETPIX_P(px-1, py),#800h)+BITAND(GETPIX_P(px, py),#800h)+BITAND(GETPIX_P(px+1, py),#800h);
Tmp:=BITAND(GETPIX_P(px, py),White)+#18h-BITSR(Tmp,8);
PIXON_P(px, py, Tmp);
END;
END;
END;
END;
FOR py FROM 1 TO 78 DO
IF Lignes[py]+Lignes[py+1]+Lignes[py+2] <> 0 THEN
IF Lignes[py+1] == 2 THEN Lignes[py+1] := 1; END;
FOR px FROM 1 TO 78 DO
Tmp:= BITAND(GETPIX_P(px, py-1),#18h)+BITAND(GETPIX_P(px, py),#18h)+BITAND(GETPIX_P(px, py+1),#18h);
IF (Tmp == #18h AND BITAND(GETPIX_P(px, py),#800h) <> 0) OR ((Tmp == #20h OR Tmp == #18h) AND BITAND(GETPIX_P(px, py),#800h) == 0) THEN
Clr:= Black; Lignes[py+1] := 2;
ELSE
Clr:= White;
END;
PIXON_P(px, py, Clr+BITAND(GETPIX_P(px, py),#18h));
END;
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,0,79,79);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= 0; Col:= 0; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1); // pour debogage
CASE
IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= 0; Cnt:= 0; END;
IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", MID(RLE, Ptr, 1)) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
PIXON_P(px+Col, py+Row, Black);
END;
Cnt:= 0; Lignes[py+Row+1]:= 2;
END;
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,0,79,79);
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, Lap;
Black:= #0h; White:= #F8F8E0h;
Lignes:= MAKELIST(0,A,0,79);
RECT_P(0,0,319,239,White);
IF St == 1 THEN
RLEMap (10, 11, "3o!"); // Blinker
RLEMap (23, 14, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (10, 16, "b3o$3o!"); // Toad
RLEMap (40, 14, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (10, 26, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Canon
END;
IF St == 2 THEN
RLEMap (27, 18, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!");
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!");
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (50, 60, "bo$3bo$2o2b3o!"); // Acorn
END;
REPEAT
Lap:= TICKS();
LNext();
Lap:= TICKS()-Lap;
// to display time between screen updates
TEXTOUT_P(Lap,0,160,0,Black,80,White);
Kb:= GETKEY();
UNTIL Kb==4;
END;
Version 1.2 Time per generation: 763 ms
Optimizations:
- avoid empty lines and empty trails recalc.
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// 1.1 2014/02 Little optimization for speed to avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed to avoid recalc of empty left and right
Lignes, Black, White;
LNext()
BEGIN
LOCAL px, py, db, fn, Clr, Tmp;
// Calcul Voisins
FOR py FROM 2 TO 81 DO
CASE
IF Lignes[py,1] == 1 THEN
LINE_P(0,py,79,py,White);
Lignes[py] := {0,80,0};
END;
IF Lignes[py,1] == 2 THEN
db:= MAX(Lignes[py,2]-1,1); fn:= MIN(Lignes[py,3]+1,78);
Lignes[py] := {2,80,0};
FOR px FROM db TO fn DO
Tmp:= #18h-BITSR(BITAND(GETPIX_P(px-1, py),#800h)+BITAND(GETPIX_P(px, py),#800h)+BITAND(GETPIX_P(px+1, py),#800h),8);
IF Tmp <> #0 THEN Lignes[py] := {2,MIN(Lignes[py,2],px),MAX(Lignes[py,3],px)}; END;
PIXON_P(px, py, BITAND(GETPIX_P(px, py),White)+Tmp);
END;
END;
END;
END;
FOR py FROM 2 TO 81 DO
IF Lignes[py-1,1]+Lignes[py,1]+Lignes[py+1,1] <> 0 THEN
db:= MIN(Lignes[py-1,2],Lignes[py,2],Lignes[py+1,2]); fn:=MAX(Lignes[py-1,3],Lignes[py,3],Lignes[py+1,3]);
IF Lignes[py,1] == 2 THEN Lignes[py,1]:= 1; END;
FOR px FROM db TO fn DO
Tmp:= BITAND(GETPIX_P(px, py-1),#18h)+BITAND(GETPIX_P(px, py),#18h)+BITAND(GETPIX_P(px, py+1),#18h);
IF (Tmp == #18h AND BITAND(GETPIX_P(px, py),#800h) <> 0) OR ((Tmp == #20h OR Tmp == #18h) AND BITAND(GETPIX_P(px, py),#800h) == 0) THEN
Clr:= Black; Lignes[py] := {2,MIN(Lignes[py,2],px),MAX(Lignes[py,3],px)};
ELSE
Clr:= White;
END;
PIXON_P(px, py, Clr+BITAND(GETPIX_P(px, py),#18h));
END;
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,2,79,81);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= py+2; Col:= px+1; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1); // for debug
CASE
IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px+1; Cnt:= 0; END;
IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", MID(RLE, Ptr, 1)) <> 0 THEN
Lignes[Row,1]:= 2; Lignes[Row,2]:= MIN(Lignes[Row,2],Col);
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
PIXON_P(Col, Row, Black);
END;
Cnt:= 0; Lignes[Row,3]:= MAX(Lignes[Row,3],Col);
END;
END;
END;
BLIT_P(G0,80,0,319,239,G0,0,2,79,81);
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, Lap;
Black:= #0h; White:= #F8F8E0h;
Lignes:= MAKELIST({0,80,0},A,0,83);
RECT_P(0,0,319,239,White);
IF St == 1 THEN
RLEMap (10, 11, "3o!"); // Blinker
RLEMap (23, 14, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (10, 16, "b3o$3o!"); // Toad
RLEMap (40, 14, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (10, 26, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Canon
END;
IF St == 2 THEN
RLEMap (0, 0, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!");
END;
IF St == 3 THEN
RLEMap (0, 0, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
REPEAT
Lap:= TICKS();
LNext();
Lap:= TICKS()-Lap;
// to display time between screen updates
TEXTOUT_P(Lap,0,160,0,Black,80,White);
Kb:= GETKEY();
UNTIL Kb==4;
END;
Version 2.0 Time per generation: 218 ms
New method: The board is stored as a bitmap
The board is 80x80 and with zoom by 3x
Optimization: counting is done by bitwise operations only
Calc need to be set as Hexadecimal 64 bits (rev 6030: not needed anymore thanks to new pragme feature)
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// The 2 lower bits of each pixels is used to store neighb on right and left.
// 1.1 2014/02 Little optimization for speed
// Avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed
// Avoid recalc of empty left and right
// 2.0 2014/02 Even faster, better scaling
// using bitmap storage and bitwise operations
Lignes;
LOcc(Lst) // Occurence
BEGIN
LOCAL v1, v2, v3, v4, sx, cx;
v1:= #0; v2:= #0; v3:= #0; v4:= #0;
FOR sx FROM 1 TO SIZE(Lst) DO
cx:= Lst(sx);
v4:= BITOR(v4,BITAND(v3,cx)); v3:= BITOR(v3,BITAND(v2,cx));
v2:= BITOR(v2,BITAND(v1,cx)); v1:= BITOR(v1,cx);
END;
RETURN {v1, v2, v3, v4};
END;
LNext()
BEGIN
LOCAL T1, T2, T3, L, Tmp;
Tmp:= MAKELIST({#0,#0},A,1,82);
FOR L FROM 2 TO 81 DO
IF BITOR(Lignes(L-1,1),Lignes(L,1),Lignes(L+1,1)) <> #0 THEN
T1:= LOcc({BITSL(Lignes(L-1,1),1),Lignes(L-1,1),BITSR(Lignes(L-1,1),1), BITSL(Lignes(L,1),1),BITSR(Lignes(L,1),1), BITSL(Lignes(L+1,1),1),Lignes(L+1,1),BITSR(Lignes(L+1,1),1)});
T2:= BITAND(BITOR(BITXOR(T1(3),T1(4)), BITAND(BITXOR(T1(2),T1(3)),Lignes(L,1))),#1FFFFFFFFFE);
//IF BITAND(T2, #10000000000) <> #0 THEN T3:= #1; ELSE T3:= #0; END;
T3:= BITSR(T2, 40);
ELSE
T2:= #0; T3:= #0;
END;
IF BITOR(Lignes(L-1,2),Lignes(L,2),Lignes(L+1,2)) <> #0 THEN
T1:= LOcc({BITSL(Lignes(L-1,2),1),Lignes(L-1,2),BITSR(Lignes(L-1,2),1), BITSL(Lignes(L,2),1),BITSR(Lignes(L,2),1), BITSL(Lignes(L+1,2),1),Lignes(L+1,2),BITSR(Lignes(L+1,2),1)});
T3:= BITOR(T3,BITAND(BITOR(BITXOR(T1(3),T1(4)), BITAND(BITXOR(T1(2),T1(3)),Lignes(L,2))),#1FFFFFFFFFE));
IF BITAND(T3, #2) <> #0 THEN T2:= BITOR(T2,#20000000000) END;
END;
Tmp(L):={T2,T3};
END;
Lignes:= Tmp;
END;
LDisp()
BEGIN
LOCAL T1, L, L2, C2;
RECT_P(0,0,79,82,#F8F8E0h);
FOR L FROM 2 TO 81 DO
FOR L2 FROM 1 TO 2 DO
T1:= Lignes(L,L2); C2:= (L2-1)*40;
WHILE T1 <> 0 DO
IF BITAND(T1,#1) THEN PIXON_P(C2, L, #0); END;
T1:= BITSR(T1,1); C2:= C2+1;
END;
END;
END;
BLIT_P(G0,80,0,320,240,G0,0,2,80,82);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= py+2; Col:= px; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1); // for debug
CASE
IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px; Cnt:= 0; END;
IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", MID(RLE, Ptr, 1)) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
Lignes(Row, IP(Col/40)+1):= BITOR(Lignes(Row, IP(Col/40)+1), BITSL(#1,(Col MOD 40)+1 ));
END;
Cnt:= 0;
END;
END;
END;
FOR Row FROM 2 TO 81 DO
IF BITAND(Lignes(Row,1), #10000000000) <> #0 THEN Lignes(Row,2):= BITOR(Lignes(Row,2),#1) END;
IF BITAND(Lignes(Row,2), #2) <> #0 THEN Lignes(Row,1):= BITOR(Lignes(Row,1),#20000000000) END;
END;
LDisp();
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, Lap;
Lignes:= MAKELIST({#0,#0},A,1,82);
RECT_P(0,0,319,239,#F8F8E0h);
IF St == 1 THEN
RLEMap (1, 1, "3o!"); // Blinker
RLEMap (13, 5, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (1, 6, "b3o$3o!"); // Toad
RLEMap (30, 5, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (1, 17, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Glider Canon
END;
IF St == 2 THEN
RLEMap (1, 1, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!"); // Pre-pulsar shuttle 29
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
REPEAT
Lap:= TICKS();
LNext(); LDisp();
Lap:= TICKS()-Lap;
// to display time between screen updates
TEXTOUT_P(Lap,0,160,0,#0,80,#F8F8E0h);
Kb:= GETKEY();
UNTIL Kb==4;
END;
Version 2.2 Time per generation: 331 ms
added screen trail (green)
Optimization:
- unrolled the loop and removed unneeded operations in LOcc
Calc need to be set as Hexadecimal 64 bits (rev 6030: not needed anymore thanks to new pragme feature)
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// The 2 lower bits of each pixels is used to store neighb on right and left.
// 1.1 2014/02 Little optimization for speed
// Avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed
// Avoid recalc of empty left and right
// 2.0 2014/02 Even faster, better scaling
// using bitmap storage and bitwise operations
// 2.1 2014/02 with trail
// show life span in green
// 2.2 A little optimization in LOcc
// Unrolled the loop and removed unneeded ops
// the Game of Life play field is 80*80 cells
// each ligne is stored in 2 integers using 2 time 40 bits
// Slice = 40
// Mask = 2^41-2= #1FFFFFFFFFEh
// LeftBit = 2^41 = #10000000000h
// RightLink= 2^42 = #20000000000h
// LeftLink = 1 = 1h
// RightBit = 2 = 2h
EXPORT Lignes, Trail;
LOcc(P1, P2, P3) // Occurence
BEGIN
LOCAL v1, v2, v3, v4, T;
v2:= BITAND(P1,P3); v1:= BITOR(P1,P3);
T:= BITSR(P1);
v3:= BITAND(v2,T); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P1);
v4:= BITAND(v3,T); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSR(P2);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P2);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSR(P3);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P3);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
RETURN {v1, v2, v3, v4};
END;
LNext()
BEGIN
LOCAL T1, T2, T3, L;
Trail:= Lignes;
FOR L FROM 2 TO 81 DO
IF BITOR(Trail(L-1,1),Trail(L,1),Trail(L+1,1)) <> #0 THEN
T1:= LOcc(Trail(L-1,1),Trail(L,1),Trail(L+1,1));
T2:= BITAND(BITOR(BITXOR(T1(3),T1(4)), BITAND(BITXOR(T1(2),T1(3)),Trail(L,1))),#1FFFFFFFFFE);
//IF BITAND(T2, #10000000000) <> #0 THEN T3:= #1; ELSE T3:= #0; END;
T3:= BITSR(T2, 40);
ELSE
T2:= #0; T3:= #0;
END;
IF BITOR(Trail(L-1,2),Trail(L,2),Trail(L+1,2)) <> #0 THEN
T1:= LOcc(Trail(L-1,2),Trail(L,2),Trail(L+1,2));
T3:= BITOR(T3,BITAND(BITOR(BITXOR(T1(3),T1(4)), BITAND(BITXOR(T1(2),T1(3)),Trail(L,2))),#1FFFFFFFFFE));
IF BITAND(T3, #2) <> #0 THEN T2:= BITOR(T2,#20000000000) END;
END;
Lignes(L):={T2,T3};
END;
END;
LDisp()
BEGIN
LOCAL T1, Tr, L, L2, C2;
//RECT_P(0,0,79,82,#F8F8E0h);
FOR L FROM 2 TO 81 DO
FOR L2 FROM 1 TO 2 DO
T1:= Lignes(L,L2); Tr:= Trail(L,L2); C2:= (L2-1)*40-1;
WHILE T1 <> #0 OR Tr <> #0 DO
IF BITAND(T1,#1) THEN PIXON_P(C2, L, #0);
ELSE
IF BITAND(Tr,#1) THEN PIXON_P(C2, L, #F800); END;
END;
T1:= BITSR(T1,1); Tr:= BITSR(Tr,1); C2:= C2+1;
END;
END;
END;
BLIT_P(G0,80,0,320,240,G0,0,2,80,82);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= py+2; Col:= px; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1); // for debug
CASE
IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px; Cnt:= 0; END;
IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", MID(RLE, Ptr, 1)) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
Lignes(Row, IP(Col/40)+1):= BITOR(Lignes(Row, IP(Col/40)+1), BITSL(#1,(Col MOD 40)+1 ));
END;
Cnt:= 0;
END;
END;
END;
FOR Row FROM 2 TO 81 DO
IF BITAND(Lignes(Row,1), #10000000000) <> #0 THEN Lignes(Row,2):= BITOR(Lignes(Row,2),#1) END;
IF BITAND(Lignes(Row,2), #2) <> #0 THEN Lignes(Row,1):= BITOR(Lignes(Row,1),#20000000000) END;
END;
LDisp();
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, Lap;
Lignes:= MAKELIST({#0,#0},A,1,82);
Trail:= MAKELIST({#0,#0},A,1,82);
RECT_P(0,0,319,239,#F8F8E0h);
IF St == 1 THEN
RLEMap (1, 1, "3o!"); // Blinker
RLEMap (13, 5, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (1, 6, "b3o$3o!"); // Toad
RLEMap (30, 5, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (1, 17, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Glider Canon
END;
IF St == 2 THEN
RLEMap (1, 1, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!"); // Pre-pulsar shuttle 29
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (38, 38, "bo$3bo$2o2b3o!"); // Acorn
END;
REPEAT
Lap:= TICKS();
LNext(); LDisp();
Lap:= TICKS()-Lap;
// to display time between screen updates
TEXTOUT_P(Lap,0,160,0,#0,80,#F8F8E0h);
Kb:= GETKEY();
UNTIL Kb==4;
END;
Version 2.3 Time per generation: 350 ms
The board is now 120x100 and with zoom by 2x
the Next Generation is now computed in constant time, the difference in timing now depend on the number of cells alive to display.
Optimization:
- Taking advantage of lists special handling, it compensate a board twice as big
Look at set 6 (Acorn Set)
Calc need to be set as Hexadecimal 64 bits (rev 6030: not needed anymore thanks to new pragme feature)
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// The 2 lower bits of each pixels is used to store neighb on right and left.
// 1.1 2014/02 Little optimization for speed
// Avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed
// Avoid recalc of empty left and right
// 2.0 2014/02 Even faster, better scaling
// using bitmap storage and bitwise operations
// 2.1 2014/02 with trail
// show life span in green
// 2.2 A little optimization in LOcc
// Unrolled the loop and removed unneeded ops
// 2.3 board is now 120*100 and zoom x2 and
// Next Gen takes advantage of calc on lists
// the Game of Life play field is 120*100 cells
EXPORT Lignes, Trail;
LOcc(P1, P2, P3) // Occurence
BEGIN
LOCAL v1, v2, v3, v4, T;
v2:= BITAND(P1,P3); v1:= BITOR(P1,P3);
T:= BITSR(P1);
v3:= BITAND(v2,T); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P1);
v4:= BITAND(v3,T); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSR(P2);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P2);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSR(P3);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); v1:= BITOR(v1,T);
T:= BITSL(P3);
v4:= BITOR(v4,BITAND(v3,T)); v3:= BITOR(v3,BITAND(v2,T)); v2:= BITOR(v2,BITAND(v1,T)); // v1:= BITOR(v1,T);
RETURN {v1, v2, v3, v4};
END;
LNext() // Next Generation
BEGIN
LOCAL T1, T2, Row;
Trail:= Lignes;
Trail(1):= BITOR(Trail(1),BITSL(BITAND(Trail(2),#2),60));
Trail(2):= BITOR(Trail(2),BITSR(Trail(1),60));
FOR Row FROM 1 TO 2 DO
T1:= LOcc(SUB(Trail(Row),1,100),SUB(Trail(Row),2,101),SUB(Trail(Row),3,102));
T2:= BITAND(BITOR(BITXOR(T1(3),T1(4)), BITAND(BITXOR(T1(2),T1(3)),SUB(Trail(Row),2,101))),#1FFFFFFFFFFFFFFE);
Lignes(Row):= CONCAT(#0,T2,#0);
END;
END;
LDisp()
BEGIN
LOCAL T1, Tr, L, L2, C2;
FOR L2 FROM 1 TO 2 DO
FOR L FROM 0 TO 99 DO
T1:= Lignes(L2,L+1); Tr:= Trail(L2,L+1); C2:= (L2-1)*60-1;
WHILE T1 <> #0 OR Tr <> #0 DO
IF BITAND(T1,#1) THEN PIXON_P(L, C2, #0);
ELSE
IF BITAND(Tr,#1) THEN PIXON_P(L, C2, #F800); END;
END;
T1:= BITSR(T1,1); Tr:= BITSR(Tr,1); C2:= C2+1;
END;
END;
END;
BLIT_P(G0,120,0,320,240,G0,0,0,100,120);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod;
Row:= py; Col:= px+2; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1);
CASE
IF INSTRING("0123456789", Cod) <> 0 THEN Cnt:= Cnt*10+EXPR(Cod); END;
IF Cod == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px+2; Cnt:= 0; END;
IF INSTRING("b.", Cod) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", Cod) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
Lignes(IP(Row/60)+1, Col):= BITOR(Lignes(IP(Row/60)+1, Col), BITSL(#2,(Row MOD 60) ));
END;
Cnt:= 0;
END;
END;
END;
LDisp();
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, Lap;
Lignes:= MAKELIST(MAKELIST(#0,B,1,102),A,1,2);
Trail:= Lignes;
RECT_P(0,0,319,239,#F8F8E0h);
IF St == 1 THEN
RLEMap (1, 1, "3o!"); // Blinker
RLEMap (13, 5, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (1, 6, "b3o$3o!"); // Toad
RLEMap (30, 5, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (1, 17, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Glider Canon
END;
IF St == 2 THEN
RLEMap (1, 1, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!"); // Pre-pulsar shuttle 29
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (50, 60, "bo$3bo$2o2b3o!"); // Acorn
END;
IF St == 6 THEN
RLEMap (52, 80, "o$obo$$bo$o$o$o!"); // Acorn vertical
END;
REPEAT
Lap:= TICKS();
LNext(); LDisp();
Lap:= TICKS()-Lap;
// to display time between screen updates
TEXTOUT_P(Lap,0,225,0,#0,80,#F8F8E0h);
Kb:= GETKEY();
UNTIL Kb==4;
END;
Version 2.4 zoom x 2 Time per generation: 350 ms
The board is now 120x160 and with zoom by 2x
Optimization:
- LDisp now detects changes since last generation and only draw the changes.
- LNext now detects changes since last generation and only calc thoses places
- LNext1 is LNext version that handle lists, rename to LNext to test it
Look at set 7 (Snark Glider Reflector Loop), this set is Fast and Furious.
Acorn sets (5 and 6) are also impressives.
Calc need to be set as Hexadecimal 64 bits (rev 6030: not needed anymore thanks to new pragme feature)
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// The 2 lower bits of each pixels is used to store neighb on right and left.
// 1.1 2014/02 Little optimization for speed
// Avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed
// Avoid recalc of empty left and right
// 2.0 2014/02 Even faster, better scaling
// using bitmap storage and bitwise operations
// 2.1 2014/02 with PrevN
// show life span in green
// 2.2 A little optimization in LOcc
// Unrolled the loop and removed unneeded ops
// 2.3 board is now 120*160 and zoom x2 and
// Next Gen takes advantage of lists handling
// 2.4 Getting Fast and Furious on large sets
// the Game of Life play field is 120*160 cells
// each ligne is stored in 2 integers using 2 time 60 bits
// Slice = 60
// Mask = 2^61-2= #1FFFFFFFFFFFFFFEh
EXPORT Lignes;
PrevD, PrevN, Delta, Tmp;
IterMax:= -1;
//This routine is good with small sets but do degrade with big ones.
LNext() // Next Generation one by one elements
BEGIN
LOCAL R, Row;
LOCAL P1, P2, P3, v1, v2, v3, v4;
// Link between columns
FOR R FROM 1 TO 2 DO
Tmp:= Lignes(R);
IF R <> 1 THEN Tmp:= BITOR(Tmp,BITAND(BITSR(PrevN(R-1),60),#1)); END;
IF R <> 2 THEN Tmp:= BITOR(Tmp,BITSL(BITAND(Lignes(R+1),#2),60)); END;
Delta:= BITXOR(PrevN(R),Tmp);
PrevN(R):=Tmp;
FOR Row FROM 2 TO 161 DO
IF BITOR(Delta(Row-1),Delta(Row),Delta(Row+1)) <> #0 THEN
P1:= PrevN(R,Row-1); P2:= PrevN(R,Row); P3:= PrevN(R,Row+1);
v2:= BITAND(P1,P3); v1:= BITOR(P1,P3);
P1:= BITSL(P1); P2:= BITSL(P2); P3:= BITSL(P3);
v3:= BITAND(v2,P1); v2:= BITOR(v2,BITAND(v1,P1)); v1:= BITOR(v1,P1);
v4:= BITAND(v3,P2); v3:= BITOR(v3,BITAND(v2,P2)); v2:= BITOR(v2,BITAND(v1,P2)); v1:= BITOR(v1,P2);
v4:= BITOR(v4,BITAND(v3,P3)); v3:= BITOR(v3,BITAND(v2,P3)); v2:= BITOR(v2,BITAND(v1,P3)); v1:= BITOR(v1,P3);
P1:= BITSR(P1,2); P2:= BITSR(P2,2); P3:= BITSR(P3,2);
v4:= BITOR(v4,BITAND(v3,P1)); v3:= BITOR(v3,BITAND(v2,P1)); v2:= BITOR(v2,BITAND(v1,P1)); v1:= BITOR(v1,P1);
v4:= BITOR(v4,BITAND(v3,P2)); v3:= BITOR(v3,BITAND(v2,P2)); v2:= BITOR(v2,BITAND(v1,P2)); v1:= BITOR(v1,P2);
v4:= BITOR(v4,BITAND(v3,P3)); v3:= BITOR(v3,BITAND(v2,P3)); v2:= BITOR(v2,BITAND(v1,P3)); // v1:= BITOR(v1,P3);
Lignes(R,Row):= BITAND(BITXOR(BITOR(v3,BITAND(v2,PrevN(R,Row))),v4),#1FFFFFFFFFFFFFFE);
END;
END;
END;
END;
LDisp()
BEGIN
LOCAL T1, Tx, C, R2, R;
FOR R2 FROM 1 TO 2 DO
Delta:= BITXOR(Lignes(R2),PrevD(R2));
FOR C FROM 0 TO 159 DO
T1:= Lignes(R2,C+2); Tx:= Delta(C+2); R:= (R2-1)*60;
WHILE Tx > #1 DO
IF BITAND(Tx,#2) THEN
IF BITAND(T1,#2) THEN PIXON_P(G1, C, R, #0);
ELSE PIXON_P(G1, C, R, #F800);
END;
END;
T1:= BITSR(T1,1); Tx:= BITSR(Tx,1); R:= R+1;
END;
END;
END;
PrevD:= Lignes;
BLIT_P(G0,G1);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod, Tmp;
Row:= py; Col:= px+2; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1);
CASE
IF INSTRING("0123456789", Cod) <> 0 THEN Cnt:= Cnt*10+EXPR(Cod); END;
IF Cod == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px+2; Cnt:= 0; END;
IF INSTRING("b.", Cod) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", Cod) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
Tmp:= BITOR(Lignes(IP(Row/60)+1, Col), BITSL(#2,(Row MOD 60) ));
Lignes(IP(Row/60)+1, Col):= Tmp;
END;
Cnt:= 0;
END;
END;
END;
LDisp();
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, LapN, LapD;
LOCAL Tm:=0, Gen:=0;
Gen:=0;
Lignes:= MAKELIST(MAKELIST(#0,B,1,322),A,1,4);
PrevN:= Lignes; PrevD:= Lignes;
DIMGROB(G1,160,120); RECT_P(G1);
RECT_P(0,0,159,119,#F8F8E0h);
IF St == 1 THEN
RLEMap (1, 1, "3o!"); // Blinker
RLEMap (13, 5, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (1, 6, "b3o$3o!"); // Toad
RLEMap (30, 5, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (1, 17, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Glider Canon
END;
IF St == 2 THEN
RLEMap (1, 1, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!"); // Pre-pulsar shuttle 29
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (80, 80, "bo$3bo$2o2b3o!"); // Acorn
END;
IF St == 6 THEN
RLEMap (80, 80, "o$obo$$bo$o$o$o!"); // Acorn vertical
END;
IF St == 7 THEN
RLEMap (1, 1, "26b2o3b2o$24b3obo2b2o$23bo4bo$23bo2b2ob4o$22b2obobobo2bo$23bobobobo$23bobob2o$24bo2$37b2o$28b2o7bo$28b2o5bobo$9bo25b2o$9b3o$12bo15b2o$11b2o15bobo$28bo2$2ob2o$2obo21b2o$3bo22bo$3b3o4b2o11b3o$b2o3bo3b2o11bo22bo$o2b4o21b2o14b5o$2obo15b2o8bo13bo5bo$bo2b3o12bobo7bobo12b3o2bo$bo5bo13bo8b2o15bob2o$2b5o14b2o21b4o2bo$4bo22bo11b2o3bo3b2o$25b3o11b2o4b3o$24bo22bo$24b2o21bob2o$46b2ob2o3$38b2o$38bo$39b3o$14b2o25bo$13bobo5b2o$13bo7b2o$12b2o2$26bo$22b2obobo$21bobobobo$18bo2bobobob2o$18b4ob2o2bo$22bo4bo$18b2o2bob3o$18b2o3b2o!"); // Snark Glider Reflector Loop
END;
IF St == 8 THEN
RLEMap (50, 50, "b2o$2o$bo!"); // R pentamino
END;
IF St == 9 THEN
RLEMap (80, 800, "o3b3o$3o2bo$bo!"); // Rabits
END;
REPEAT
LapN:= TICKS(); LNext(); LapN:= TICKS()-LapN;
LapD:= TICKS(); LDisp(); LapD:= TICKS()-LapD;
Tm:=Tm+LapN+LapD; Gen:= Gen+1; IF Gen == IterMax THEN RETURN Tm/IterMax; END;
// to display time between screen updates
TEXTOUT_P(STRING(Gen,2,0)+"-"+STRING(LapN,2,0)+"-"+STRING(LapD,2,0),0,225,0,#0,160,#F8F8E0h);
Kb:= GETKEY();
UNTIL Kb==4;
Lignes:= 0; PrevN:= 0; PrevD:= 0;
END;
Version 2.4 zoom x 1
The same in full screen size, I recommand sets 6 and 9.
Timing depend on set size.
Code:
#pragma mode( separator(.,;) integer(h64) )
// Conway's Game of Life B3/S23
// Author: Patrice Torchet
// 1.0 2014/01 First release.
// The 2 lower bits of each pixels is used to store neighb on right and left.
// 1.1 2014/02 Little optimization for speed
// Avoid recalc of empty lines.
// 1.2 2014/02 Better optimization for speed
// Avoid recalc of empty left and right
// 2.0 2014/02 Even faster, better scaling
// using bitmap storage and bitwise operations
// 2.1 2014/02 with PrevN
// show life span in green
// 2.2 A little optimization in LOcc
// Unrolled the loop and removed unneeded ops
// 2.3 board is now 120*160 and zoom x2 and
// Next Gen takes advantage of lists handling
// 2.4 Getting Fast and Furious on large sets
// the Game of Life play field is 120*160 cells
// each ligne is stored in 2 integers using 2 time 60 bits
// Slice = 60
// Mask = 2^61-2= #1FFFFFFFFFFFFFFEh
EXPORT Lignes;
PrevD, PrevN, Delta, Tmp;
IterMax:= -1;
//This routine is good with small sets but do degrade with big ones.
LNext() // Next Generation one by one elements
BEGIN
LOCAL R, Row;
LOCAL P1, P2, P3, v1, v2, v3, v4;
// Link between columns
FOR R FROM 1 TO 4 DO
Tmp:= Lignes(R);
IF R <> 1 THEN Tmp:= BITOR(Tmp,BITAND(BITSR(PrevN(R-1),60),#1)); END;
IF R <> 4 THEN Tmp:= BITOR(Tmp,BITSL(BITAND(Lignes(R+1),#2),60)); END;
Delta:= BITXOR(PrevN(R),Tmp);
PrevN(R):=Tmp;
FOR Row FROM 2 TO 321 DO
IF BITOR(Delta(Row-1),Delta(Row),Delta(Row+1)) <> #0 THEN
P1:= PrevN(R,Row-1); P2:= PrevN(R,Row); P3:= PrevN(R,Row+1);
v2:= BITAND(P1,P3); v1:= BITOR(P1,P3);
P1:= BITSL(P1); P2:= BITSL(P2); P3:= BITSL(P3);
v3:= BITAND(v2,P1); v2:= BITOR(v2,BITAND(v1,P1)); v1:= BITOR(v1,P1);
v4:= BITAND(v3,P2); v3:= BITOR(v3,BITAND(v2,P2)); v2:= BITOR(v2,BITAND(v1,P2)); v1:= BITOR(v1,P2);
v4:= BITOR(v4,BITAND(v3,P3)); v3:= BITOR(v3,BITAND(v2,P3)); v2:= BITOR(v2,BITAND(v1,P3)); v1:= BITOR(v1,P3);
P1:= BITSR(P1,2); P2:= BITSR(P2,2); P3:= BITSR(P3,2);
v4:= BITOR(v4,BITAND(v3,P1)); v3:= BITOR(v3,BITAND(v2,P1)); v2:= BITOR(v2,BITAND(v1,P1)); v1:= BITOR(v1,P1);
v4:= BITOR(v4,BITAND(v3,P2)); v3:= BITOR(v3,BITAND(v2,P2)); v2:= BITOR(v2,BITAND(v1,P2)); v1:= BITOR(v1,P2);
v4:= BITOR(v4,BITAND(v3,P3)); v3:= BITOR(v3,BITAND(v2,P3)); v2:= BITOR(v2,BITAND(v1,P3)); // v1:= BITOR(v1,P3);
Lignes(R,Row):= BITAND(BITXOR(BITOR(v3,BITAND(v2,PrevN(R,Row))),v4),#1FFFFFFFFFFFFFFE);
END;
END;
END;
END;
LDisp()
BEGIN
LOCAL T1, Tx, C, R2, R;
FOR R2 FROM 1 TO 4 DO
Delta:= BITXOR(Lignes(R2),PrevD(R2));
FOR C FROM 0 TO 319 DO
T1:= Lignes(R2,C+2); Tx:= Delta(C+2); R:= (R2-1)*60;
WHILE Tx > #1 DO
IF BITAND(Tx,#2) THEN
IF BITAND(T1,#2) THEN PIXON_P(G1, C, R, #0);
ELSE PIXON_P(G1, C, R, #F800);
END;
END;
T1:= BITSR(T1,1); Tx:= BITSR(Tx,1); R:= R+1;
END;
END;
END;
PrevD:= Lignes;
BLIT_P(G0,G1);
END;
RLEMap (px, py, RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Cod, Tmp;
Row:= py; Col:= px+2; Cnt:= 0;
FOR Ptr FROM 1 TO DIM(RLE) DO
Cod:= MID(RLE, Ptr, 1);
CASE
IF INSTRING("0123456789", Cod) <> 0 THEN Cnt:= Cnt*10+EXPR(Cod); END;
IF Cod == "$" THEN Row:= Row+MAX(1, Cnt); Col:= px+2; Cnt:= 0; END;
IF INSTRING("b.", Cod) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
IF INSTRING("oA", Cod) <> 0 THEN
FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO
Tmp:= BITOR(Lignes(IP(Row/60)+1, Col), BITSL(#2,(Row MOD 60) ));
Lignes(IP(Row/60)+1, Col):= Tmp;
END;
Cnt:= 0;
END;
END;
END;
LDisp();
END;
EXPORT Life(St)
BEGIN
LOCAL Kb, LapN, LapD;
LOCAL Tm:=0, Gen:=0;
Gen:=0;
Lignes:= MAKELIST(MAKELIST(#0,B,1,322),A,1,4);
PrevN:= Lignes; PrevD:= Lignes;
DIMGROB(G1,320,240); RECT_P(G1);
RECT_P(0,0,319,239,#F8F8E0h);
IF St == 1 THEN
RLEMap (1, 1, "3o!"); // Blinker
RLEMap (13, 5, "bo$3o$obo$3o$bo!"); // Pulsar
LNext();
RLEMap (1, 6, "b3o$3o!"); // Toad
RLEMap (30, 5, "bo$3o$obo$3o$bo!"); // Pulsar
RLEMap (1, 17, "24bo11b$22bobo11b$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o14b$2o8bo3bob2o4bobo11b$10bo5bo7bo11b$11bo3bo20b$12b2o!"); // Glider Canon
END;
IF St == 2 THEN
RLEMap (1, 1, "10b2o3b2o10b$9bo2bobo2bo9b$5b2o3b2o3b2o3b2o5b$5bo15bo5b$2b2obo15bob2o2b$o2bob2o13b2obo2bo$2obo19bob2o$3bo19bo3b$3b2o17b2o3b$9b3o3b3o9b$9bobo3bobo9b$9b3o3b3o9b4$9bo7bo9b$8bobo5bobo8b$9bo7bo!"); // Pre-pulsar shuttle 29
END;
IF St == 3 THEN
RLEMap (1, 1, "13bo20b$13b3o7b2o9b$16bo6bo10b$9bo5b2o4bobo10b$9b3o9b2o11b$12bo4b3o6b2o6b$5bo5b2o4b3o6bo7b$5b3o16bobo7b$8bo15b2o8b$bo5b2o4b3o13b2o3b$b3o9b3o4b3o6bo4b$4bo4b3o8b3o4bobo4b$3b2o4b3o4b3o8b2o5b$16b3o4b3o6b2o$23b3o6bob$5b3o22bobob$5b3o4b3o15b2o2b$2b2o8b3o4b3o12b$bobo4b3o8b3o4b3o5b$bo6b3o4b3o8b3o5b$2o13b3o4b3o9b$5b2o15b3o4b2o3b$4bobo22bo4b$4bo6b3o16b3ob$3b2o6b3o4b3o4b2o5bob$8b2o8b3o4bo8b$7bobo4b3o9b3o5b$7bo6b3o4b2o5bo5b$6b2o13bo12b$11b2o9b3o9b$10bobo4b2o5bo9b$10bo6bo16b$9b2o7b3o13b$20bo!"); // Extended dinner table
END;
IF St == 4 THEN
RLEMap (0, 0, "11bo7bo39bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo9b2o17b2o9bo7bo11b$29bo19bo29b$27bobo19bobo27b$27b2o21b2o27b$6bo17bo29bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo11bobobobo11bo17bo6b$2b2o31bo2bobo2bo31b2o2b$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$2o34bobobobo34b2o$37bo3bo37b$7b2o13b2o31b2o13b2o7b$7b2o13b2o31b2o13b2o7b$37bo3bo37b$2o34bobobobo34b2o$bo8bo3bobo3bo14bo2bobo2bo14bo3bobo3bo8bob$bobo7b3o3b3o15bo7bo15b3o3b3o7bobob$2b2o31bo2bobo2bo31b2o2b$6bo17bo11bobobobo11bo17bo6b$6bo17bo12bo3bo12bo17bo6b$6bo17bo29bo17bo6b$27b2o21b2o27b$27bobo19bobo27b$29bo19bo29b$11bo7bo9b2o17b2o9bo7bo11b$10bobo5bobo37bobo5bobo10b$11bo7bo39bo7bo!"); // Pre-pulsar shuttle 47
END;
IF St == 5 THEN
RLEMap (160, 150, "bo$3bo$2o2b3o!"); // Acorn
END;
IF St == 6 THEN
RLEMap (160, 150, "o$obo$$bo$o$o$o!"); // Acorn vertical
END;
IF St == 7 THEN
RLEMap (1, 1, "26b2o3b2o$24b3obo2b2o$23bo4bo$23bo2b2ob4o$22b2obobobo2bo$23bobobobo$23bobob2o$24bo2$37b2o$28b2o7bo$28b2o5bobo$9bo25b2o$9b3o$12bo15b2o$11b2o15bobo$28bo2$2ob2o$2obo21b2o$3bo22bo$3b3o4b2o11b3o$b2o3bo3b2o11bo22bo$o2b4o21b2o14b5o$2obo15b2o8bo13bo5bo$bo2b3o12bobo7bobo12b3o2bo$bo5bo13bo8b2o15bob2o$2b5o14b2o21b4o2bo$4bo22bo11b2o3bo3b2o$25b3o11b2o4b3o$24bo22bo$24b2o21bob2o$46b2ob2o3$38b2o$38bo$39b3o$14b2o25bo$13bobo5b2o$13bo7b2o$12b2o2$26bo$22b2obobo$21bobobobo$18bo2bobobob2o$18b4ob2o2bo$22bo4bo$18b2o2bob3o$18b2o3b2o!"); // Snark Glider Reflector Loop
END;
IF St == 8 THEN
RLEMap (50, 50, "b2o$2o$bo!"); // R pentamino
END;
IF St == 9 THEN
RLEMap (160, 150, "o3b3o$3o2bo$bo!"); // Rabits
END;
REPEAT
LapN:= TICKS(); LNext(); LapN:= TICKS()-LapN;
LapD:= TICKS(); LDisp(); LapD:= TICKS()-LapD;
Tm:=Tm+LapN+LapD; Gen:= Gen+1; IF Gen == IterMax THEN RETURN Tm/IterMax; END;
// to display time between screen updates
TEXTOUT_P(STRING(Gen,2,0)+"-"+STRING(LapN,2,0)+"-"+STRING(LapD,2,0),0,225,0,#0,160,#F8F8E0h);
Kb:= GETKEY();
UNTIL Kb==4;
Lignes:= 0; PrevN:= 0; PrevD:= 0;
END;
Patrice
“Everything should be made as simple as possible, but no simpler.” Albert Einstein
|