Simulator 0.1

中国ルールでプレイアウトを繰り返し、勝敗の統計を取る予定ですが、今回はプレイアウトのルールのみ実装し、手動での対局となっています。 勝敗の記録は取れません。プレイアウトのルールにより自石の1目の眼に打てなくなっています。

実行結果

Simulator 0.1 には HTML5 Canvas が必要です。 Simulator 0.1 には HTML5 Canvas が必要です。 Simulator 0.1 には HTML5 Canvas が必要です。
0 0
       活路 Liberty 0        活路 Liberty 0        白石 White 0        黒石 Black 0

ソース

後半のソースはリンクを張ってあります。ソースは UTF-8 でエンコードしてあります。

simulator01.html

スタイルシートの部分です。goban06.html から変更はありません。
<style>
hr.colored {
	border-color: goldenrod
}
#table {
	margin: 0;
	color: white;
	background-image: url(img/table800.jpg);
	z-index: 1;
	position: relative;
	left: 0px;
	top: 0px
}
#shadow {
	margin: 0;
	z-index: 2;
	position: absolute;
	left: 0px;
	top: 0px
}
#stones {
	margin: 0;
	z-index: 3;
	position: absolute;
	left: 0px;
	top: 0px
}
#control {
	color: white;
	height: 48px;
	width: 630px;
	background-color: #26130D;
	padding: 5px;
	border-spacing: 0;
	margin: 0;
	position: absolute;
	left: 0px;
	top: 480px
}
.list {
	border: 1px solid lightgray;
	max-height: 300px
}
</style>
実行結果を表示する部分です。goban06.html から石の数を表示するように変更しました。
<h2>実行結果</h2>
<div style="height: 540px; width: 640; position: relative">
<canvas width="640" height="480" id="table">Simulator 0.1 には HTML5 Canvas が必要です。</canvas>
<canvas width="640" height="480" id="shadow">Simulator 0.1 には HTML5 Canvas が必要です。</canvas>
<canvas width="640" height="480" id="stones">Simulator 0.1 には HTML5 Canvas が必要です。</canvas>
<div id="control">
<img style="vertical-align: bottom; padding-left: 10px" src="img/white22.png">
<input id="white" type="button" value="パス Pass" onclick="pass()">
<span id="pw">0</span>
<img style="vertical-align: bottom; padding-left: 10px" src="img/black22.png">
<input id="black" type="button" value="パス Pass" onclick="pass()">
<span id="pb">0</span>
<input style="margin-left: 40px" type="button" value="はじめから Restart" onclick="restart()"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 活路 Liberty <span id="iw">0</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 活路 Liberty <span id="ib">0</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 白石 White <span id="w">0</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 黒石 Black <span id="b">0</span>
</div><!-- end of control -->
</div><!-- end of 実行結果 -->

simulator01.js

石の数の表示処理を追加しました。
/*
 * Copyright (C) 2012-2013 たかはしのんき. All rights reserved.
 *
 * History:
 *  0.1 2013-04-07 碁盤プログラム goban06.js を元に新規作成。
 */

/**
 * Simulator - 囲碁対局シミュレータ
 * @version 0.1
 * @author たかはしのんき
 * 
 */

// 共通に使う定数と変数
var BLACK = 1;
var WHITE = 2;
var PX_BOWL = 134;	// 碁笥の直径 [ピクセル]
var Z2_BOWL = 20;	// 碁笥の高さ / 2 [ピクセル]
var PX_LID = 110;	// 碁笥の蓋の直径 [ピクセル]
var Z2_LID = 8;		// 碁笥の蓋の高さ / 2 [ピクセル]
var PX_STONE = 22;	// 碁石の直径 [ピクセル]
var Z2_STONE = 2;	// 碁石の高さ / 2 [ピクセル]
var PX_STAR = 5;	// 星の直径 [ピクセル]
var PX_CHAR = 24;	// 文字の高さ [ピクセル]
var Z2_BOARD = 6;	// 碁盤の高さ / 2 [ピクセル]

// キャッシュにイメージを読み込んでおく
var imgbb = new Image(PX_BOWL, PX_BOWL);	// 黒の碁笥 (black bowl)
imgbb.src = "img/blackbowl134.png";
var imgwb = new Image(PX_BOWL, PX_BOWL);	// 白の碁笥 (white bowl)
imgwb.src = "img/whitebowl134.png";
var imgl = new Image(PX_LID, PX_LID);		// 碁笥の蓋 (lid)
imgl.src = "img/lid110.png";
var imgb = new Image(PX_STONE, PX_STONE);	// 黒石 (white stone)
imgb.src = "img/black22.png";
var imgw = new Image(PX_STONE, PX_STONE);	// 白石 (black stone)
imgw.src = "img/white22.png";
var imgs = new Image(PX_STAR, PX_STAR);		// 星 (star)
imgs.src = "img/star5.png";

// キャッシュに効果音を読み込んでおく
var ext = audioExt();
var auClick = new Audio("se/button6."  + ext);
var auSwitch = new Audio("se/se_sad05." + ext);
var auError = new Audio("se/se_sad08." + ext);

var ro = 9;							// 路数
var context3;						// 碁石レイヤーのキャンバスのコンテキスト
var context2;						// 影レイヤーのキャンバスのコンテキスト
var passButton = new Array(2);		// [パス]ボタン
var brd;							// 碁盤オブジェクト
var offsetBLid = new Object();		// 黒の碁笥の蓋のオフセット
var offsetWLid = new Object();		// 白の碁笥の蓋のオフセット

/**
 * ロード時に碁盤イメージを描画します。
 */
window.onload = function() {
	// 黒石の <input id="black"> 取得
	passButton[BLACK] = document.getElementById('black');
	// 白石の <input id="white"> 取得
	passButton[WHITE] = document.getElementById('white');

	// キャンバスとコンテキスト取得
	var canvas = document.querySelector('#table');
	var context = canvas.getContext('2d');
	var canvas3 = document.querySelector('#stones');
	context3 = canvas3.getContext('2d');
	var canvas2 = document.querySelector('#shadow');
	context2 = canvas2.getContext('2d');
	// 座標 (270, 50) にタイトルを表示
	context.fillStyle = "white";
	context.font = "bold 24px Arial";
	var title = "Simulator 0.1";
	var x = context.canvas.width / 2 - 
			PX_CHAR / 1.8 * title.length / 2;
	var y = PX_CHAR * 2;
	context.fillText(title, x, y);
	// 机の中央に 碁盤を表示
	brd = new Board(ro, context);
	// 碁盤の左に白の碁笥の蓋のイメージを表示
	offsetWLid.x = Math.floor((brd.boardOffset.x - PX_LID) / 2);
	offsetWLid.y = brd.boardOffset.y +
		Math.floor((brd.boardSize.height - PX_LID) / 2);
	drawObject(offsetWLid.x, offsetWLid.y, Z2_LID, imgl, context, context);
	// 左上に白の碁笥のイメージを表示
	var xb = offsetWLid.x - Math.floor((PX_BOWL - PX_LID) / 2);
	var yb = offsetWLid.y - PX_BOWL - Z2_BOWL;
	drawObject(xb, yb, Z2_BOWL, imgwb, context, context);
	// 碁盤の右に黒の碁笥の蓋のイメージを表示
	offsetBLid.x = offsetWLid.x + brd.boardOffset.x + brd.boardSize.width;
	offsetBLid.y = offsetWLid.y;
	drawObject(offsetBLid.x, offsetBLid.y, Z2_LID, imgl, context, context);
	// 右下に黒の碁笥のイメージを表示
	xb = offsetBLid.x - Math.floor((PX_BOWL - PX_LID) / 2);
	yb = offsetBLid.y + PX_LID + Z2_BOWL;
	drawObject(xb, yb, Z2_BOWL, imgbb, context, context);
	// 碁盤を表示
	brd.drawBoard(Z2_BOARD, context);
	// 黒番から
	passButton[WHITE].disabled = true;
	// クリックイベント登録
	canvas3.addEventListener("click", onClick, false);
};

/**
 * アゲハマの表示
 * @param stone 石の色
 * @param prisoner アゲハマの数
 * @since 0.1
 */
function showPrisoner(stone, prisoner) {
	if (stone == BLACK) {
		var p = document.getElementById('pb');
	} else {
		var p = document.getElementById('pw');
	}
	p.firstChild.nodeValue = prisoner;
}

/**
 * 活路の表示
 * @param stone 石の色
 * @param liberty 活路の数
 * @since 0.1
 */
function showLiberty(stone, liberty) {
	if (stone == BLACK) {
		var p = document.getElementById('ib');
	} else {
		var p = document.getElementById('iw');
	}
	p.firstChild.nodeValue = liberty;
}

/**
 * 石の数の表示
 * @param stone 石の色
 * @param num 石の数
 * @since 0.1
 */
function showNumStones(stone, num) {
	if (stone == BLACK) {
		var p = document.getElementById('b');
	} else {
		var p = document.getElementById('w');
	}
	p.firstChild.nodeValue = num;
}

/**
 * マウスイベントハンドラー
 * 碁石を置きます。
 * @since 0.1
 */
function onClick() {
	var event = arguments[0];
	var mx = event.pageX - this.parentNode.offsetLeft;
	var my = event.pageY - this.parentNode.offsetTop; 
	var mv = brd.offsetToMove(mx, my);
	if (mv.onBoard) {
		brd.move(mv.col, mv.row, context3, context2);
	} else {
		if (brd.p.turn == BLACK) 
			drawObject(mx - (PX_STONE / 2), my - (PX_STONE / 2), Z2_STONE, imgb, context2, context2);
		else
			drawObject(mx - (PX_STONE / 2), my - (PX_STONE / 2), Z2_STONE, imgw, context2, context2);
		auError.play();
	}
}


/**
 * [パス]ボタンの処理
 * @since 0.1
 */
function pass() {
	// ボタンの音を鳴らす。
	auSwitch.play();
	var col = PASS(ro);
	var row = PASS(ro);
	brd.move(col, row, context3, context2);
}

/**
 * [はじめから]ボタンの処理
 * @since 0.1
 */
function restart() {
	// ボタンの音を鳴らす。
	auSwitch.play();
	// 碁石と影のレイヤーをクリア
	context3.clearRect(0, 0, context3.canvas.width, context3.canvas.height);
	context2.clearRect(0, 0, context2.canvas.width, context2.canvas.height);
	// アゲハマのクリア
	showPrisoner(BLACK, 0);
	showPrisoner(WHITE, 0);
	// 活路のクリア
	showLiberty(BLACK, 0);
	showLiberty(WHITE, 0);
	// 石の数のクリア
	showNumStones(BLACK, 0);
	showNumStones(WHITE, 0);
	// 黒番から
	brd.clear();
	passButton[BLACK].disabled = false;
	passButton[WHITE].disabled = true;
}

/**
 * ブラウザで有効なAudioの拡張子を獲得
 * @since 0.1
 */
function audioExt() {
    var ext = "";
    var audio = new Audio();
 	if (audio.canPlayType("audio/ogg") == 'maybe')
 		ext="ogg";
    else if (audio.canPlayType("audio/mp3") == 'maybe')
    	ext="mp3";
    else if (audio.canPlayType("audio/wav") == 'maybe')
    	ext="wav";
    return ext;
}

/**
 * 円形オブジェクトを描画します。
 * @param x 左端座標
 * @param y 上端座標
 * @param s 影の長さ(高さ/2)
 * @param img オブジェクトのイメージ
 * @param context3 描画先のコンテキストを指定します。
 * @param context2 影用のコンテキストを指定します。
 * @since 0.1
 */
function drawObject(x, y, s, img, context3, context2) {
	var r = img.width / 2;
	context2.beginPath();
	context2.arc(x + r + s, y + r + s, r, 0, 2 * Math.PI);
	context2.fillStyle = "black";
	context2.globalAlpha = 0.5;
	context2.fill();
	context3.globalAlpha = 1.0;
	context3.drawImage(img, x, y);
}

board04.js

石の数の表示処理を追加しました。
Board.prototype = {
	
	/**
	 * 着手します。
	 * @param col 石の桁位置を指定します。
	 * @param row 石の行位置を指定します。
	 * @param context3 石を描画するコンテキスト
	 * @param context2 影を描画するコンテキスト
	 * @since 0.2
	 */
	move : function(col, row, context3, context2) {
		passButton[this.p.turn].disabled = true;
		var turn = this.p.turn;
		var moved = this.p.move(col, row);	// 着手禁止点は false
		var mv = new Move(col, row);
		if (!mv.isPass(this.ro)) {
//			setWatch();
			if (moved) {
				this.prisoner[P_BLACK] = this.p.prisoner[P_BLACK];
				this.prisoner[P_WHITE] = this.p.prisoner[P_WHITE];
//				rec.move(col, row);
				this.drawStone(col, row, turn, context3, context2);
				auClick.play();
				if (this.p.d.abs()) {
					this.removeStones(this.p.d, this.p.turn, context3, context2);
					showPrisoner(turn, this.prisoner[turn - 1]);
				}
				showLiberty(BLACK, this.p.liberty[P_BLACK]);
				showLiberty(WHITE, this.p.liberty[P_WHITE]);
				showNumStones(BLACK, this.p.w.inv().abs());
				showNumStones(WHITE, this.p.b.inv().abs());
			} else
				auError.play();
		}
		passButton[this.p.turn].disabled = false;
		return moved;
	},

pos05.js

プレイアウトのための着手禁止の処理、石の数の表示処理を追加しました。
/*
 * Copyright (c) 2012-2013 たかはしのんき. All rights reserved.
 *
 * History:
 *  0.5 2013-04-08 プレイアウトのために自分の1目の眼への着手を禁止。
 *  0.4 2013-03-29 式の整理、活路の表示。
 *  0.3 2013-03-18 コウの処理を追加。
 *  0.2 2012-05-17 SixVectors オブジェクトを外せるよう変更。メソッド clear の追加。
 *  0.1 2012-05-15 新規作成。Java 版より移植。
 *
 * Reference:
 *  [1]佐藤真史,穴田浩一,堤正義:囲碁の数理モデル化とその応用,
 *     第16回ゲームプログラミングワークショップ2011,Vol.2011 No.6,
 *     pp.100-103(2011)
 */

/**
 * 囲碁の局面 (position) を B-W graph model で表したオブジェクトです。
 * このオブジェクトで扱う メソッドの引数に盤面の桁位置 col と行位置 row を 指定する
 * 場合は、囲碁に合わせ、col, row の順で指定します。
 * 行列の行 i、 列 j を指定する場合の i, j の順と逆になるので注意してください。
 * @author たかはしのんき
 * @version 0.5
 */
var COL = 0;		// 横座標
var ROW = 1;		// 縦座標
var SPACE = 0;		// 空点
var BLACK = 1;		// 黒石
var WHITE = 2;		// 白石
var P_BLACK = 0;	// 黒石(アゲハマと活路用)
var P_WHITE = 1;	// 白石(アゲハマと活路用)
var OPPOSITE = 3;	// 敵石計算用定数
var playout = true;	// true ならプレイアウト用に着手可能の式を変更

/**
 * n 路盤の局面を表すオブジェクトです。
 * @param n 路数を指定します。
 * @since 0.1
 */
Pos = function(n) {
//	this.h = new BVector(order);					// アタリ
//	this.A = new BMatrix(order, order);				// 追加される連接関係
//	this.D = new BMatrix(order, order)				// リセットされる連接関係
//	this.a = new BVector(order);					// 追加される連
//	this.d = new BVector(order);					// リセットされる連

	this.ro = n;									// 路数
	this.order = n * n;								// ベクトルの次数
	this.F0 = new BMatrix(this.order, this.order);	// 隣接関係
	this.initF0();
	this.prisoner = new Array(2);					// アゲハマ
	this.liberty = new Array(2);					// 活路の数
	try {
		this.v6 = new SixVectors(this);				// 6ベクトル
	} catch(e) {
		this.v6 = null;
	}
	this.clear();
};

Pos.prototype = {
	/**
	 * 隣接関係 F0 を初期化します。
	 * @since 0.1
	 */
	initF0 : function() {
		var adj = new Array(4);
		adj = [				// 隣接する(adjacent)相対座標
				[0, -1],
				[-1, 0], [0, 0], [1, 0],
				[0, 1]
		];
		for (var row = 1; row <= this.ro; row++)
			for (var col = 1; col <= this.ro; col++)
				for (var i = 0; i < adj.length; i++) {
					var ar = row + adj[i][ROW];
					var ac = col + adj[i][COL];
					if (ar > 0 && ar <= this.ro && ac > 0 && ac <= this.ro)
						this.F0.setValue(this.toIndex(col, row), this.toIndex(ac, ar), 1);
				}
	},

	/**
	 * 局面を初期化します。
	 * @since 0.3
	 */
	clear : function() {
		this.F = this.F0.clone();						// 連接関係
		this.b = new BVector(this.order, 1);			// 黒の着点∨空点
		this.w = this.b.clone();						// 白の着点∨空点
		this.l = this.b.and(this.w);					// 空点
		this.k = new BVector(this.order);				// コウ
		if (playout)
			this.k1 = new BVector(this.order);			// 1手前のコウ
		this.ib = new BVector(this.order);				// 黒石の活路
		this.iw = new BVector(this.order);				// 白石の活路
		this.calcVectors(0, 0);
		if (this.v6 != null)
			this.v6.calcSixVectors(this);
		this.watch = null;								// 監視する BVector
		this.turn = BLACK;								// 手番(次の番)
		this.moves = 0;									// 手数
		this.prisoner = [0, 0];							// アゲハマ
		this.liberty = [0, 0];							// 活路の数
	},

	/**
	 * 監視する BVector を設定します。
	 * @param watch 監視する BVector を指定します。 null なら監視を解除します。
	 * @since 0.1
	 */
	setWatch : function(watch) {
		this.watch = watch;
	},

	/**
	 * 監視する BVector を返します。
	 * @return 監視する BVector を返します。なければ null を返します。
	 * @since 0.1
	 */
	getWatch : function() {
		return this.watch;
	},

	/**
	 * 碁盤上の点 (move) をベクトル要素の添字 (index) に変換します。
	 * @param col 点の横方向の座標
	 * @param row 点の縦方向の座標
	 * @return 添字を返します。(1 origin)
	 * @since 0.1
	 */
	toIndex : function(col, row) {
		return (row - 1) * this.ro + col;
	},

	/**
	 * ベクトル要素の添字 (index) を碁盤上の点 (move) に変換します。
	 * @param index 添字を渡します。 (1 origin)
	 * @return 碁盤上の点の座標をクラス Move のオブジェクトとして返します。
	 * @since 0.1
	 */
	toMove : function(index) {
		var mv = new Move();
		mv.row = Math.floor((index - 1) / this.ro) + 1;
		mv.col = (index - 1) % this.ro + 1;
		return mv;
	},

	/**
	 * turn の反対のプレイヤーを返します。
	 * @param turn BLACK か WHITE を指定します。
	 * @return turn の反対のプレイヤーを返します。
	 * @since 0.1
	 */
	opposite : function(turn) {
		return OPPOSITE - turn;
	},

	/**
	 * 着手により局面を更新します。 col と row のいずれかを ro+1 にするとパスできます。
	 * @param col 着手の横座標
	 * @param row 着手の縦座標
	 * @return 着手できたら true、着手できない手なら false を返します。
	 * @since 0.1
	 */
	move : function(col, row) {
		var mv = new Move(col, row);
		if (!mv.isPass(this.ro)) {
			if (!this.isMovable(col, row))
				return false;
			this.calcVectors(col, row);
			if (this.v6 != null)
				this.v6.calcSixVectors(this);
		}
		this.turn = this.opposite(this.turn);
		this.moves++;
		return true;
	},

	/**
	 * 与えられた交点に着手できるかどうかを調べます。
	 * @param col 調べる交点の桁位置
	 * @param row 調べる交点の行位置
	 * @return 着手可能なら true を返します。
	 * @since 0.3
	 */
	isMovable : function(col, row) {
		if (this.h == null) {
			this.h = new BVector(this.order);
		}
		if (playout) {
			var rb = new BVector(this.order);	// プレイアウトでの黒石の着手禁止点を表すベクトル
			var rw = new BVector(this.order);	// プレイアウトでの白石の着手禁止点を表すベクトル
			var z = new BVector(this.order);	// all 0 (zero)
		}
		var tF = this.F.tran();
		for (var i = 1; i <= this.order; i++) {
			var ei = new BVector(this.order);
			ei.setValue(i, 1);
			var tFei = tF.mul(ei); 
			if ((tFei.and(this.l)).abs() == 1)
				this.h.setValue(i, 1);
			else
				this.h.setValue(i, 0);
			if (playout) {
				var F0ei_ei = this.F0.mul(ei).diff(ei);
				if (F0ei_ei.diff(this.w.inv()).equals(z))
					rb.setValue(i, 1);
				if (F0ei_ei.diff(this.b.inv()).equals(z))
					rw.setValue(i, 1);
			}
		}
		if (row == 0 && col == 0)
			return false;
		var o = new BVector(this.order);
		if (playout) {
			if (this.turn == BLACK)
				o = this.F.mul(this.b.xor(this.h)).and(this.l).diff(this.k).diff(rb.diff(this.k1));
			else if (this.turn == WHITE)
				o = this.F.mul(this.w.xor(this.h)).and(this.l).diff(this.k).diff(rw.diff(this.k1));
			else
				return false;
		} else {
			if (this.turn == BLACK)
				o = this.F.mul(this.b.xor(this.h)).and(this.l).diff(this.k);
			else if (this.turn == WHITE)
				o = this.F.mul(this.w.xor(this.h)).and(this.l).diff(this.k);
			else
				return false;
		}
		var i = this.toIndex(col, row);	// 調べる着点
		var ei = new BVector(this.order);
		ei.setValue(i, 1);
		if (o.and(ei).equals(ei))
			return true;
		return false;
	},

	/**
	 * BWモデルに関連するベクトルと行列を計算します。計算の対象は以下のとおり。<br>
	 * l - 空点を表すベクトル<br>
	 * h - アタリの石の集合を表すベクトル<br>
	 * a - 着手によって形成される連接点を表すベクトル<br>
	 * d - 着手によって削除される石を表すベクトル<br>
	 * A - 着手によって追加される連接点を表す行列<br>
	 * D - 着手によってリセットされる連接点を表す行列<br>
	 * b - 着手後の黒石∨空点を表すベクトル<br>
	 * w - 着手後の白石∨空点を表すベクトル<br>
	 * F - 着手後の連接点を表す行列<br>
	 * k - 着手後のコウを表すベクトル<br>
	 * ib - 着手後の黒石の活路を表すベクトル<br>
	 * iw - 着手後の白石の活路を表すベクトル
	 * @param col 着手した点の横座標
	 * @param row 着手した点の縦座標
	 * @since 0.3
	 */
	calcVectors : function(col, row) {
		if (this.h == null)
			this.h = new BVector(this.order);
		var tF = this.F.tran();							// Fの転置
		for (var i = 1; i <= this.order; i++) {
			var ei = new BVector(this.order);
			ei.setValue(i, 1);
			var tFei = tF.mul(ei); 
			if ((tFei.and(this.l)).abs() == 1)
				this.h.setValue(i, 1);
			else
				this.h.setValue(i, 0);
		}
		if (row ==0 && col==0)
			return;
		var i = this.toIndex(col, row);					// 着点
		var ei = new BVector(this.b.order);
		ei.setValue(i, 1);
		var Fei = this.F.mul(ei);						// 着点を連接点とする交点
		var F0ei = this.F0.mul(ei);						// 着点の隣接点
		var z = new BVector(this.b.order);				// all 0 (zero)
		if (playout)
			this.k1 = this.k.clone();					// 1手前のコウ
		if (this.turn == BLACK) {
			this.a = (Fei.diff(this.w)).or(ei);			// 着点を連接点とする黒石と着点
			this.d = (Fei.and(this.h)).diff(this.b);	// 着点を連接点とする白石のアタリの連
			if (F0ei.diff(ei).and(this.b).abs() == 0 && this.d.abs() == 1)
				this.k = this.d;
			else
				this.k = z;
			this.b = this.b.or(this.d);
			this.w = this.w.diff(ei);
			this.prisoner[P_BLACK] += this.d.abs();
		} else if (this.turn == WHITE) {
			this.a = (Fei.diff(this.b)).or(ei);			// 着点を連接点とする白石と着点
			this.d = (Fei.and(this.h)).diff(this.w);	// 着点を連接点とする黒石のアタリの連
			if (F0ei.diff(ei).and(this.w).abs() == 0 && this.d.abs() == 1)
				this.k = this.d;
			else
				this.k = z;
			this.b = this.b.diff(ei);
			this.w = this.w.or(this.d);
			this.prisoner[P_WHITE] += this.d.abs();
		}
		this.A = this.a.cross(tF.mul(this.a));
		var o = new BVector(this.b.order, 1);			// all 1 (one)
		this.D = this.F0.or((this.d.inv()).cross(o));
		this.F = (this.F.or(this.A)).and(this.D);
		this.l = this.b.and(this.w);
		this.ib = (tF.mul((this.w).inv())).and(this.l);	// 黒石の活路
		this.liberty[P_BLACK] = this.ib.abs();			// 黒石の活路の数
		this.iw = (tF.mul((this.b).inv())).and(this.l);	// 白石の活路
		this.liberty[P_WHITE] = this.iw.abs();			// 白石の活路の数
	},

move02.js

変更はありません。
リンク先をご覧下さい。

bvector05.js

変更はありません。
リンク先をご覧下さい。

bmatrix04.js

変更はありません。
リンク先をご覧下さい。