読者です 読者をやめる 読者になる 読者になる

node.jsでchess

node.jsでネット対戦できるチェスができたのでメモ

まず、サーバサイドの処理

var fs = require("fs");
var path = require("path");

var server = require("http").createServer(function(req, res){
  console.log("request:" + req.url);
  res.writeHead(200, {"Content-Type":"text/html"});
  
  //console.log("pathExist", path.existsSync("/onlineChess.html"));
  var output = "";
  try {
    fs.statSync("." + req.url);
    console.log("file found")
    output = fs.readFileSync("." + req.url, "utf-8");
  } catch (e) {
    console.log("no file");
  }
  res.end(output);
}).listen(8888);
console.log("server running port 8888");
var io = require("socket.io").listen(server);

var userHash = {};
var userRoomHash = {};
var roomStateHash = {};
var userTeamHash = {};
var roomPieces = {};
var roomTurn = {};
var roomScore = {}

io.sockets.on("connection",  function(socket) {
  console.log("connection connected socket-id" + socket.id);
  socket.join(socket.id);
  socket.on("roomSelect", function(data){
    console.log("roomSelect");
    console.log("roomClient" + io.sockets.manager);
    var name = data.name;
    var room = data.room;
    console.log("name:" + name + "; room" + room);
    if(room.match(/[^0-9]+/)){
      io.sockets.to(socket.id).emit("room", {result:0, msg:"フォーマットエラー"});
      console.log("フォーマットエラー");
      return;
    }
    if(roomStateHash[room] == undefined) roomStateHash[room] = 0;
    console.log("room" + room +" state:" + roomStateHash[room]);
    if(roomStateHash[room]>=2){
      io.sockets.to(socket.id).emit("room", {result:0, msg:"満室です"});
      return;
    }else{
      userHash[socket.id] = name;
      userRoomHash[socket.id] = room;
      if(roomStateHash[room] == null || roomStateHash[room] == 0){
        roomStateHash[room] = 1;
        userTeamHash[socket.id] = 'W';
        roomPieces[room] = piecesInit();
        roomTurn[room] = "S";
        roomScore[room] = new Score();
      }else{
        roomStateHash[room] += 1;
        if(roomStateHash[room] == 2){
          userTeamHash[socket.id] = 'B';
          roomTurn[room] = "W";
        }
      }
     //var html = fs.readFileSync("./socket_game.html", "utf-8");
     
     
     io.sockets.to(socket.id).emit("roomIn", {result:1,
                                msg:"あなたは room" + room + "に入室しました。",
                                team: userTeamHash[socket.id],
                                pieces: pieces,
                                turn: turn,
                                });
    
    }
    socket.join(userRoomHash[socket.id]);
    var pieces = roomPieces[room];
    var turn = roomTurn[room];
    io.sockets.to(userRoomHash[socket.id]).emit("turnChange",
                                  {msg:userHash[socket.id] + "がroom" + userRoomHash[socket.id] + "に入室しました",
                                  pieces: pieces,
                                  turn: turn,
                                  });
  });

  socket.on("connected", function(name){
    console.log("connected");
    var msg = name + "が入室しました";
    userHash[socket.id] = name;
    io.sockets.emit("publish", {value: msg});
  });

  socket.on("publish", function(msg){
    console.log("publish msg:" + msg);
    io.sockets.to(userRoomHash[socket.id]).emit("publish", {value:userHash[socket.id] + ":" +  msg});
  });
  
  socket.on("pieceMove", function(data){
    var turn = userTeamHash[socket.id];
    console.log("pieces move turn:" + turn);
    if(turn == "W"){
      turn = "B";
    }else{
      turn = "W";
    }
    io.sockets.to(userRoomHash[socket.id]).emit("turnChange",
                                  {msg:"",
                                  pieces: data.pieces,
                                  turn: turn,
                                  check: data.check,
                                  });
  });
  
  socket.on("win", function(data){
    var room = userRoomHash[socket.id];
    var score = roomScore[room];
    score.win(data.team);
    io.sockets.to(userRoomHash[socket.id]).emit("gameEnd",
                                  {msg:"",
                                  pieces: data.pieces,
                                  score: score,
                                  });
  });

  socket.on("disconnect", function(){
    console.log("disconnect");
    if(userHash[socket.id]){
      var msg = userHash[socket.id] + "が退出しました";
      io.sockets.to(userRoomHash[socket.id]).emit("publish", {value:msg});
      if(roomStateHash[userRoomHash[socket.id]] != undefined){
        roomStateHash[userRoomHash[socket.id]] -= 1;
      }
      console.log("room" + userRoomHash[socket.id] + "state:" + roomStateHash[userRoomHash[socket.id]]);
      delete userRoomHash[socket.id];
      delete userHash[socket.id];
    }
  });
  
});


Object.subClass = function(properties) {                           //#2
  var _super = this.prototype;

  // Instantiate a base class (but only create the instance,
  // don't run the init constructor)
  initializing = true;                                              //#3
  var proto = new this();                                           //#3
  initializing = false;                                             //#3

  // Copy the properties over onto the new prototype
  for (var name in properties) {                                    //#4
    // Check if we're overwriting an existing function
    proto[name] = typeof properties[name] == "function" &&
                  typeof _super[name] == "function" &&
                  superPattern.test(properties[name]) ?
        (function(name, fn) {                                        //#5
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);
            this._super = tmp;

            return ret;
          };
        })(name, properties[name]) :
        properties[name];
  }

  // The dummy class constructor
  function Class() {                                                   //#6
    // All construction is actually done in the init method
    if (!initializing && this.init)
      this.init.apply(this, arguments);
  }

  // Populate our constructed prototype object
  Class.prototype = proto;                                             //#7

  // Enforce the constructor to be what we expect
  Class.constructor = Class;                                           //#8

  // And make this class extendable
  Class.subClass = arguments.callee;                                   //#9

  return Class;
};

var Piece = Object.subClass({
	column:0,
	row:0,
	role:'',
	live:1,
	team:0,
	init:function(column, row, role, team, live){
		this.column = column;
		this.row = row;
		this.role = role;
		this.team = team;
		this.live = live;
	}
});

var Score = Object.subClass({
	wWin:0,
	bWin:0,
	win:function(team){
		if(team == "W"){
		 	this.wWin += 1;
		}else{
		 	this.bWin += 1;
		}
	}
});

function piecesInit(){
	
	var blackData = [
			[0,0,'L'],[1,0,'N'],[2,0,'B'],[3,0,'Q'],[4,0,'K'],[5,0,'B'],[6,0,'N'],[7,0,'L'],
			[0,1,'P'],[1,1,'P'],[2,1,'P'],[3,1,'P'],[4,1,'P'],[5,1,'P'],[6,1,'P'],[7,1,'P']
		];
	/*
	var blackData = [
			[0,1,'P'],[4,0,'K']
		];
	*/
	var blackPeace =[]
	for(var i=0; i<blackData.length; i++){
		blackPeace[i] = new Piece(blackData[i][0], blackData[i][1], blackData[i][2], 'B', 1);
	}
	
	var whiteData = [
			[0,7,'L'],[1,7,'N'],[2,7,'B'],[3,7,'Q'],[4,7,'K'],[5,7,'B'],[6,7,'N'],[7,7,'L'],
			[0,6,'P'],[1,6,'P'],[2,6,'P'],[3,6,'P'],[4,6,'P'],[5,6,'P'],[6,6,'P'],[7,6,'P']
		];
	/*
	var whiteData = [[7,6,'P'],[4,7,'K']
		];
	*/
	var whitePeace =[]
	for(var j=0; j<whiteData.length; j++){
		whitePeace[j] = new Piece(whiteData[j][0], whiteData[j][1], whiteData[j][2], 'W', 1);
	}
	
	var gPieces = {
		white:whitePeace,
		black:blackPeace
	}
	return gPieces;
}

サーバーサイドの処理としては、socket.ioを使用して駒の位置情報の共有及び、チャットの機能を実現している。
fs.statSyncではfsモジュールにより相対パスでリクエストされたファイルが存在するかチェックし、存在するのなら返している。
ゲームの積み判定周りの処理はクライアント側で実装している。

次に、クライアントサイドのhtml及び、jsは以下になる。

<html>
<head>
  <meta charset="UTF-8">
  <title>nodejs game</title>
  <script src="/socket.io/socket.io.js"></script>
  <script src="/subclass.js"></script>
  <script src="/chess.js"></script>
  <script type="text/javascript">
    var msgArea;
    var socketio = io.connect('http://サーバーのドメイン:8888');
    var gameController = new GameController();

    
    socketio.on("connected", function(name){});
    socketio.on("roomIn", function(data){roomIn(data);});
    socketio.on("turnChange", function(data){turnChange(data);});
    socketio.on("gameEnd", function(data){gameEnd(data);});
    socketio.on("publish", function(data){addMessage(data.value);});
    socketio.on("disconnect", function(){});

    function selectRoom(){
      console.log("select Room");
      var data = {};
      var name = document.getElementById("name_input");
      var room = document.getElementById("room_input");
      data.name = name.value;
      data.room = room.value;
      socketio.emit("roomSelect", data);
    }

    function roomIn(data){
      if(data.result == 0){
        alert(data.msg);
      }else{
        var initArea = document.getElementById("initArea");
        initArea.setAttribute("style", "display:none");
        
        document.getElementById("chatArea").setAttribute("style", "dispaly:");        
        document.getElementById("chessArea").setAttribute("style", "display:");

        var domMsg = document.createElement('div');
        domMsg.innerHTML = new Date().toLocaleTimeString() + ' ' + data.msg;
        msgArea.appendChild(domMsg);
        
        var team = "white";
        if(data.team == "B"){
          team = "black";
        }
        document.getElementById("teamView").innerHTML = "You are " + team;
        gameController.setTeam(data.team, socketio);
      }
    }
	
	function turnChange(data){
		if(data.msg != ''){
			var domMsg = document.createElement('div');
        	domMsg.innerHTML = new Date().toLocaleTimeString() + ' ' + data.msg;
        	//msgArea.appendChild(domMsg);
        	msgArea.insertBefore(domMsg, msgArea.firstChild);
		}
		var pieces = data.pieces;
        var turn = data.turn;
        if(data.check){
        	if(gameController.myTeam == turn){
        		alert("Check Mate");
        	}
        }
        gameController.setTurn(pieces, turn);
	}
	function gameEnd(data){
		alert("gameEnd");
	}
    function start(name){
      socketio.emit("connected", name);
    }

    function publishMessage(){
      var textInput = document.getElementById('msg_input');
      socketio.emit("publish", textInput.value);
      textInput.value='';
    }

    function addMessage(msg){
      var domMsg = document.createElement('div');
      domMsg.innerHTML = new Date().toLocaleTimeString() + ' ' + msg;
      //msgArea.appendChild(domMsg);
      msgArea.insertBefore(domMsg, msgArea.firstChild);
    }

    
	function start(){
		msgArea = document.getElementById("msg");
		gameController.boardInit();
	}
	
	function viewAtackArea(team){
		gameController.viewAtackArea(team, true);
	}
	
	
  </script>
</head>
 <body onload="start();">
  <h1>online Chess</h1>
  <div id="initArea">
    <h1>名前入力</h1>
    <input type="text" id="name_input" style="width:200px;" />
    <h1>部屋選択</h1>
    <select id="room_input" >
    	<option value="1">1</option>
    	<option value="2">2</option>
    	<option value="3">3</option>
    	<option value="4">4</option>
    	<option value="5">5</option>
    </select>
    <button onclick="selectRoom();">選択</button>
  </div>
  </div>
	<div id="chessArea" style="display:none">
		<h3><div id="teamView"></div></h1>
		<canvas id="chess_canvas"></canvas>
		<p>turn: <span id="turn"></span></p>
		<p>White Win: <span id="wWin"></span> Black Win: <span id="bWin"></span></p>
		
		<button onclick="viewAtackArea('W');">White Area</button>
		<button onclick="viewAtackArea('B');">Black Area</button><br />
		<button onclick="start();">Restart</button>
		
	</div>
	<div id="chatArea" style="display:none">
	    <button onclick="publishMessage();">コメント</button>
	    <input type="text" id="msg_input" style="width:200px;" />
	    <div id="msg"></div>
	</div>
</body>
</html>
(function() {
  var initializing = false,
      superPattern =  // Determine if functions can be serialized
        /xyz/.test(function() { xyz; }) ? /\b_super\b/ : /.*/;       //#1

  // Creates a new Class that inherits from this class
  Object.subClass = function(properties) {                           //#2
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;                                              //#3
    var proto = new this();                                           //#3
    initializing = false;                                             //#3

    // Copy the properties over onto the new prototype
    for (var name in properties) {                                    //#4
      // Check if we're overwriting an existing function
      proto[name] = typeof properties[name] == "function" &&
                    typeof _super[name] == "function" &&
                    superPattern.test(properties[name]) ?
          (function(name, fn) {                                        //#5
            return function() {
              var tmp = this._super;

              // Add a new ._super() method that is the same method
              // but on the super-class
              this._super = _super[name];

              // The method only need to be bound temporarily, so we
              // remove it when we're done executing
              var ret = fn.apply(this, arguments);
              this._super = tmp;

              return ret;
            };
          })(name, properties[name]) :
          properties[name];
    }

    // The dummy class constructor
    function Class() {                                                   //#6
      // All construction is actually done in the init method
      if (!initializing && this.init)
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = proto;                                             //#7

    // Enforce the constructor to be what we expect
    Class.constructor = Class;                                           //#8

    // And make this class extendable
    Class.subClass = arguments.callee;                                   //#9

    return Class;
  };
})();


var GameController = Object.subClass({
	gCanvasElement: '',
	gDrawingContext: '',
	kBoardWidth: 8,
	kBoardHeight:8,
	kNumPieces: 9,
	kPieceWidth: 50,
	kPieceHeight:50,
	wWin:0,
	bWin:0,
	kPixelWidth:'',
	kPixelHeight: '',
	gCells:'',
	gPieces:'',
	gMoveAreaCells:'',
	gSelectedPiece:'',
	gNumPieces:'',
	turn:'',
	selected:false,
	checkPiece:'',
	myTeam:'',
	socketio: '',
	boardInit:function(){
		this.kPixelWidth = 1 + (this.kBoardWidth * this.kPieceWidth);
		this.kPixelHeight= 1 + (this.kBoardHeight * this.kPieceHeight);

	    this.gCanvasElement = document.getElementById("chess_canvas");
	    this.gCanvasElement.width = this.kPixelWidth;
	    this.gCanvasElement.height = this.kPixelHeight;
	    this.gCanvasElement.addEventListener("click", this.chessOnClick, false);
	    this.gDrawingContext = this.gCanvasElement.getContext("2d");
	    
	    this.cellDataInit();
	    //this.pieceDataInit();
	    this.drawBoard();
	    
	    //this.turn = 'W';
	    //this.viewTurn();
	    
	    this.viewWin();
	},
	cellDataInit: function(){
		var cells = new Array(this.kBoardWidth);
		for(var i=0; i < this.kBoardWidth; i++){
			var rowCell = new Array(this.kBoardHeight);
			for(var j=0; j < this.kBoardHeight; j++){
				var style = 'rgb(255,255,255)';
				if((i+j) % 2 == 1){
					style = 'rgb(150,150,150)';
				}
				rowCell[j] = new Cell(i, j, style);
			}
			cells[i] = rowCell;
		}
		this.gCells = cells;
		this.gMoveAreaCells = new Array();
	},
	drawBoard: function() {
		this.gDrawingContext.clearRect(0, 0, this.kPixelWidth, this.kPixelHeight);

	    this.gDrawingContext.beginPath();
	    
	    /* vertical lines */
	    for (var x = 0; x <= this.kPixelWidth; x += this.kPieceWidth) {
			this.gDrawingContext.moveTo(0.5 + x, 0);
			this.gDrawingContext.lineTo(0.5 + x, this.kPixelHeight);
	    }
	    
	    /* horizontal lines */
	    for (var y = 0; y <= this.kPixelHeight; y += this.kPieceHeight) {
			this.gDrawingContext.moveTo(0, 0.5 + y);
			this.gDrawingContext.lineTo(this.kPixelWidth, 0.5 +  y);
	    }
	    this.gDrawingContext.strokeStyle = "#ccc";
	    this.gDrawingContext.stroke();
	    
	    this.viewRefresh();
	   
	},
	fillBack: function(cell, style){
		if(style != null){
			this.gDrawingContext.fillStyle = style;
			this.gDrawingContext.fillRect(cell.column * this.kPieceWidth + 1, cell.row * this.kPieceHeight + 1,
					this.kPieceWidth - 2, this.kPieceHeight - 2);
		}
	},
	chessOnClick: function(event) {
		if(gameController.turn == gameController.myTeam){
			var clickCol = Math.floor((event.clientX - gameController.gCanvasElement.getBoundingClientRect().left) / gameController.kPieceWidth);
			var clickRow = Math.floor((event.clientY - gameController.gCanvasElement.getBoundingClientRect().top) / gameController.kPieceHeight);
			if(gameController.selected == false){
				var turn = "W";
				if(gameController.turn == "W"){
					turn = "B";
				}
				gameController.viewAtackArea(turn, false);
				gameController.selectCell(clickCol, clickRow);
			}else{
				gameController.movePiece(clickCol, clickRow);
			}
		}
	},
	pieceDataInit: function(){
		var blackData = [
				[0,0,'L'],[1,0,'N'],[2,0,'B'],[3,0,'Q'],[4,0,'K'],[5,0,'B'],[6,0,'N'],[7,0,'L'],
				[0,1,'P'],[1,1,'P'],[2,1,'P'],[3,1,'P'],[4,1,'P'],[5,1,'P'],[6,1,'P'],[7,1,'P']
			];
		var blackPeace =[]
		for(var i=0; i < blackData.length; i++){
			blackPeace[i] = new Piece(blackData[i][0], blackData[i][1], blackData[i][2], 'B');
		}
		
		var whiteData = [
				[0,7,'L'],[1,7,'N'],[2,7,'B'],[3,7,'Q'],[4,7,'K'],[5,7,'B'],[6,7,'N'],[7,7,'L'],
				[0,6,'P'],[1,6,'P'],[2,6,'P'],[3,6,'P'],[4,6,'P'],[5,6,'P'],[6,6,'P'],[7,6,'P']
			];
		var whitePeace =[]
		for(var j=0; j < whiteData.length; j++){
			whitePeace[j] = new Piece(whiteData[j][0], whiteData[j][1], whiteData[j][2], 'W');
		}
		
		this.gPieces = {
			white:whitePeace,
			black:blackPeace
		}
	},
	setTeam: function(team, socketio){
		this.myTeam = team;
		this.socketio = socketio;
	},
	setTurn: function(pieces, turn){
		this.gPieces = pieces;
		this.turn = turn;
		this.viewRefresh();
	},
	drawPieces: function(){
		var whitePiece = this.gPieces.white;
		var blackPiece = this.gPieces.black;
		if(whitePiece === undefined || whitePiece === null){
		}else{
			for(var i=0; i < whitePiece.length; i++){
				this.drawPiece(whitePiece[i]);
			}

			for(var j=0; j < blackPiece.length; j++){
				this.drawPiece(blackPiece[j]);
			}
		}
	},
	drawPiece: function(piece){
		if(piece.live == 1){
			var column = piece.column;
		    var row = piece.row;
		    var x = (column * this.kPieceWidth) + (this.kPieceWidth/2);
		    var y = (row * this.kPieceHeight) + (this.kPieceHeight/2);
		    var radius = (this.kPieceWidth/2) - (this.kPieceWidth/10);
		    this.gDrawingContext.beginPath();
		    
		    //円の描画
		    this.gDrawingContext.arc(x, y, radius, 0, Math.PI*2, false);
		    this.gDrawingContext.closePath();
		    this.gDrawingContext.strokeStyle = "#000";
		    this.gDrawingContext.stroke();
		    if(piece.team == 'B'){
				this.gDrawingContext.fillStyle = "#000";
			}else{
				this.gDrawingContext.fillStyle = "#FFF";
			}
			this.gDrawingContext.fill();
			
			//文字の描画
			this.gDrawingContext.font = "20pt Arial";
			if(piece.team == 'B'){
				this.gDrawingContext.fillStyle = "#FFF";
			}else{
				this.gDrawingContext.fillStyle = "#000";
			}
			this.gDrawingContext.fillText(piece.role, x - 10, y + 10);
		}
	},
	viewTurn: function(){
		//ターン表示
		if(this.turn == 'W'){
			document.getElementById("turn").innerHTML = "WHITE";
		}else if(this.turn == 'B'){
			document.getElementById("turn").innerHTML = "BLACK";
		}else{
			document.getElementById("turn").innerHTML = "Wait";
		}
	},
	viewWin: function(){
	
		document.getElementById("wWin").innerHTML = this.wWin;
		document.getElementById("bWin").innerHTML = this.bWin;
	},
	findPiece: function(col, row){
		var target = target = this.gPieces.white;
		for(var i=0; i < target.length; i++){
			if(target[i].column == col && target[i].row == row && target[i].live == 1){
				return target[i];
			}
		}
		
		target = target = this.gPieces.black;
		for(var i=0; i < target.length; i++){
			if(target[i].column == col && target[i].row == row && target[i].live == 1){
				return target[i];
			}
		}
		
		return null;
	},
	selectCell: function(clickCol, clickRow){
		var targetPiece = this.findPiece(clickCol, clickRow);
		if ( targetPiece === undefined || targetPiece === null) {
		}else{
			if(targetPiece.team == this.turn){
				this.selectPiece(targetPiece, targetPiece.team, false);
			}
		}
	},
	selectPiece: function(piece, team, simulate){
		this.gSelectedPiece = piece;
		this.selected = true;
		var style = 'rgb(255, 45, 0)';
		if(simulate == true){
			style = null
		}
		
		this.fillBack( this.gCells[piece.column][ piece.row], style);
		this.drawPiece(piece);
		eval("this.draw" + piece.role + "Area(piece,team, style);");
	},
	
	drawPArea: function(piece, team, style){
		var row;
		var col = piece.column;
		if(team == 'W'){
			row = piece.row - 1;
		}else{
			row = piece.row + 1;
		}
		if(col < 0 || col > this.kBoardWidth
			|| row < 0 || row > this.kBoardHeight){
			return;
		}
		var destPiece = gameController.findPiece(col, row);
		if ( destPiece === undefined || destPiece === null) {
			this.gMoveAreaCells.push(this.gCells[col][row]);
			this.fillBack( this.gCells[col][row], style);
		}else{
		}
		if(parseInt(col)-1 >= 0){
			this.atackArea(gameController.findPiece(parseInt(col)-1, row, style), team, style);
			eval("this.gCells[col-1][row]." + team + "Atack = 1;");
		}
		if(parseInt(col)+1 < this.kBoardWidth){
			this.atackArea(gameController.findPiece(parseInt(col)+1, row, style), team, style);
			eval("this.gCells[col+1][row]." + team + "Atack = 1;");
		}
		
	},
	drawLArea: function(piece, team, style){
		for(var i=1; (i + parseInt(piece.column)) < this.kBoardWidth; i++){
			if(this.pieceJudge(parseInt(piece.column) + i, piece.row, team, style)){
				break;
			}
		}
		for(var j=1; ( parseInt(piece.column) - j) >= 0; j++){
			if(this.pieceJudge(parseInt(piece.column) - j, piece.row , team, style)){
				break;
			}
		}
		for(var k=1; (parseInt( piece.row) + k) < this.kBoardHeight; k++){
			if(this.pieceJudge(piece.column, parseInt(piece.row) + k, team, style)){
				break;
			}
		}
		for(var l=1; ( parseInt(piece.row) - l) >= 0; l++){
			if(this.pieceJudge(piece.column, parseInt(piece.row) - l, team, style)){
				break;
			}
		}
	},
	drawBArea: function(piece, team, style){
		for(var i=1; (parseInt(piece.column) + i) < this.kBoardWidth && ( parseInt(piece.row) + i) < this.kBoardHeight ; i++){
			if(this.pieceJudge(parseInt(piece.column) + i, parseInt(piece.row) + i, team, style)){
				break;
			}
		}
		for(var j=1; ( parseInt(piece.column) + j) < this.kBoardWidth && (parseInt(piece.row) - j) >= 0 ; j++){
			if(this.pieceJudge(parseInt(piece.column) + j, parseInt(piece.row) - j, team, style)){
				break;
			}
		}
		for(var k=1; (parseInt(piece.column) - k) >= 0 && ( parseInt(piece.row) + k) < this.kBoardHeight ; k++){
			if(this.pieceJudge(parseInt(piece.column) - k, parseInt(piece.row) + k, team, style)){
				break;
			}
		}
		for(var l=1; ( parseInt(piece.column) - l) >= 0 && (parseInt(piece.row) - l) >= 0 ; l++){
			if(this.pieceJudge(parseInt(piece.column) - l, parseInt(piece.row) - l, team, style)){
				break;
			}
		}
		
	},
	drawNArea: function(piece, team, style){
		if((parseInt(piece.column) + 1) < this.kBoardWidth && (parseInt(piece.row) + 2) < this.kBoardHeight){
			this.pieceJudge(parseInt(piece.column) + 1, parseInt(piece.row) + 2 ,team,style);
			
		}
		if((parseInt(piece.column) + 1) < this.kBoardWidth && (parseInt(piece.row) - 2) >= 0){
			this.pieceJudge(parseInt(piece.column) + 1, parseInt(piece.row) - 2 ,team,style);
			
		}
		if((parseInt(piece.column) + 2) < this.kBoardWidth && (parseInt(piece.row) + 1) < this.kBoardHeight){
			this.pieceJudge(parseInt(piece.column) + 2, parseInt(piece.row) + 1 ,team,style);
			
		}
		if((parseInt(piece.column) + 2) < this.kBoardWidth && (parseInt(piece.row) - 1) >= 0){
			this.pieceJudge(parseInt(piece.column) + 2, parseInt(piece.row) - 1 ,team,style);
			
		}
		if((parseInt(piece.column) - 1) >= 0 && (parseInt(piece.row) + 2) < this.kBoardHeight){
			this.pieceJudge(parseInt(piece.column) - 1, parseInt(piece.row) + 2 ,team,style);
			
		}
		if((parseInt(piece.column) - 1) >= 0 && (parseInt(piece.row) - 2) >= 0){
			this.pieceJudge(parseInt(piece.column) - 1, parseInt(piece.row) - 2 ,team,style);
			
		}
		if((parseInt(piece.column) - 2) >= 0 && (parseInt(piece.row) + 1) < this.kBoardHeight){
			this.pieceJudge(parseInt(piece.column) - 2, parseInt(piece.row) + 1 ,team,style);
			
		}
		if((parseInt(piece.column) - 2) >= 0 && (parseInt(piece.row) - 1) >= 0){
			this.pieceJudge(parseInt(piece.column) - 2, parseInt(piece.row) - 1 ,team,style);
		}
	},
	drawQArea: function(piece, team, style){
		this.drawLArea(piece, team, style);
		this.drawBArea(piece, team, style);
	},
	drawKArea: function(piece, team, style){
		var ret = false;
		for(var i= -1; i <= 1; i++){
			for(var j= -1; j <= 1; j++){
				if(i==0 && j==0){
				}else if(this.kBoardWidth > (piece.column + i) && (piece.column + i) >= 0 &&
						this.kBoardHeight > (piece.row + j)  && (piece.row + j) >= 0){
					if(this.gCells[piece.column + i][piece.row + j].BAtack == 0 && team == 'W'){

						this.pieceJudge(parseInt(piece.column) + i, parseInt(piece.row) + j ,team,style);
						var pieceW = this.findPiece(parseInt(piece.column) + i, parseInt(piece.row) + j);
						if(pieceW == null || pieceW.team == 'B'){
							ret = true;

						}
					}else if(this.gCells[piece.column + i][piece.row + j].WAtack == 0 && team == 'B'){

						this.pieceJudge(parseInt(piece.column) + i, parseInt(piece.row) + j ,team,style);
						var pieceB = this.findPiece(parseInt(piece.column) + i, parseInt(piece.row) + j);
						if(pieceB == null || pieceB.team == 'W'){
							ret = true;

						}
					}
				}
			}
		}
		return ret;
	},
	pieceJudge: function(col, row, team, style){
		var ret = false;
		eval("this.gCells[col][row]." + team + "Atack = 1;");

		var destPiece = this.findPiece(col, row);
		if (destPiece === "undefined" || destPiece === null) {
			this.gMoveAreaCells.push(this.gCells[col][ row ]);
			this.fillBack( this.gCells[col][ row], style);
		}else{
			this.atackArea(destPiece, team, style);
			ret = true;
		}
		return ret;
	},
	atackArea: function(destPiece, team, style){
		var ret = false;
		if (destPiece === undefined || destPiece === null) {
		}else{
			if(destPiece.team != team){
				this.gMoveAreaCells.push(this.gCells[destPiece.column][destPiece.row]);
				this.fillBack( this.gCells[destPiece.column][destPiece.row], style);
				this.drawPiece(destPiece);
				ret = true;
			}
		}
		return ret;
	},
	movePiece:function(col, row){
		var piece = this.gSelectedPiece;
		
		var pieceColTemp = this.gSelectedPiece.column.toString();
		var pieceRowTemp = this.gSelectedPiece.row.toString();
		var selectePieceTemp = this.gSelectedPiece;
		var targetCell = this.findFromMoveArea(col, row);
		var check = false;
		if (targetCell === undefined || targetCell === null) {
			this.selected = false;
		}else if(this.gSelectedPiece.column == col && this.gSelectedPiece.row == row){
			this.selected = false;
		}else{
			this.viewRefresh();
			
			if(this.checkMateSimu(selectePieceTemp, col, row)){
				//自分自身のチームのチェック
				alert("checkMate");
			}else{
				var targetPiece = this.findPiece(col, row);
				if ( targetPiece === undefined || targetPiece === null) {
				}else{
					targetPiece.live = 0;
				}
				selectePieceTemp.row = row;
				selectePieceTemp.column = col;
				this.turnChange();
				this.viewRefresh();
				var check = this.atackJudge(this.turn, piece);
				
				var data = {
					pieces: this.gPieces,
					check: check
				}
				this.selected = false;
				this.gMoveAreaCells = new Array();
				this.socketio.emit("pieceMove", data);
				return;
			}

		}
		
		
		this.viewRefresh();
		/*
		if(check){
			alert("CheckMate" + this.turn);
		}
		*/
		return;
	},
	findFromMoveArea: function(col, row){
		var ret = null;
		for(var i=0; i < this.gMoveAreaCells.length; i++){
			if(this.gMoveAreaCells[i].column == col && this.gMoveAreaCells[i].row == row){
				return this.gMoveAreaCells[i];
			}
		}
		return ret;
	},
	turnChange: function(){
		if(this.turn == 'W'){
			this.turn = 'B';
		}else{
			this.turn = 'W';
		}
	},
	viewRefresh: function(){
		this.selected = false;
		this.gMoveAreaCells = new Array();
		//背景の塗りつぶし
	    for (var i = 0; i < this.kBoardWidth; i++) {
	    	for (var j = 0; j < this.kBoardHeight; j++ ) {
	    		this.fillBack( this.gCells[i][j], this.gCells[i][j].style);
	    	}
	    }
	    this.drawPieces();
	    this.viewTurn();
	},
	atackAreaRefresh: function(){
		var wTargetPices = this.gPieces.white;
		var bTargetPices = this.gPieces.black;

		for(var i=0; i< this.kBoardWidth; i++){
			for(var j=0; j< this.kBoardHeight; j++){
				this.gCells[i][j].WAtack = 0;
				this.gCells[i][j].BAtack = 0;
			}
		}
		for(var k=0; k < wTargetPices.length; k++){
			if(wTargetPices[k].live == 1){
				this.selectPiece(wTargetPices[k], wTargetPices[k].team, true);
			}
		}
		for(var l=0; l < wTargetPices.length; l++){
			if(bTargetPices[l].live == 1){
				this.selectPiece(bTargetPices[l], bTargetPices[l].team, true);
			}
		}
		this.gMoveAreaCells = new Array();
		this.gSelectedPiece={};
		this.selected = false;
	},
	viewAtackArea: function(team, show){
		this.atackAreaRefresh();
		var style = 'rgb(0, 191, 255)';
		if(show == false){
			style = null;
		}else if(team == 'B'){
			style = 'rgb(114, 252, 0)';
		}
		for(var i=0; i < this.kBoardWidth; i++){
			for(var j=0; j < this.kBoardHeight; j++){
				if(eval("this.gCells[i][j]." + team + "Atack == 1")){
					this.fillBack( this.gCells[i][j], style);
					/*
					if(team == 'W'){
						this.fillBack( this.gCells[i][j], style);
					}else{
						this.fillBack( this.gCells[i][j], style);
					}
					*/
				}
			}
		}
		this.drawPieces();
	},
	checkMateCheck: function(team){
		var ret = false;
		var pieces = []
		var targetPiece;
		if(team == 'W'){
			pieces = this.gPieces.white;
		}else{
			pieces = this.gPieces.black;
		}
		targetPiece = this.findKing(pieces);
		if(team == 'W'){
			if(this.gCells[targetPiece.column][targetPiece.row].BAtack == 1){
				ret = true;
			}
		}else{
			if(this.gCells[targetPiece.column][targetPiece.row].WAtack == 1){
				ret = true;
			}
		}
		return ret;
	},
	atackJudge: function(team, checkPiece){
		var ret = false;
		if(this.checkMateCheck(this.turn)){
			var targetPieces = this.gPieces.white;
			if(team == 'B'){
				targetPieces = this.gPieces.black;
			}
			var king = this.findKing(targetPieces);
			
			if(this.drawKArea(king, king.team, null)){
				//逃げれる
				return true;
			}else{
				var escapeArea = this.findEscape(king, checkPiece);
				var escapable = false;
				for(var i=0; i < targetPieces.length; i++){
					this.gMoveAreaCells = new Array();
					this.selectPiece(targetPieces[i], team, true);
					for(var j=0; j < escapeArea.length; j++){
						for(var k=0; k < this.gMoveAreaCells.length; k++){
							if(escapeArea[j].column == this.gMoveAreaCells[k].column &&
									escapeArea[j].row == this.gMoveAreaCells[k].row){
									
								if(this.checkMateSimu(targetPieces[i], escapeArea[j].column ,escapeArea[j].row) == false){
									escapable = true;
									return true;
								}
							}
							
						}
					}
				}
				if(escapable == false){
				    /*
					alert("loose" + this.turn);
					if(this.turn == 'W'){
						this.bWin += 1;
					}else{
						this.wWin += 1;
					}
					this.viewWin();
					*/
					this.turn = "S";
					var data = {
						team: this.myTeam,
						pieces: this.gPieces
					}
					this.socketio.emit("win", data);
				}
			}
			//if(this.drawKArea(piece, team, style
		}
		return ret;
	},
	findKing: function(targetPieces){
		var ret = null;
		for(var i=0; i < targetPieces.length; i++){
			if(targetPieces[i].role == 'K'){
				ret = targetPieces[i];
			}
		}
		return ret;
	},
	findEscape: function(king, checkPiece){
		var ret = new Array();
		ret.push(this.gCells[checkPiece.column][checkPiece.row]);
		if(checkPiece.role == 'L' || checkPiece.role == 'B' || checkPiece.role == 'Q'){
			var colAngle = '+';
			var rowAngle = '+';
			if(king.column < checkPiece.column){
				colAngle = '-';
			}else if(king.column == checkPiece.column){
				colAngle = '+0*';
			}
			if(king.row < checkPiece.row){
				rowAngle = '-';
			}else if(king.row == checkPiece.row){
				rowAngle = '+0*';
			}
			
			var i = 1;
			while(true){
				if(colAngle != '+0*'){
					if(eval("checkPiece.column" + colAngle + "i != king.column")){
						eval("ret.push(this.gCells[checkPiece.column" + colAngle + "i][checkPiece.row" + rowAngle + "i])");
					}else{
						break;
					}
				}else{
					if(eval("checkPiece.row" + rowAngle + "i != king.row")){
						eval("ret.push(this.gCells[checkPiece.column" + colAngle + "i][checkPiece.row" + rowAngle + "i])");
					}else{
						break;
					}
				}
				i++;
			}
		}
		return ret;
	},
	checkMateSimu: function(movePiece, col, row){
		var ret = false;
		var pieceColTemp = movePiece.column;
		var pieceRowTemp = movePiece.row;
		
		if(movePiece.live == 0){
			return ret;
		}
		
		var targetPiece = this.findPiece(col, row);
		if ( targetPiece === undefined || targetPiece === null) {
		}else{
			targetPiece.live = 0;
		}
		movePiece.column = col;
		movePiece.row = row;
		this.atackAreaRefresh();
		

		if(this.checkMateCheck(movePiece.team)){
			ret = true;
		}
		movePiece.row = pieceRowTemp
		movePiece.column = pieceColTemp;
			if ( targetPiece === undefined || targetPiece === null) {
		}else{
			targetPiece.live = 1;
		}
		return ret;	
	}
});

var Cell = Object.subClass({
	column:0,
	row:0,
	style:'rgb(150,150,150)',
	WAtack:0,
	BAtack:0,
	init:function(column, row, style){
		this.column = column;
		this.row = row;
		this.style = style;
	}
});

var Piece = Object.subClass({
	column:0,
	row:0,
	role:'',
	live:1,
	team:0,
	init:function(column, row, role, team){
		this.column = column;
	this.row = row;
		this.role = role;
		this.team = team;
	}
});