Monday, August 6, 2012

"Baghchal"[Tiger and Goat] Project Source code Download


             Baghchal is a traditional board game of Nepal. It is quite simple to setup and play. The board is drawn by a combination of horizontal, vertical, and slanting lines. Each intersecting point can hold a piece, a tiger or a goat. The pieces can only move one step along the lines, except for the case in which a tiger can eat a goat.
The game is played between two players, one represents tiger, four in number, and the other represents goats, twenty in number to start with. The tiger can eat goats by jumping above it, while the goats tries to limit the movement of a tiger.
This is a javascript version of the game, which can be played on the web browser

Game Explanation.


At the start of the game all four tigers are placed on the four corners of the grid, facing the center. All goats start off the board.
The pieces must be put at the intersections of the board lines and moves follow these lines.
The player controlling the goats moves first by placing a goat onto a free intersection on the board. Then it is the tigers' turn. One tiger is then moved to an adjacent position along the lines that indicate the valid moves. Moves are alternate between players.
Tigers capture goats by jumping over them to an adjacent free position. Goats cannot move until all 20 have been put on the board.
The tigers must move according to these rules:
1.    They can start capturing goats any moment after the match has started.
2.    They can capture only one goat at a time.
3.    They can jump over a goat in any direction, but it must be to an adjacent intersection following any of the lines drawn on the board.
4.    A tiger cannot jump over another tiger.
The goats must move according to these rules:
1.    They must leave the board when captured.
2.    They can not jump over the tigers or other goats.
3.    They can only move after all 20 have been put on the board.
The tigers win once they have captured five goats. Goats try to avoid being captured (jumped over) and they win by blocking the tigers' moves till they are unable to move.


Source Code:
 //save as main.html
<html>
<head>
<script type ="text/javascript" src = "ai.js"></script>
<script type = "application/x-javascript" src = "game.js"></script>
</head>

<body >
<table>
<tbody align="center">
<tr>
<canvas id="canvas" width="500" height="500" onmousedown="clickBoard()" onmouseup="mouseup()"></canvas>

<td>
<table border="3px" width="240px" style="position: absolute; left: 500px; top: 30px; padding: 5px;">
<tbody align="center">
<tr><td><h2>Baghchal</h2></td></tr>

<tr><td><button id="newGame1" onclick="game(2)">Computer Vs Human</button></td></tr>
<tr><td><button id="newGame2" onclick = "game(1)"> Human Vs Human</button></td></tr>
<tr><td>Move:<input type="text" id="turnof" value="Goat"></input></td></tr>
<tr><td>Goats Remaining:<input type="text" id="onhand" value="20"></input></td></tr>
<tr><td>Goats Eaten:<input type="text" id="eaten" value="0"></input></td></tr>

</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<script language="JavaScript1.2">
<!--
// Detect if the bwhichPieceXser is IE or not.
// If it is not IE, we assume that the bwhichPieceXser is NS.
var IE = document.all?true:false
// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE)
// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;

// Temporary variables to hold mouse x-y pos.s
mouseX = 0
mouseY = 0

// Main function to retrieve mouse x-y pos.s
function getMouseXY(e) {
if (IE) { // grab the x-y pos.s if bwhichPieceXser is IE
mouseX = event.clientX document.body.scrollLeft
mouseY = event.clientY document.body.scrollTop
}
else { // grab the x-y pos.s if bwhichPieceXser is NS
mouseX = e.pageX
mouseY = e.pageY
}

mouseX = mouseX - canvas.offsetLeft;
mouseY = mouseY - canvas.offsetTop;

// catch possible negative values in NS4
if (mouseX < 0){mouseX = 0}
if (mouseY < 0){mouseY = 0}

return true
}
//-->
</script>
<script type ="text/javascript">game(2)</script>
</body>
</html>
//save as game.js
dim = 100;
tigerRadius = 25;
goatRadius = 15;
whichPieceX = -1;
whichPieceY = -1;
leftPad = 15;
topPad = 15;

function game(n) {
pieces = new Array(5);
for (i = 0; i < pieces.length; i) {
pieces[i] = new Array(5);
for (j = 0; j < pieces.length; j) {
pieces[i][j] = 0;
}
}

pieces[0][0] = 1;
pieces[0][4] = 1;
pieces[4][0] = 1;
pieces[4][4] = 1;
whichGame = n;
goatsEaten = 0;
goatsOnhand = 20;
goatOnhand = 0;
goatOnhandRow = 0;
goatOnhandCol = 0;
tigerOnhand = 0;
tigerOnhandRow = 0;
tigerOnhandCol = 0;
turn = 2;

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
drawBoard();
drawPieces();
}

function drawLine(x1, y1, x2, y2) {
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}

//Draw the board
function drawBoard() {
boardLeft = leftPad tigerRadius;
boardTop = topPad tigerRadius;
ctx.fillStyle="orange";
ctx.fillRect(boardLeft-tigerRadius, boardTop-tigerRadius, dim*4 tigerRadius*2, dim*4 tigerRadius*2);
ctx.strokeStyle="black";
ctx.strokeRect(boardLeft, boardTop, dim*4, dim*4);
ctx.moveTo(boardLeft, boardTop);
for (i = 0; i < 5; i) {
drawLine(boardLeft, boardTop i * dim, boardLeft dim *4, boardTop i * dim);
drawLine(boardLeft i * dim, boardTop, boardLeft i * dim, boardTop dim *4);
}
drawLine(boardLeft, boardTop, boardLeft dim*4, boardTop dim*4);
drawLine(boardLeft dim*4, boardTop, boardLeft, boardTop dim*4);
ctx.moveTo(boardLeft, boardTop dim*2);
ctx.lineTo(boardLeft dim*2, boardTop);
ctx.lineTo(boardLeft dim*4, boardTop dim*2);
ctx.lineTo(boardLeft dim*2, boardTop dim*4);
ctx.lineTo(boardLeft, boardTop dim*2);
ctx.stroke();


}

function drawPieces() {
for (i = 0; i < 5; i) {
for (j = 0; j < 5; j) {
ctx.beginPath();
if (pieces[i][j]==1) {
ctx.arc(boardLeft dim*j, boardTop dim*i, tigerRadius,0, 2*Math.PI, true);
ctx.fillStyle = "rgba(200,0,0,0.96)";
}
else if (pieces[i][j]==2) {
ctx.arc(boardLeft dim*j, boardTop dim*i, goatRadius, 0, 2*Math.PI, true);
ctx.fillStyle = "rgba(10,200,100,0.96)";
}
ctx.fill();
}
}
eaten.value = goatsEaten;
onhand.value = goatsOnhand;
if (turn==2) {
turnof.value="Goat";
}
else if (turn==1) {
turnof.value="Tiger";
}
else {
turnof.value="";
}

}
function mouseup() {
drawBoard();
drawPieces();
if (tigerOnhand!=0 || goatOnhand!=0) {
clickBoard();
}
}
function clickBoard() {
// check which piece is clicked;
for (i = 0; i < 5; i) {
for (j = 0; j < 5; j) {
posX = leftPad tigerRadius j * dim;
posY = topPad tigerRadius i * dim;
if ((mouseX>posX-tigerRadius) && (mouseX<posX tigerRadius) && (mouseY>posY-tigerRadius) && (mouseY<posY tigerRadius)) {
whichPieceX = i;
whichPieceY = j;
}
}
}

// check for the game turn, make a move, && change the turn
if (whichPieceX>-1) {

if (whichGame==1 || whichGame==2) {
if (turn==2 && goatsOnhand>0 && pieces[whichPieceX][whichPieceY]==0) {
goatsOnhand = goatsOnhand-1;
pieces[whichPieceX][whichPieceY]=2;
turn = 1;

}
else if (turn==2 && goatsOnhand==0 && pieces[whichPieceX][whichPieceY]==2) {
goatOnhand = 1;
goatOnhandRow = whichPieceX;
goatOnhandCol = whichPieceY;
}
else if (turn==2 && goatOnhand==1 && pieces[whichPieceX][whichPieceY]==0) {
if (validmove(goatOnhandRow, goatOnhandCol, whichPieceX, whichPieceY)==1) {
pieces[whichPieceX][whichPieceY]=2;
pieces[goatOnhandRow][goatOnhandCol]=0;
goatOnhand = 0;
turn = 1;
}
}
}

if (whichGame==1 || whichGame==3) {
if (turn==1 && pieces[whichPieceX][whichPieceY]==1){
tigerOnhand = 1;
tigerOnhandRow = whichPieceX;
tigerOnhandCol = whichPieceY;
}


if (turn==1 && tigerOnhand==1 && pieces[whichPieceX][whichPieceY]==0) {
if (validmove(tigerOnhandRow, tigerOnhandCol, whichPieceX, whichPieceY)==1) {
pieces[whichPieceX][whichPieceY]=1;
pieces[tigerOnhandRow][tigerOnhandCol]=0;
tigerOnhand = 0;
turn = 2;
}
else if (validjump(tigerOnhandRow, tigerOnhandCol, whichPieceX, whichPieceY)==1) {
pieces[whichPieceX][whichPieceY]=1;
pieces[tigerOnhandRow][tigerOnhandCol]=0;
pieces[(whichPieceX tigerOnhandRow)/2][(whichPieceY tigerOnhandCol)/2]=0;
tigerOnhand = 0;
turn = 2;
goatsEaten = goatsEaten 1;
}
}
}
}
if (whichGame==2 && turn==1) {
bestMoveTiger();
}

// check piece code end

// at last set the clicked piece to none



whichPieceX = -1;
whichPieceY = -1;
drawBoard();
drawPieces();
if (whichGame!=0) {
winner = checkWinner();
if (winner==1) {
alert("Tiger Wins");
whichGame = 0;
}
else if (winner==2) {
alert("Goat Wins");
whichGame = 0;
}
}
}

function checkWinner() {
if (goatsEaten>5) {
return 1;
}
for(r1=0;r1<5; r1){
for (c1=0; c1<5; c1) {
if (pieces[r1][c1]==1) {
for (r2=0; r2<5; r2) {
for (c2=0; c2<5; c2) {
if (pieces[r2][c2]==0) {
if (validmove(r1, c1, r2, c2)==1 || validjump(r1, c1, r2, c2)==1) {
return 0;
}
}
}
}
}
}
}
return 2;
}
//save as ai.js
function validmove(r1, c1, r2, c2) {
// no check for pieces here...do it manually
// this is useful because valimove is used for tiger, goat, && ai moves

if (distance(r1, c1, r2, c2)<2) {
if ((r1 c1)%2==0) {
return 1;
} else {
if (distance(r1, c1, r2, c2)==1) {
return 1;
}
}
}
return 0;
}

function validjump(r1, c1, r2, c2) {
// (midRow, midCol) should be a goat; two end points can have any piece || none so check it manually while using validjump
midRow = (r1 r2)/2;
midCol = (c1 c2)/2;
if (distance(r1, c1, midRow, midCol)==0.5*distance(r1, c1, r2, c2)) {
if (isGoat(midRow, midCol) && validmove(r1, c1, midRow, midCol) && validmove(midRow, midCol, r2, c2)) {
return 1;
}
}
}

function bestMoveTiger() {
maxPts = 0;
maxr1 = 0; maxc1 = 0; maxr2 = 0; maxc2 = 0;
for(r1=0; r1<5; r1) {
for(c1=0; c1<5; c1) {
for(r2=0; r2<5; r2) {
for(c2=0; c2<5; c2) {
pts = 0;
if (isTiger(r1, c1) && isBlank(r2, c2)) {
if (validjump(r1, c1, r2, c2)==1) {
pts = pts 1000;
// pts = pts tigerSecondary(r1, c1, r2, c2);
}
if (validmove(r1, c1, r2, c2)==1) {
pts = pts 20;
// pts = pts tigerSecondary(r1, c1, r2, c2);
}
if (pts>maxPts) {
maxr1 = r1;
maxc1 = c1;
maxr2 = r2;
maxc2 = c2;
maxPts = pts;
}
// implement random if you wish for equal ones.
}
}
}
}
}

if (maxPts!=0) {
pieces[maxr1][maxc1] = 0;
pieces[maxr2][maxc2] = 1;
if (maxPts>900) {
pieces[(maxr1 maxr2)/2][(maxc1 maxc2)/2]=0;
goatsEaten = goatsEaten 1;
}
turn = 2;
}
}

// function tigerSecondary(r1, c1, r2, c2) {
// tmp = 0;
// for(i=r2-2; i<r2 3; i=i 2) {
// for(j=c2-2; j<c2 3; j=j 2) {
// if(validjump(r2, c2, i, j)==1 && isBlank(i, j)) {
// tmp = tmp 100;
// }
// }
// }
// for(i=r1-2; i<r1 3; i=i 2) {
// for(j=c1-2; j<c1 3; j=j 2) {
// if(validjump(i, j, r1, c1)==1 && isTiger(i, j)) {
// tmp = tmp 50;
// }
// }
// }
// if((r2 c2)%2==0) {
// tmp = tmp 10;
// }
// if(r2==0 || r2==4 || c2==0 || c2==4) {
// tmp = tmp 4;
// }

// tmp = tmp Math.abs(Math.pow(r2-2, 3) Math.pow(c2-2, 3));
// return tmp;
// }


function isTiger(row, col) {
if (Math.round(row)==row && Math.round(col)==col) {
if ((row>=0 && row <5) && (col>=0 && col<5) && pieces[row][col]==1) {
return true;
}
}
}

function isGoat(row, col) {
if (Math.round(row)==row && Math.round(col)==col) {
if ((row>=0 && row <5) && (col>=0 && col<5) && pieces[row][col]==2) {
return true;
}
}
}

function isBlank(row, col) {
if (Math.round(row)==row && Math.round(col)==col) {
if ((row>=0 && row <5) && (col>=0 && col<5) && pieces[row][col]==0) {
return true;
}
}
}


function distance(x1, y1, x2, y2) {
return (Math.sqrt(Math.pow((x2-x1),2) Math.pow((y2-y1), 2)));
}

4 comments: