<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="りばーし君"
			 description="敵AIの思考がいやらしいJavaScriptでできたリバーシです。白がプレイヤーで先攻です。"
			 author_email="heiwaboke@gmail.com"
			 width="200"
			 height="225"
			 screenshot="http://www.heiwaboke.net/PHP/osero/ribarshikun.png"
			 thumbnail="http://www.heiwaboke.net/PHP/osero/ribarshikun-thumb.png"
			 author="ｔｎ"
			 author_link="http://www.heiwaboke.net/"
			 author_location="Japan" />
<UserPref name="turn" display_name="先攻後攻" datatype="enum" default_value="1">
	<EnumValue value="1" display_value="先攻（白）" />
	<EnumValue value="-1" display_value="後攻（黒）" />
</UserPref>
<Content type="html">
<![CDATA[
<style type=text/css>
<!--
* {
	margin:0;
	padding:0;
	font:normal normal normal 100%/1.3 "ＭＳ Ｐゴシック","Osaka",sans-serif;
	border:none;
}
body {
	color: #000000;
	background-colro: #ffffff;
	font-size: 10px;
}
table {
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
}
td {
	text-align: center;
	vertical-align: middle;
}
#last {
	border-style: solid;
	border-color: #000000;
	border-width: 0px 0px 1px 0px;
}
-->
</style>
<script type="text/javascript">
var reversi = {
	ver			: 0.50,
	prefs		: new _IG_Prefs(__MODULE_ID__),
	ailv		: 3,
	masu		: 8,
	maximum		: 1000000,
	minimum		: -1000000,
	img			: [],
	siro		: 1,
	kuro		: -1,
	muzi		: 0,
	putflag		: true,
	ImageSiro	: "",
	ImageKuro	: "",
	ImageMuzi	: ""
}
var gameObj;

Array.prototype.clone = function(){
	return Array.apply(null,this);
}

reversi.Game = function()
{
	this.turn = reversi.prefs.getInt("turn");
	this.copy = [];
	this.all = 0;
	reversi.putflag = true;
	
	this.board = [[0,0,0,0,0,0,0,0],
				  [0,0,0,0,0,0,0,0],
				  [0,0,0,0,0,0,0,0],
				  [0,0,0,-1,1,0,0,0],
				  [0,0,0,1,-1,0,0,0],
				  [0,0,0,0,0,0,0,0],
				  [0,0,0,0,0,0,0,0],
				  [0,0,0,0,0,0,0,0]];
	
	this.pointmap = [[ 30,-12,  0, -1, -1,  0,-12, 30],
					 [-12,-15, -3, -3, -3, -3,-15,-12],
					 [  0, -3,  0, -1, -1,  0, -3,  0],
					 [ -1, -3, -1, -1, -1, -1, -3, -1],
					 [ -1, -3, -1, -1, -1, -1, -3, -1],
					 [  0, -3,  0, -1, -1,  0, -3,  0],
					 [-12,-15, -3, -3, -3, -3,-15,-12],
					 [ 30,-12,  0, -1, -1,  0,-12, 30]];
	
	this.map = [[ -1,  0,  1, -1,  1, -1,  0,  1],
				[ -1, -1, -1,  0,  0,  1,  1,  1]];
	
	this.dmap = [[ 0, 0, 7, 7], [ 0, 7, 0, 7], [[ 1, 2], [ 1, 4], [ 3, 2], [ 3, 4]]];
	
	var k = 0;
	for(var i = 0; i < reversi.masu; i++){
		reversi.img[i] = [];
		for(var j = 0; j < reversi.masu; j++){
			reversi.img[i][j] = document.getElementById(k);
			reversi.img[i][j].onclick = this.getPoint(k);
			k++;
		}
	}
	
	this.cmd = document.getElementById("cmd");
	this.com = document.getElementById("com");
	this.cmd.innerHTML = "";
	this.com.innerHTML = "";
	this.printBoard();
	
	// AIが先攻の場合
	if(this.turn == reversi.kuro){
		this.aiStoneCheck();
		this.printBoard();
	}
};
reversi.Game.prototype = {
	startTurn: function(y, x)
	{
		if(this.checkReverse(y, x)){
			this.all++;
			this.printBoard();
			this.aiStoneCheck();
			this.printBoard();
		} else {
			if(this.boardStoneCheck()){
				this.com.innerHTML = "そこには置けません。";
			} else {
				this.aiStoneCheck();
				this.printBoard();
			}
		}
	},
	
	irekae: function()
	{
		this.turn *= -1;
	},
	
	getPoint: function(data)
	{
		return function()
		{
			if(reversi.putflag){
				reversi.putflag = false;
				gameObj.startTurn((Math.floor(data / reversi.masu)), (data % reversi.masu));
				reversi.putflag = true;
			} else {
				alert("処理中です");
			}
		}
	},
	
	keep: function(lv)
	{
		this.copy[lv] = [];
		for(var i = 0; i < reversi.masu; i++){
			this.copy[lv][i] = this.board[i].clone();
		}
	},
	
	back: function(lv)
	{
		for(var i = 0; i < reversi.masu; i++){
			this.board[i] = this.copy[lv][i].clone();
		}
	},
	
	aiStoneCheck: function()
	{
		var ij;
		var txt = "";
		this.irekae();
		ij = this.AandB(true, reversi.ailv, reversi.minimum, reversi.maximum);
		var y = Math.floor(ij / reversi.masu);
		var x = ij % reversi.masu;
		if(y != null || y >= 0 || x != null || x >= 0){
			this.checkReverse(y, x);
			txt = "AIは " + this.abcdefgh(x) + (y+1) + " に置きました。<br />";
			this.all++;
		} else {
			txt = "AIはパスしました";
		}
		this.com.innerHTML = txt;
		this.irekae();
	},
	
	AandB: function(flag, ai, a, b)
	{
		var val, Cval, bestY = -1, bestX = -1;
		
		if(ai == 0) return this.boardPoint(flag);
		
		if(flag){
			val = reversi.minimum;
		} else {
			val = reversi.maximum;
		}
		this.keep(ai);
		for(var i = 0; i < reversi.masu; i++){
			for(var j = 0; j < reversi.masu; j++){
				if(this.board[i][j] == reversi.muzi){
					if(this.putStoneCheck(i, j)){
						this.checkReverse(i, j);
						this.irekae();
						Cval = this.AandB(!flag, ai-1, a, b);
						this.irekae();
						this.back(ai);
						
						if(flag){
							if(Cval > val){
								val = Cval;
								a = val;
								bestY = i;
								bestX = j;
							}
							if(val > b) return val;
						} else {
							if(Cval < val){
								val = Cval;
								b = val;
								bestY = i;
								bestX = j;
							}
							if(val < a) return val;
						}
					}
				}
			}
		}
		if(ai == reversi.ailv){
			if((bestY == -1) || (bestX == -1)){
				return false;
			}
			return ((bestY * reversi.masu) + bestX);
		}
		if((bestY == -1) || (bestX == -1)) return this.boardPoint(flag);
		return val;
	},
	
	boardPoint: function(flag)
	{
		var point = 0;
		for(var i = 0; i < reversi.masu; i++){
			for(var j = 0; j < reversi.masu; j++){
				point += this.board[i][j] * this.pointmap[i][j];
			}
		}
		point += this.decisionStone() * 5;
		
		if(flag){
			return point;
		}
		return -point;
	},
	
	stoneCheck: function(i, j, y, x)
	{
		i += y;
		j += x;
		
		if((i >= reversi.masu) || (i < 0) || (j >= reversi.masu) || (j < 0)){
			return false;
		}
		if(this.board[i][j] != (this.turn * -1)){
			return false;
		}
		
		i += y;
		j += x;
		
		while((i < reversi.masu) && (i >= 0) && (j < reversi.masu) && (j >= 0)){
			if(this.board[i][j] == reversi.muzi) return false;
			if(this.board[i][j] == this.turn) return true;
			i += y;
			j += x;
		}
		return false;
	},
	
	putStoneCheck: function(i, j)
	{
		for(var k = 0; k < reversi.masu; k++){
			if(this.stoneCheck(i, j, this.map[0][k], this.map[1][k])) return true;
		}
		return false;
	},
	
	boardStoneCheck: function()
	{
		var count = 0;
		for(var i = 0; i < reversi.masu; i++){
			for(var j = 0; j < reversi.masu; j++){
				if(this.board[i][j] == reversi.muzi){
					if(this.putStoneCheck(i, j)){
						count++;
					}
				}
			}
		}
		if(count == 0){
			return false;
		} else {
			return true;
		}
	},
	
	checkReverse: function(i, j)
	{
		if(this.board[i][j] == reversi.muzi){
			var count = 0;
			var hanten = 0;
			for(var k = 0; k < reversi.masu; k++){
				if(this.stoneCheck(i, j, this.map[0][k], this.map[1][k])){
					hanten += this.hanten(i, j, this.map[0][k], this.map[1][k]);
					count++;
				}
			}
			if(count != 0){
				return hanten;
			}
		}
		return false;
	},
	
	hanten: function(i, j, y, x)
	{
		this.board[i][j] = this.turn;
		i += y;
		j += x;
		var hanten = 1;
		
		while(this.board[i][j] == (this.turn * -1)){
			this.board[i][j] = this.turn;
			i += y;
			j += x;
			hanten++;
		}
		return hanten;
	},
	
	decisionStone: function()
	{
		var point = 0;
		for(var i = 0; i < 4; i++){
			if(this.board[this.dmap[0][i]][this.dmap[1][i]] != reversi.muzi){
				point += this.decisionCount(this.dmap[0][i], this.dmap[1][i], this.dmap[2][i][0]);
				point += this.decisionCount(this.dmap[0][i], this.dmap[1][i], this.dmap[2][i][1]);
			}
		}
		return point;
	},
	
	decisionCount: function(y, x, type)
	{
		var count = 0;
		var my = 0;
		var my2 = 0;
		var enemy = 0;
		var enemy2 = 0;
		
		while(this.board[y][x] != reversi.muzi){
			if((this.board[y][x] == this.turn) && (my == count)){
				my++;
			} else if(this.board[y][x] == this.turn){
				my2++;
			}
			
			if((this.board[y][x] != this.turn) && (enemy == count)){
				enemy++;
			} else if(this.board[y][x] != this.turn){
				enemy2++;
			}
			
			if(count >= 7){
				return ((my + my2) - (enemy + enemy2));
			}
			
			count++;
			
			switch(type){
				case 1:
					y++;
					break;
				
				case 2:
					x++;
					break;
				
				case 3:
					y--;
					break;
				
				case 4:
					x--;
					break;
			}
		}
		return (my - enemy);
	},
	
	abcdefgh: function(x)
	{
		// a + x
		return String.fromCharCode(97 + x);
	},
	
	printBoard: function()
	{
		var siroisi = 0;
		var kuroisi = 0;
		var aki = 0;
		var txt = "";
		for(var i = 0; i < reversi.masu; i++){
			for(var j = 0; j < reversi.masu; j++){
				if(this.board[i][j] == reversi.siro){
					reversi.img[i][j].src = reversi.imageSiro;
					siroisi++;
				} else if(this.board[i][j] == reversi.kuro){
					reversi.img[i][j].src = reversi.imageKuro;
					kuroisi++;
				} else {
					reversi.img[i][j].src = reversi.imageMuzi;
					aki++;
				}
			}
		}
		txt = "白 " + siroisi + "個　　黒" + kuroisi + "個<br />";
		if(aki == 0){
			if((this.turn == reversi.siro) && (kuroisi < siroisi)){
				txt += "あなたの勝ちです。<br />";
			} else if((this.turn == reversi.kuro) && (siroisi < kuroisi)){
				txt += "あなたの勝ちです。<br />";
			} else {
				txt += "あなたの負けです。<br />";
			}
		}
		this.cmd.innerHTML = txt;
	}
}

_IG_RegisterOnloadHandler(function(){
	reversi.imageSiro = _IG_GetImageUrl("http://www.heiwaboke.net/PHP/osero/siro2.gif");
	reversi.imageKuro = _IG_GetImageUrl("http://www.heiwaboke.net/PHP/osero/kuro2.gif");
	reversi.imageMuzi = _IG_GetImageUrl("http://www.heiwaboke.net/PHP/osero/muzi2.gif");
	
	var txt = [];
	txt[0] = "<center><table><tr><td> </td>";
	for(var i = 1; i <= reversi.masu; i++){
		txt[i] = "<td>" + String.fromCharCode(96 + i) + "</td>";
	}
	txt[i] = "</tr>";
	var k = 0;
	for(var i = 1; i <= reversi.masu; i++){
		txt[txt.length] = "<tr><td>" + i + "</td>";
		for(var j = 0; j < reversi.masu; j++){
			txt[txt.length] = '<td><img src="" width="18" height="18" id="' + k + '" /></td>';
			k++;
		}
		txt[txt.length] = "</tr>";
	}
	txt[txt.length] = '<tr><td colspan="9"><div id="last"><!--line--></div></td><tr><tr><td colspan="2"><button onclick="gameObj = new reversi.Game();">再</button></td><td colspan="7"><div id="com"></div><div id="cmd"></div></td></tr></table></center>';
	document.getElementById("board").innerHTML = txt.join("");
	gameObj = new reversi.Game();
});
</script>
<div id="board"></div>
]]></Content>
</Module>