commit c36b91b8f4a74fbca1cdb5eaae49c99b53c37430 Author: Christopher Ramey Date: Tue Aug 28 04:55:45 2012 +0000 Initial commit of shogi javascript library diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24798dd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.compiled.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ca2da75 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2012, Christopher Ramey +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d205028 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +CLOSURE_PATH=~/closure/compiler.jar +VERSION=1.0 + +shogi-${VERSION}.compiled.js: shogi.js + java -jar ${CLOSURE_PATH} --js $^ --js_output_file $@ + +clean: + rm shogi-*.compiled.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..7539e48 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +shogi.js +======== + +shogi.js is a javascript library for managing shogi games. It's intended +as the display end of a web-based pickup shogi game system. diff --git a/shogi.js b/shogi.js new file mode 100644 index 0000000..19f76cd --- /dev/null +++ b/shogi.js @@ -0,0 +1,357 @@ +/** + @license Copyright (c) 2012, Christopher Ramey | http://github.com/cramey/shogi/LICENSE" +*/ +var Shogi = { + KING : 0, + ROOK : 1, + BISHOP : 2, + GOLD_GENERAL : 3, + SILVER_GENERAL : 4, + KNIGHT : 5, + LANCE : 6, + PAWN : 7, + PROMOTED_ROOK : 9, + PROMOTED_BISHOP : 10, + PROMOTED_SILVER : 12, + PROMOTED_KNIGHT : 13, + PROMOTED_LANCE : 14, + PROMOTED_PAWN : 15, + + desc_king : [ + 'reigning', 'challenging' + ], + + desc_peice : [ + 'King', 'Rook', 'Bishop', 'Gold General', + 'Silver General', 'Knight', 'Lance', 'Pawn' + ], + + peicePromoted : function(n) + { + return (n & 8) != 0; + }, + + peiceCanPromote : function(b, l){ + var peice = b[l]; + if(peice == -1){ return false; } + + var pe = peice & 15; + if(pe < 1 || pe > 7){ return false; } + + var player = this.peicePlayer(peice); + if(player == 0 && l > 26){ return false; } + + if(player == 1 && l < 54){ return false; } + + return true; + }, + + peicePlayer : function(n) + { + return (n & 16) >> 4; + }, + + peiceName : function(n) + { + return this.desc_peice[n & 7]; + }, + + peiceMoves : function(b, l) + { + var peice = b[l]; + var player = this.peicePlayer(peice); + + var moves = []; + + switch(peice & 15){ + case this.KING: + var i = l + 9; + if(i <= 80 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 9; + if(i >= 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 1; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 1; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 8; + if(i <= 80 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 10; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 10; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 8; + if(i >= 0 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + break; + + + case this.GOLD_GENERAL: + case this.PROMOTED_SILVER: + case this.PROMOTED_PAWN: + case this.PROMOTED_LANCE: + case this.PROMOTED_KNIGHT: + var i = l + 9; + if(i <= 80 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 9; + if(i >= 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 1; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 1; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + if(player){ + i = l + 8; + if(i <= 80 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 10; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + } else { + i = l - 10; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 8; + if(i >= 0 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + } + break; + + + case this.KNIGHT: + var i = l + (player ? 19 : -19); + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + (player ? 17 : -17); + if(i >= 0 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + break; + + + case this.LANCE: + if(player){ + for(var i = l + 9; i <= 80; i += 9){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + } else { + for(var i = l - 9; i >= 0; i -= 9){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + } + break; + + + case this.PROMOTED_ROOK: + var i = l - 10; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 8; + if(i >= 0 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 8; + if(i <= 80 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 10; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + case this.ROOK: + for(var i = l - 9; i >= 0; i -= 9){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l - 1; i % 9 != 8; i--){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l + 1; i % 9 != 0; i++){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l + 9; i <= 80; i += 9){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + break; + + + case this.PROMOTED_BISHOP: + var i = l + 9; + if(i <= 80 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 9; + if(i >= 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 1; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 1; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + case this.BISHOP: + for(var i = l - 8; i >= 0 && i % 9 != 0; i -= 8){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l - 10; i >= 0 && i % 9 != 8; i -= 10){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l + 8; i <= 80 && i % 9 != 8; i += 8){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + + for(var i = l + 10; i <= 80 && i % 9 != 0; i += 10){ + if(b[i] == -1){ moves.push(i); } + else if(this.peicePlayer(b[i]) != player){ + moves.push(i); break; + } else { break; } + } + break; + + + case this.PAWN: + var i = l + (player ? 9 : -9); + if(i >= 0 && i <= 80 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + break; + + + case this.SILVER_GENERAL: + i = l + (player ? 9 : -9); + if(i >= 0 && i <= 80 && (b[i] == -1 || this.peicePlayer(b[i]))){ + moves.push(i); + } + + var i = l - 10; + if(i >= 0 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l - 8; + if(i >= 0 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 8; + if(i <= 80 && i % 9 != 8 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + + i = l + 10; + if(i <= 80 && i % 9 != 0 && (b[i] == -1 || this.peicePlayer(b[i]) != player)){ + moves.push(i); + } + break; + } + + return moves; + }, + + peiceDescription : function(n) + { + var pl = (n & 16) >> 4; + var pe = n & 7; + + return (this.peicePromoted(n) ? 'Promoted ' : '') + + this.peiceName(n) + + (pe == this.KING ? ' (' + this.desc_king[pl] + ')' : ''); + }, + + boardStandard: function() + { + return [ + 22,21,20,19,16,19,20,21,22, + -1,18,-1,-1,-1,-1,-1,17,-1, + 23,23,23,23,23,23,23,23,23, + -1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1, + 7, 7, 7, 7, 7, 7, 7, 7, 7, + -1, 1,-1,-1,-1,-1,-1, 2,-1, + 6, 5, 4, 3, 0, 3, 4, 5, 6 + ]; + } +};