サクラエディタでライフゲーム

# 環境
サクラエディタ Ver.2.2.0.1
Windows 10


# ライフゲームマクロ

サクラエディタの可能性を試すために
なんとなく動かしたくなり昔作ったコードを移植。

業務でライフゲームを動かす必要に迫られた場合にどうぞ。
※一応言っておくと私は業務時間中にライフゲームを動かしたりはしていない。

```javascript

function simpleMethod(  board, width, height ){
	var next_isLiving = new Array( width * height );
	for (var x = 0; x < width; x++) {
		for (var y = 0; y < height; y++) {
			var isLiving_around = 0;
			var ym  = y - 1;
			var yp  = y + 1;
			var xm  = x - 1;
			var xp  = x + 1;

			if (x > 0 &&      y > 0 &&      board[ym * width + xm] === 1) isLiving_around++;
			if (x > 0 &&                    board[y  * width + xm] === 1) isLiving_around++;
			if (x > 0 &&      y < height && board[yp * width + xm] === 1) isLiving_around++;
			if (              y < height && board[yp * width + x ] === 1) isLiving_around++;
			if (x < width &&  y < height && board[yp * width + xp] === 1) isLiving_around++;
			if (x < width &&                board[y  * width + xp] === 1) isLiving_around++;
			if (x < width &&  y > 0 &&      board[ym * width + xp] === 1) isLiving_around++;
			if (              y > 0 &&      board[ym * width + x ] === 1) isLiving_around++;

			if ( 1 === board[y * width + x] ) { // 生きセル
				if (isLiving_around <= 1) {
					next_isLiving[y * width + x] = 0; // 孤独死
				}
				else if (isLiving_around >= 4) {
					next_isLiving[y * width + x] = 0; // 過密死
				}
				else { //次のフレームでも生きてる場合
					next_isLiving[y * width + x] = 1; // 生存維持
				}
			}
			else {
				if (isLiving_around === 3) next_isLiving[y * width + x] = 1; //繁殖
				else {
					next_isLiving[y * width + x] = 0;
				}
			}
		}
	}
	return next_isLiving;
}

function nextStep(board, width, height){
  var nextLiving = simpleMethod( board, width, height );
  
  return nextLiving;
}

function boardToString(board, width, height){
  var outText = "";
  for(var i = 0; i < height; ++i){
    for(var j = 0; j < width; ++j){
      if( 1 === nextBoard[ i * width + j ] ){
        outText += "*";
      }
      else{
        outText += " ";
      }
    }
    outText += "\n";
  }
  return outText;
}

// ここからエディタマクロ

var nStep = 10;
var text = Editor.GetSelectedString(0);
lines = text.split("\n");

var arr = new Array(30 * 30);
for( var i = 0; i < 30 * 30; ++i){
  arr[i] = 0;
}

for( var i = 0; i < lines.length && i < 30; ++i ) {
  for( var j = 0; j < lines[i].length && j < 30; ++j ) {
    var num = parseInt(lines[i].charAt(j));
    if( " " === lines[i].charAt(j) ){
      arr[ i * 30 + j ] = 0;
    }
    else if( "*" === lines[i].charAt(j) ){
      arr[ i * 30 + j ] = 1;
    }
  }
}

Editor.Sleep(100);

var nextBoard = nextStep( arr, 30, 30 );
var outText = boardToString( nextBoard, 30, 30 );
Editor.InsText( outText );

Editor.Sleep(100);

for(var step = 0; step < nStep; ++step){
  Editor.SelectLine(0);
  for(var i = 0; i < 30; ++i){
    Editor.Up_Sel();
  }

  nextBoard = nextStep( nextBoard, 30, 30 );
  outText = boardToString( nextBoard, 30, 30 );
  
  Editor.InsText( outText );
  Editor.Sleep(100);
}

```


# 実用

入力は30x30に固定している(それ以下でも入力できるが、描画開始すると30x30になる)
"\*"を入れた個所が生存マスになる。

以下の形式で入力を行い、実行前に全体を文字列選択しておく。

**※Qiitaの仕様なのか空白のみの行が空行になっているが、動かない場合直してほしい**

```:入力例
                           
   *               *       
    *              *       
  ***              *       
                           
                           
                           
                           
                           
                           
                           
                           
    ** ******              
    ** ******              
    **                     
    **     **              
    **     **              
    **     **              
           **        *     
    ****** **        *     
    ****** **        *     
                     *     
                     *     
                           
                           
                           
```


![image.png](https://qiita-image-store.s3.amazonaws.com/0/28988/7291f780-4fb2-b111-dfab-ab69f707cdae.png)

マクロ実行。(「共通設定」→「マクロ」から登録でも良い)

**変な入力でマクロが暴走しても責任持てないので実行は自己責任で**

![image.png](https://qiita-image-store.s3.amazonaws.com/0/28988/68fd6623-6f22-6c27-bc09-05c8bf502332.png)


![test.gif](https://qiita-image-store.s3.amazonaws.com/0/28988/a5b7b927-f4bf-f0ab-1f41-92d72eb850b1.gif)


マクロ動作なので若干ぎこちない気がするものの、動いた。

## 気になる点

マクロの実行時間が一定時間(3秒程度?)を超えるとサクラエディタ自体に制御が戻らないせいか、画面の描画が死ぬ。

なので、描画周期としているEditor.Sleep()の待ち時間を長めにすると、
最初の数ステップ描画後にウインドウが固まってしまい、後の動きが見れない。
逆に待ち時間を短めにすると勢いよく動いてすぐ終わってしまう。