03-07-2013, 02:08 PM | #1 |
Junior Member
Posts: 1
Karma: 19348
Join Date: Mar 2013
Device: Kindle Paperwhite
|
WAF Senet Game for Kindle touch/PW
While playing around to learn about the WAF on the Kindle PW, I implemented an old Egyptian board game called Senet, see e.g. http://en.wikipedia.org/wiki/Senet
Install by extracting into extensions folder and start with the Kindle Launcher. Tested no the PW, should work on the touch as well. Have fun. |
03-07-2013, 03:13 PM | #2 |
( ͡° ͜ʖ ͡°){ʇlnɐɟ ƃǝs}Tır
Posts: 6,586
Karma: 6299991
Join Date: Jun 2012
Location: uti gratia usura (Yao ying da ying; Mo ying da yieng)
Device: PW-WIFI|K5-3G+WIFI| K4|K3-3G|DXG|K2| Rooted Nook Touch
|
nice one - TESTED ON A TOUCH (5.3.2)
Last edited by twobob; 03-08-2013 at 11:44 AM. Reason: revision info |
Advert | |
|
03-08-2013, 11:43 AM | #3 |
( ͡° ͜ʖ ͡°){ʇlnɐɟ ƃǝs}Tır
Posts: 6,586
Karma: 6299991
Join Date: Jun 2012
Location: uti gratia usura (Yao ying da ying; Mo ying da yieng)
Device: PW-WIFI|K5-3G+WIFI| K4|K3-3G|DXG|K2| Rooted Nook Touch
|
How about if I publicly grovel for the source code. would that help?
*does grovelling* I am reticent to index something I don't see the source for. Last edited by twobob; 03-09-2013 at 01:04 PM. |
03-08-2013, 10:32 PM | #4 |
Guru
Posts: 608
Karma: 1588610
Join Date: Jan 2012
Device: Kindle Scribe
|
|
03-09-2013, 06:39 AM | #5 |
( ͡° ͜ʖ ͡°){ʇlnɐɟ ƃǝs}Tır
Posts: 6,586
Karma: 6299991
Join Date: Jun 2012
Location: uti gratia usura (Yao ying da ying; Mo ying da yieng)
Device: PW-WIFI|K5-3G+WIFI| K4|K3-3G|DXG|K2| Rooted Nook Touch
|
Okay Ill repost it myself then
Code:
<html> <head> <title>Senet Game</title> <meta charset="UTF-8" /> <script type="text/javascript"> var xSize; var ySize; var xOffset = 10; var yOffset = 10; var gameState = ""; var currentDice = -1; var myCanvas; var userTurn = false; var longGame = false; var coefficients = [0.0625, 0.25, 6/16, 0.25, 0.0625]; var imageAnch = new Image(); var imageBaw = new Image(); var imageMw = new Image(); var imageRa = new Image(); var imageUdjat = new Image(); var imageZp = new Image(); imageAnch.src = "anchs.png"; imageBaw.src = "baws.png"; imageMw.src = "mws.png"; imageRa.src = "ras.png"; imageUdjat.src = "udjats.png"; imageZp.src = "zps.png"; function init(){ clock(); setInterval(clock,1000); } function throwDice() { var result = 0; for( var i=0; i<4; i++) result += Math.round(Math.random()); return result; } function moveState(state, index, dice) { var newIndex; var newState = state; //console.log("moveState: " + state + " index " + index +" dice " + dice); switch (dice) { case 0: newIndex = index + 6; break; // and you get another throw case 1: newIndex = index + 1; break; case 2: newIndex = index + 2; break; case 3: newIndex = index + 3; break; case 4: newIndex = index + 4; break; // and you get another throw } // console.log("newIndex: " + newIndex); // On the last fields you need to have the right throw if( index>26 ) { if( index === 29 || newIndex === 30 ) { newState=newState.substr(0, index)+"0"+newState.substr(index+1); return newState; } else { return ""; } } if (newIndex > 29) return ""; if (newIndex === 26 ) // bad field newIndex = 14; // console.log("A"); if(state[index]==state[newIndex]) // can't move onto yourself return ""; if (newIndex < index) { // actually newIndex == 14 here var savedField = state[newIndex]; newState=newState.substr(0, newIndex) + state[index]+newState.substr(newIndex+1); newState=newState.substr(0, index) + savedField + newState.substr(index+1); return newState; } // console.log("B"); // moving over group of 3? var count = 0; for (var i = index; i < newIndex; i++) { if( (state[i] === state[index]) || (state[i] === "0")) { count = 0; continue; } count++ if (count === 3) return ""; } // console.log("C"); if(state[newIndex] === "0") { // moving onto empty field newState=newState.substr(0, newIndex) + state[index] + newState.substr(newIndex+1); newState=newState.substr(0, index)+"0"+newState.substr(index+1); // console.log("New state:" + newState); return newState; } // moving onto enemy field if(state[newIndex] === state[newIndex-1] || state[newIndex] === state[newIndex+1]) // two adjacent enemy pieces return ""; //console.log("D"); if(newIndex > 26 || newIndex === 25) // enemy on safe field? return ""; var savedField = state[newIndex]; newState=newState.substr(0, newIndex) + state[index] + newState.substr(newIndex+1); newState=newState.substr(0, index) + savedField + newState.substr(index+1); // console.log("New state:" + newState); return newState; } function generateMoves(who, state, dice) { var moves=new Array(); for (var i = 0; i < state.length; i++) { if ( state[i] == "0" ) continue; if(state[i] === who) { var newState = moveState(state, i, dice); if (newState !== "") moves.push(newState); } } return moves; } // level is depth of total moves, who means who moves next function evaluateStrength(state, level, who) { var countWhite = 0; var countBlack = 0; var strength = 0; var pFactor = 1; // console.log("Evaluating state Level: " + level + " state: " + state + " who: "+ who); if (level > 0) { var averageStrength =0; for (var d = 0; d < 5; d++ ) { var bestStrength = (who === "1")? 1000 : -1000; var possibleMoves = generateMoves(who, state, d); if( possibleMoves.length < 1){ // No moves possible, other's turn possibleMoves.push(state); } for (var i=0; i< possibleMoves.length; i++) { var whoNext = (who === "1") ? "2" : "1"; if( d===0 || d=== 4) whoNext = who; strength = evaluateStrength(possibleMoves[i], level - 1, whoNext); if (who === "1") { bestStrength = (strength < bestStrength)? strength:bestStrength; } else { bestStrength = (strength < bestStrength)? bestStrength:strength; } // console.log("Level: " + level + " dice: " + d + " state: " + possibleMoves[i] + " strength: "+ strength + " bestStrength " + bestStrength); } averageStrength += bestStrength * coefficients[d]; } // console.log("Returning Level: " + level + " state: " + state + " strength: "+ averageStrength); return averageStrength; } for (var i = 0; i < state.length; i++) { if ( state[i] == "0" ) continue; if(state[i] === "2") { // White strength += i; if (i == 25 || i==27 || i== 28) // safe fields strength += Math.pow(i, pFactor); countWhite++; if (i < (state.length-1) && state[i+1] === "2" ) { strength += Math.pow(i, pFactor) * (countBlack/2 +1); i++; countWhite++; if (i < (state.length-1) && state[i+1] === "2" ) { strength += Math.pow(i, pFactor) * (countBlack/2 +1); i++; countWhite++; } continue; } } else { // Black strength -= i; if (i == 25 || i==27 || i== 28) // safe fields strength -= Math.pow(i, pFactor); countBlack++; if (i < (state.length-1) && state[i+1] === "1" ) { strength -= Math.pow(i, pFactor) * (countWhite/2 +1); i++; countBlack++; if (i < (state.length-1) && state[i+1] === "1" ) { strength += Math.pow(i, pFactor) * (countWhite/2 +1); i++; countBlack++; } continue; } } } if(longGame) { strength += (7-countWhite) * 100; strength -= (7-countBlack) * 100; } else { strength += (5-countWhite) * 100; strength -= (5-countBlack) * 100; } // console.log("State " + state + ": " +strength); return strength; } function prepareHumanTurn() { userTurn = false; updateStrength(); currentDice = throwDice(); // document.getElementById("dice").innerHTML="Dice: " + currentDice; showDice(currentDice); document.getElementById("notice").innerHTML="Your turn!"; var possibleMoves = generateMoves("2", gameState, currentDice); for (var i = 0; i < possibleMoves.length; i++) console.log("Your moves: " + possibleMoves[i]); if( possibleMoves.length < 1 ) { document.getElementById("notice").innerHTML="You cannot move!"; setTimeout(prepareComputerTurn, 3000) //wait two seconds before continuing return; } userTurn=true; } function showDice(d) { switch (d) { case 0: document.getElementById("dImage").src="dice0_320.png"; document.getElementById("dImage").alt="0"; break; case 1: document.getElementById("dImage").src="dice1_320.png"; document.getElementById("dImage").alt="1"; break; case 2: document.getElementById("dImage").src="dice2_320.png"; document.getElementById("dImage").alt="2"; break; case 3: document.getElementById("dImage").src="dice3_320.png"; document.getElementById("dImage").alt="3"; break; case 4: document.getElementById("dImage").src="dice4_320.png"; document.getElementById("dImage").alt="4"; break; } } function getComputerStrength() { var radios = document.getElementsByName('cstrength'); for (var i = 0, length = radios.length; i < length; i++) { if (radios[i].checked) { // alert(radios[i].value); return radios[i].value; } } return 1; } function prepareComputerTurn() { userTurn = false; currentDice = throwDice(); // document.getElementById("dice").innerHTML="Dice: " + currentDice; showDice(currentDice); console.log("My move: " + currentDice + "-------------------------------------"); document.getElementById("notice").innerHTML="My move..."; setTimeout(computerTurn, 2000) //wait five seconds before continuing } function computerTurn() { document.getElementById("notice").innerHTML="Thinking..."; var possibleMoves = generateMoves("1", gameState, currentDice); if( possibleMoves.length < 1 ) { document.getElementById("notice").innerHTML="Cannot move!"; setTimeout(prepareHumanTurn, 3000) //wait five seconds before continuing } var minStrength=1000; var minIndex =-1; for(var i = 0; i<possibleMoves.length; i++){ var strength; if( currentDice === 0 || currentDice === 4 ) strength = evaluateStrength(possibleMoves[i], getComputerStrength(), "1"); else strength = evaluateStrength(possibleMoves[i], getComputerStrength(), "2"); // console.log("State: " + possibleMoves[i] + ": " + strength); if(strength < minStrength){ minStrength = strength; minIndex = i; } } console.log("Choosing: " + possibleMoves[minIndex]); drawUpdatedState(myCanvas.getContext('2d'), gameState, possibleMoves[minIndex]); gameState = possibleMoves[minIndex]; if(gameState.indexOf("1") === -1){ document.getElementById("notice").innerHTML="I won!"; userTurn = false; return; } if (currentDice === 0 || currentDice === 4) { console.log("Computer gets another turn"); prepareComputerTurn(); return; } prepareHumanTurn(); } function drawPin(ctx, state, i) { // console.log("Drawing pin number " +i); ctx.strokeStyle="black"; ctx.lineWidth=3; ctx.beginPath(); if (state[i]=="2" ) ctx.fillStyle = "white"; else ctx.fillStyle = "black"; if (Math.floor(i/10) !== 1){ ctx.arc(xOffset + xSize/6 + (xSize/3) * Math.floor(i/10), yOffset + ySize - (ySize /20 + (ySize/10) * (i%10)), xSize/20, 0, 2*Math.PI, true); } else { ctx.arc(xOffset + xSize/6 + (xSize/3) * Math.floor(i/10), yOffset + ySize /20 + (ySize/10) * (i%10), xSize/20, 0, 2*Math.PI, true); } ctx.closePath(); ctx.stroke(); ctx.fill(); } function drawState(ctx, state) { if ( state.length != 30 ) alert("Illegal State: " + state); ctx.save(); console.log("DRAWING STATE " + state); ctx.strokeStyle="black"; ctx.lineWidth=3; for (var i = 0; i < state.length; i++) { if ( state[i] == "0" ) continue; drawPin(ctx, state, i); } ctx.restore(); } function drawPictureField(ctx, i) { if (i === 14) ctx.drawImage(imageAnch, xOffset + 1 + (xSize/3) * Math.floor(15/10), yOffset +1 + ySize-((ySize/10) * ((15%10)+1)), xSize/3.2, ySize/10.2-2); if (i === 25) ctx.drawImage(imageUdjat, xOffset + 1 + (xSize/3) * Math.floor(25/10), yOffset +1 + ySize-((ySize/10) * ((25%10)+1)), xSize/3.2, ySize/10.2-2); if (i === 26) ctx.drawImage(imageMw, xOffset + 1 + (xSize/3) * Math.floor(26/10), yOffset +1 + ySize-((ySize/10) * ((26%10)+1)), xSize/3.2, ySize/10.2-2); if (i === 27) ctx.drawImage(imageBaw, xOffset + 1 + (xSize/3) * Math.floor(27/10), yOffset +1 + ySize-((ySize/10) * ((27%10)+1)), xSize/3.2, ySize/10.2-2); if (i === 28) ctx.drawImage(imageZp, xOffset + 1 + (xSize/3) * Math.floor(28/10), yOffset +1 + ySize-((ySize/10) * ((28%10)+1)), xSize/3.2, ySize/10.2-2); if (i === 29) ctx.drawImage(imageRa, xOffset + 1 + (xSize/3) * Math.floor(29/10), yOffset +1 + ySize-((ySize/10) * ((29%10)+1)), xSize/3.2, ySize/10.2-2); } function drawUpdatedState(ctx, oldState, newState) { console.log("Updating state to " + newState); if ( oldState.length != 30 || newState.length != 30) alert("Illegal State: " + state); ctx.save(); for (var i = 0; i < oldState.length; i++) { ctx.fillStyle = "white"; if ( oldState[i] === newState[i] ) continue; //console.log("Doing something for " + i); if (Math.floor(i/10) !== 1) { ctx.fillRect(xOffset + 1 + (xSize/3) * Math.floor(i/10), yOffset +1 + ySize-((ySize/10) * ((i%10)+1)), xSize/3.1, ySize/10 - 4); } else { ctx.fillRect(xOffset + 1 + (xSize/3) * Math.floor(i/10), yOffset +1+ (ySize/10) * (i%10), xSize/3.1, ySize/10 - 4); } drawPictureField(ctx, i); if ( newState[i] === "0") continue; drawPin(ctx, newState, i); } ctx.restore(); } function mouseClick(e) { console.log("Position: " + e.pageX + ", " + e.pageY); var rect = myCanvas.getBoundingClientRect(); var fieldX = Math.floor((e.pageX-xOffset-rect.left)/(xSize / 3)); var fieldY = Math.floor((e.pageY-yOffset-rect.top)/(ySize / 10)); var field; if (fieldX !== 1) field = fieldX *10 + (9-fieldY); else field = fieldX *10 + fieldY; console.log("Field: " + fieldX + ", " + fieldY +" :" +field); if( !userTurn ) return; if( gameState[field] != "2" ) { document.getElementById("notice").innerHTML="Not your piece!"; return; } var newState = moveState(gameState, field, currentDice); if (newState === "") { document.getElementById("notice").innerHTML="Illegal Move!"; return; } drawUpdatedState(myCanvas.getContext('2d'), gameState, newState); gameState = newState; if(gameState.indexOf("2") === -1){ document.getElementById("notice").innerHTML="You won!"; userTurn = false; return; } if ( currentDice == 0 || currentDice == 4){ // Move twice prepareHumanTurn(); return; } prepareComputerTurn(); } function drawBoard() { console.log("Drawing board, game state:" + gameState); myCanvas = document.getElementById('canvas'); // myCanvas.setAttribute("width",window.innerWidth*1/3); // myCanvas.setAttribute("heights", window.innerHeight-4); var ctx = myCanvas.getContext('2d'); xSize = myCanvas.width-(2*xOffset); ySize = myCanvas.height - (2 * yOffset); ctx.save(); ctx.beginPath(); ctx.clearRect ( xOffset,yOffset,xSize, ySize); ctx.strokeStyle="black"; ctx.strokeRect(xOffset,yOffset,xSize, ySize); ctx.restore(); ctx.strokeStyle = "black"; // draw horizontal lines for( var i = 1; i < 10; i++) { ctx.moveTo(xOffset, yOffset + (ySize /10) * i); ctx.lineTo(xOffset + xSize, yOffset + (ySize/10) * i); } // draw vertical lines for (var i = 1; i < 3; i++) { ctx.moveTo(xOffset + (xSize/3)*i, yOffset); ctx.lineTo(xOffset + (xSize/3)*i, yOffset + ySize); } ctx.stroke(); ctx.restore(); // drawUpdatedState(ctx, "000000000000000000000000000000", gameState); for (var i = 0; i< 30; i++) drawPictureField(ctx, i); drawState(ctx, gameState); } function updateStrength() { var strength = evaluateStrength(gameState, 0); document.getElementById("score").innerHTML="Your strength: " + strength; } function showRules() { var v = document.getElementById("rules").getAttribute("hidden"); console.log("Attr: " + v); if(v === null) { document.getElementById("rules").setAttribute("hidden", true); document.getElementById("rules_button").innerHTML="Show Rules"; } else { document.getElementById("rules").removeAttribute("hidden"); document.getElementById("rules_button").innerHTML="Hide Rules"; } } function newGame() { longGame = false; gameState = "121212121200000000000000000000"; if(document.getElementById('duration_long').checked) { longGame = true; gameState = "121212121212120000000000000000"; } drawBoard(); myCanvas.addEventListener('click', mouseClick, false); prepareHumanTurn(); } </script> <style type="text/css"> #canvas { border: 1px solid black;} #board { float:left; top:10; width:400px; right:20; padding:10; } #controls { width:260px; top:10; padding:10px; float:left; text-align:center; } </style> </head> <body onload="newGame();"> <div id="title" text-align="center" width="600px"> <h1>Game of Senet</h1></div> <div id="board"> <canvas id="canvas" height=720 width=400></canvas> </div> <div id="controls"> <button onClick="newGame();">New Game</button> <p>Duration:<br> <input id="duration_short" type="radio" name="duration" value="short" checked> short <input id="duration_long" type="radio" name="duration" value="long"> long </p> <p> Computer strength: <br> <input id="strength_1" type="radio" name="cstrength" value="1" checked> 1 <input id="strength_2" type="radio" name="cstrength" value="2"> 2 <input id="strength_3" type="radio" name="cstrength" value="3"> 3 <br> <hr /> <br> <p id="score"> Your strength: 0</p> <p id="notice">Your Turn!</p> <p id="dice"> <img id="dImage" width="240" height="240" border="0" alt="Dice 0" src="dice0_320.png" title="Dice"/></p> </div> <div id="footer" style="clear:both;text-align:center;"> <button id="rules_button" onClick="showRules();">Show Rules</button> <div id="rules" style="text-align:left;" hidden> <p> Each player has 5 (short game) or 7 pawns (long game) on a board with 30 fields. Pieces move forward in a snake-like line. The goal is to get all your pieces off the board at the right upper corner.</p> <img id="dImage" width="200" height="320" border="0" alt="Dice 0" src="board.png" title="Dice"/> <p> To the lower right the result of throwing the "dice" is shown. The "dice" is actually 4 flattened sticks which have a black and a white side. Throwing 1, 2 or 3 black sticks means the player can mode one piece the same number of fields forward. If no black side faces upwards, the player can move 6 fields, and 4 if all black sides are up. In both cases, the player may cast the sticks a second time. Note that it is far more likely to throw a 2 than a 6.</p> <p>Pieces must be moved forward. A piece can only be moved onto an empty field or a field with an enemy piece on it, in which case the enemy piece and your piece change positions. You cannot move onto a field already occupied by your own pawns. Groups of 2 pawns are safe and you cannot move onto their fields. Groups of three enemy pieces can additionally not be passed.<p> <p>There are 6 special fields on the board. The three last fields and the one showing the Udjat-Eye are safe fields, where enemy pieces cannot be pushed away from. The water field makes a piece fall back to the Anch field. For a piece to leave the board it needs to reach exactly the field after the end of the board. Pieces on the three last fields can only be moved off the board, i.e. a pawn e.g. on the field with the three birds can only be moved if a 3 is thrown.</p> <p>The difficulty, that is the strength of the computer, can be changed during game-play. The strength gives the number of moves the computer looks ahead and then chooses the likeliest best move for himself.</p> </div> </div> </body> </html> Last edited by twobob; 03-09-2013 at 11:44 AM. |
Advert | |
|
03-09-2013, 10:22 AM | #6 |
SQUIRREL!!
Posts: 1,636
Karma: 8400000
Join Date: Nov 2010
Location: California
Device: K-Fire, PW2, PW3
|
|
Tags |
games, kindle, launcher add-ons |
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
KinGo: A viewer and editor for the game of Go [Kindle Touch] | thatworkshop | Kindle Developer's Corner | 27 | 03-28-2013 05:09 PM |
Touch gestures in WAF apps | RandoManaphy | Kindle Developer's Corner | 0 | 07-01-2012 08:25 PM |
WAF Kalc for kindle touch | aditya3098 | Kindle Developer's Corner | 8 | 02-28-2012 11:10 PM |
Bargain (Kindle App) Next Puzzle Game (A Matching Game for Kindle) | arcadata | Deals and Resources (No Self-Promotion or Affiliate Links) | 0 | 05-13-2011 10:07 AM |