IchigoJamでライフゲーム

# 何をするのか

IchigoJamでライフゲームの世代交代の計算をする。

[ライフゲーム - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0)

正方形のグリッドにおいて、各マスは「生」または「死」の状態をとる。
世代交代とは、

* 「生」のマスは、8近傍の「生」のマスの数が2または3なら「生」のまま、そうでないなら「死」になる
* 「死」のマスは、8近傍の「生」のマスの数が3なら「生」になり、そうでないなら「死」のまま

という計算である。
今回は白で「生」を、黒で「死」を表現した。

# BASICでやってみた

今回は、「女王蜂」の両側に「ブロック」を配置し、30世代周期でもとに戻るパターンを用意した。
1個だと寂しいので、左右反転して2個並べてみた。

[ブロック (ライフゲーム) - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF_(%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0))

↓「女王蜂」はここを参照した。
[シャトル (ライフゲーム) - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%A3%E3%83%88%E3%83%AB_(%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0))

まず、配列に初期パターンを格納する。
その後、「配列のデータをVRAMに反映する → VRAMのデータをもとに配列のデータを更新する」を繰り返す。

## ソースコード

```
10 'ﾗｲﾌｹﾞｰﾑ
20 LET[0],0,0,0,0,0,0,0,0,0,#4000,0,#5000,0,#2800,#600,#2460
30 LET[16],#600,#2860,0,#5000,0,#4000,0,0,0,0,2,0,#A,0,#614,#60
40 LET[32],#624,#60,#14,0,#A,0,2,0,0,0,0,0,0,0,0,0
50 G=0
60 FOR I=0 TO #2FF
70 POKE#900+I,([I/16]>>(15-I%16))&1
80 NEXT
90 LOCATE0,0:?G
100 POKE#909,#5B:POKE#91F,#5D
110 FOR I=0 TO 47:[I]=0:NEXT
120 FOR Y=2 TO 22:FOR X=1 TO 30
130 P=#900+Y*32+X:C=PEEK(P-33)+PEEK(P-32)+PEEK(P-31)+PEEK(P-1)+PEEK(P+1)+PEEK(P+31)+PEEK(P+32)+PEEK(P+33)
140 IF C=3 OR (PEEK(P) AND C=2) K=Y*2+X/16:[K]=1<<(15-X%16)|[K]
150 POKE#908+Y,#23:NEXT:NEXT
160 WAIT 6
170 G=G+1:IF G>9999 G=0
180 GOTO 60
```

## 実行結果

YouTube動画 (14分16秒)
[![実行結果(YouTube)](http://img.youtube.com/vi/kKi5BrvagDE/0.jpg)](http://www.youtube.com/watch?v=kKi5BrvagDE)

30世代の計算を行うのに、約13分32秒(812秒)かかった。

# マシン語でやってみた

BASIC版は頑張っている感はあるものの遅すぎて実用的でないため、
「配列のデータをVRAMに反映する」「VRAMのデータをもとに配列のデータを更新する」それぞれをマシン語に移植してみた。

## 埋め込んだマシン語のソースコード

```
@START
	R3 = PC + 64 ' 配列の先頭アドレス (コードは#700から)
	R2 = R3 + 1
	R2 += 255 ' VRAMの先頭アドレス
	R0 & R0
	IF !0 GOTO @UPDATE
	' 描画処理を行う
	R12 = R4
	R1 = 3
	R1 = R1 << 8 ' カウンタ
	R1 -= 1
@DRAW_LOOP
	R0 = [R3 + 0]W
	R4 = 15
	R4 &= R1
	IF !0 GOTO @DRAW_LOOP_NOARRAYINC
	R3 += 2
@DRAW_LOOP_NOARRAYINC
	R0 >>= R4
	R4 = 1
	R0 &= R4
	[R2 + 0] = R0
	R2 += 1
	R1 -= 1
	IF CS GOTO @DRAW_LOOP
	R4 = R12
	RET
@UPDATE
	' 更新処理を行う
	PUSH {R4, R5, R6, R7}
	R0 = 92
	R1 = 0
@UPDATE_INIT_LOOP
	[R3 + R0]L = R1
	R0 -= 4
	IF CS GOTO @UPDATE_INIT_LOOP
	R6 = R2
	R6 -= 33
	R4 = 2
@UPDATE_OUTER_LOOP
	R5 = 1
@UPDATE_INNER_LOOP
	R0 = R4 << 5
	R0 = R0 + R5
	R0 = R0 + R6
	R1 = [R0 + 0]
	R7 = [R0 + 1]
	R1 = R1 + R7
	R7 = [R0 + 2]
	R1 = R1 + R7
	R0 += 64
	R7 = [R0 + 0]
	R1 = R1 + R7
	R7 = [R0 + 1]
	R1 = R1 + R7
	R7 = [R0 + 2]
	R1 = R1 + R7
	R0 -= 32
	R7 = [R0 + 0]
	R1 = R1 + R7
	R7 = [R0 + 2]
	R1 = R1 + R7
	R1 - 3
	IF EQ GOTO @UPDATE_LIVE
	R1 - 2
	IF NE GOTO @UPDATE_CONTINUE
	R7 = [R0 + 1]
	R7 & R7
	IF 0 GOTO @UPDATE_CONTINUE
@UPDATE_LIVE
	R0 = R4 << 1
	R1 = R5 >> 4
	R0 = R0 + R1
	R0 = R0 << 1
	R0 = R0 + R3
	R1 = 15
	R1 &= R5
	R7 = 15
	R7 = R7 - R1
	R1 = 1
	R1 <<= R7
	R7 = [R0 + 0]W
	R7 |= R1
	[R0 + 0]W = R7
@UPDATE_CONTINUE
	R5 += 1
	R5 - 30
	IF LS GOTO @UPDATE_INNER_LOOP
	R4 += 1
	R4 - 22
	IF LS GOTO @UPDATE_OUTER_LOOP
	POP {R4, R5, R6, R7}
	RET
```

## ソースコード

```
10 'ﾗｲﾌｹﾞｰﾑ (ﾏｼﾝｺﾞ ver.)
20 LET[0],0,0,0,0,0,0,0,0,0,#4000,0,#5000,0,#2800,#600,#2460
30 LET[16],#600,#2860,0,#5000,0,#4000,0,0,0,0,2,0,#A,0,#614,#60
40 LET[32],#624,#60,#14,0,#A,0,2,0,0,0,0,0,0,0,0,0
50 POKE#700,63,163,90,28,255,50,0,66,17,209,164,70,3,33,9,2,1,57,24,136,15,36,12,64,0,209,2,51,224,64,1,36,32,64,16,112,1,50,1,57,243,210,100,70,112,71,240,180,92,32,0,33,25,80,4,56,252,210,22,70
60 POKE#73C,33,62,2,36,1,37,96,1,64,25,128,25,1,120,71,120,201,25,135,120,201,25,64,48,7,120,201,25,71,120,201,25,135,120,201,25,32,56,7,120,201,25,135,120,201,25,3,41,4,208,2,41,16,209,71,120,63,66
70 POKE#776,13,208,96,0,41,9,64,24,64,0,192,24,15,33,41,64,15,39,127,26,1,33,185,64,7,136,15,67,7,128,1,53,30,45,211,217,1,52,22,44,207,217,240,188,112,71
80 G=0
90 I=USR(#700,0)
100 LOCATE0,0:?G
110 I=USR(#700,1)
120 WAIT 6
130 G=G+1:IF G>9999 G=0
140 GOTO 90
```

## 実行結果

YouTube動画 (0分42秒)
[![実行結果(YouTube)](http://img.youtube.com/vi/ft1Ts57pn1E/0.jpg)](http://www.youtube.com/watch?v=ft1Ts57pn1E)

30世代の計算をするのに、約3秒しかかからなかった。
BASIC版の約270倍速いということである…といいたいところだが、ここには｀WAIT 6`の時間も含まれる。
これは0.1秒待つということなので、30世代で3秒待つ…すなわち、計算時間はほぼゼロになってしまった。
マシン語つよい。 (BASICがよわい？)

# IchigoJamとは

2,000円前後で購入することができ、BASICによるプログラミングが可能なパソコン。
[こどもパソコン IchigoJam - はじめてのプログラミングパソコン(1500円)](https://ichigojam.net/)

また、プログラムをWebブラウザ上で実行できるサービスもある。
[IchigoJam web by WebAssembly](https://fukuno.jig.jp/app/IchigoJam/)
※マシン語を用いるプログラムは、今のところこのサービスでは動かない

※「IchigoJam」はjig.jpの登録商標