Author: hhubner Date: 2007-12-02 18:36:27 -0500 (Sun, 02 Dec 2007) New Revision: 2296
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp branches/trunk-reorg/projects/scrabble/website/scrabble.js Log: Gameplay fixes.
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp =================================================================== --- branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-12-02 18:46:42 UTC (rev 2295) +++ branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-12-02 23:36:27 UTC (rev 2296) @@ -55,6 +55,7 @@ (encode-json-plist (list :type "move" :participant-login (user-login (player-of (participant-of move))) :score (score-of move) + :player-score (score-of (participant-of move)) :placed-tiles (placed-tiles-of move) :words (mapcar (lambda (word-cons) (list (car word-cons) (cdr word-cons))) @@ -64,12 +65,14 @@ (defmethod encode-json ((move move-withdrawal) stream) (encode-json-plist (list :type "move-withdrawal" :participant-login (user-login (player-of (participant-of move))) + :player-score (score-of (participant-of move)) :reason (or (reason-of move) "")) stream))
(defmethod encode-json ((move tile-swap) stream) (encode-json-plist (list :type "tile-swap" :participant-login (user-login (player-of (participant-of move))) + :player-score (score-of (participant-of move)) :reason (count-of move)) stream))
@@ -92,6 +95,7 @@ (start-session) (encode-json-plist (append (list :login (user-login (player-of participant)) :name (user-full-name (player-of participant)) + :score (score-of participant) :remaining-tiles) (list (if (eq (player-of participant) (session-value :user))
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js =================================================================== --- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-12-02 18:46:42 UTC (rev 2295) +++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-12-02 23:36:27 UTC (rev 2296) @@ -1,4 +1,4 @@ -// -*- Java -*- (really Javascript) +// -*- JavaScript -*-
var boardScoring = [["triple-word",null,null,"double-letter",null,null,null,"triple-word", null,null,null,"double-letter",null,null,"triple-word"], @@ -38,7 +38,7 @@ // Given the board and list of placed tiles, either throw an error or // return if the move is legal.
- var positions = map(function (placement) { return [ placement[0], placement[1] ] }, placedTiles) + var positions = map(function (placement) { return [ placement.x, placement.y ] }, placedTiles) .sort(function (a, b) { return (a[0] - b[0]) || (a[1] - b[1])});
if (filter(partial(operator.ne, positions[0][0]), map(function (position) { return position[0] }, positions)).length @@ -133,6 +133,13 @@ nextTurn.style.textAlign = 'left'; setElementPosition(nextTurn, { x: border + 680, y: border + 665 }); appendChildNodes($('playfield'), nextTurn); + + var nextTurn = DIV({ id: 'status' }, ""); + nextTurn.style.position = 'absolute'; + nextTurn.style.width = '280px'; + nextTurn.style.textAlign = 'left'; + setElementPosition(nextTurn, { x: border + 680, y: border + 680 }); + appendChildNodes($('playfield'), nextTurn); }
function setLetter(x, y, letter, isBlank) { @@ -147,22 +154,11 @@ }
function placeLetter(x, y, tile) { - var mask = IMG({ src: 'images/mask.png'}); - mask.style.position = 'absolute'; - mask.style.top = '3px'; - mask.style.left = '3px'; - mask.style.zIndex = '20'; - appendChildNodes(board[x][y], mask); - board[x][y].letterNode = tile; - board[x][y].letter = tile.letter; - board[x][y].justPlaced = true; - tile.anim = new YAHOO.util.Motion(tile, { points: { to: [ border + x * 44 + 3, - border + y * 44 + 3 ]}}, - 0.15, - YAHOO.util.Easing.easeBoth); - tile.anim.animate(); }
+function removeLastLetterFromMove() { +} + function letterAt(x, y) { return board[x][y].letter && !board[x][y].justPlaced; } @@ -239,28 +235,74 @@
var move = [];
-function makeMove(x, y, letter, isBlank) { - move[move.length] = [x, y, letter, isBlank]; +function makeMask() +{ + var mask = IMG({ src: 'images/mask.png'}); + mask.style.position = 'absolute'; + mask.style.top = '3px'; + mask.style.left = '3px'; + mask.style.zIndex = '20'; + return mask; +} + +function addLetterToMove(x, y, tile) { + mask = makeMask(); + appendChildNodes(board[x][y], mask); + board[x][y].letterNode = tile; + board[x][y].letter = tile.letter; + board[x][y].justPlaced = true; + tile.mask = mask; + tile.anim = new YAHOO.util.Motion(tile, { points: { to: [ border + x * 44 + 3, + border + y * 44 + 3 ]}}, + 0.15, + YAHOO.util.Easing.easeBoth); + tile.anim.animate(); + + move[move.length] = { x: x, y: y, tile: tile }; try { checkMoveLegality(move); $('move').onclick = submitMove; - $('move').innerHTML = move.toString(); + $('move').innerHTML = "submit move"; + displayStatus(''); } catch (e) { + if (typeof e != 'string') { + alert(e.message); + } else { + displayStatus(e); + } $('move').onclick = undefined; $('move').innerHTML = e.toString(); } }
-function clearMove() { +function confirmMove() { + for (var i = 0; i < move.length; i++) { + removeElement(move[i].tile.mask); + move[i].tile.mask = undefined; + } + cursor.clear(); move = []; $('move').onclick = null; - $('move').innerHTML = '[no move]'; + $('move').innerHTML = ''; + }
+function moveAsString() { + // We internally keep the move as array of objects, but send it to the server rather unstructured: + var serverMessage = []; + for (var i = 0; i < move.length; i++) { + serverMessage.push(move[i].x); + serverMessage.push(move[i].y); + serverMessage.push(move[i].tile.letterName); + serverMessage.push(move[i].tile.letterName == undefined); + } + return serverMessage.toString(); +} + function submitMove() { - var queryString = MochiKit.Base.queryString({ move: move.toString(), game: gameID }); + var queryString = MochiKit.Base.queryString({ move: moveAsString(), game: gameID }); var res = MochiKit.Async.doXHR("/place-tiles", { method: 'POST', sendContent: queryString, @@ -270,20 +312,27 @@
function moveSuccess(result) { - var response; try { - response = eval('(' + result.responseText + ')'); + var response; + try { + response = eval('(' + result.responseText + ')'); + } + catch (e) { + alert("invalid JSON reply: " + result.responseText); + return; + } + if (response.error) { + alert(response.error); + } else { + confirmMove(); + alert(response.move.playerScore); + $('playfield')['score-' + response.move.participantLogin].innerHTML = response.move.playerScore.toString(); + displayMyTray(response.tray); + } } catch (e) { - alert("invalid JSON reply: " + result.responseText); - return; + alert('error during moveSuccess: ' + e.message); } - if (response.error) { - alert(response.error); - } else { - clearMove(); - makeMyTray(response.tray); - } }
function moveFailure(e) @@ -315,18 +364,17 @@ } } if (tilePosition == -1) { - alert("You don't have letter + '" + letter + "'!"); + displayStatus('you-dont-have-that-letter', letter); } else { var isHoriz; if (move.length > 0) { - isHoriz = (move[0][0] != x); + isHoriz = (move[0].x != x); } cursor.advance(isHoriz); if (!letterAt(x, y)) { var tile = tray[tilePosition]; tray.splice(tilePosition, 1); - placeLetter(x, y, tile); - makeMove(x, y, tile.letterName, tile.letterName == undefined); + addLetterToMove(x, y, tile); } } } @@ -362,6 +410,10 @@ if (!letterAt(x, ++y)) break; break; + case backspaceKey: + if (move.length) { + removeLastLetterFromMove(); + } } if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) { cursor.clear(); @@ -391,7 +443,7 @@ this.anim.animate(); }
-function makeMyTray(letters) { +function displayMyTray(letters) { map(removeElement, tray); tray = []; for (var i = 0; i < letters.length; i++) { @@ -403,7 +455,7 @@ element.style.height = '34px'; element.style.zIndex = '10'; element.onclick = trayClick; - setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 }); + setElementPosition(element, { x: border + i * 40, y: border + 665 }); tray[i] = element; } appendChildNodes($('playfield'), tray); @@ -428,7 +480,9 @@
var otherPlayerIndex = 0;
-function makeTheirTray (name, tileCount) { +function makeTheirTray (participant) { + var tileCount = (typeof participant.remainingTiles == 'number') ? participant.remainingTiles : participant.remainingTiles.length; + var tray = []; for (var i = 0; i < tileCount; i++) { var element = IMG({src: 'images/null.png'}); @@ -441,12 +495,21 @@ } appendChildNodes($('playfield'), tray);
- var nameTag = DIV(null, name); + var nameTag = DIV(null, participant.name); nameTag.style.position = 'absolute'; nameTag.style.width = '200px'; nameTag.style.textAlign = 'left'; setElementPosition(nameTag, { x: border + 680, y: border + 80 * otherPlayerIndex + 50 }); appendChildNodes($('playfield'), nameTag); + + var scoreTag = DIV(null, participant.score); + scoreTag.style.position = 'absolute'; + scoreTag.style.width = '80px'; + scoreTag.style.textAlign = 'right'; + setElementPosition(scoreTag, { x: border + 870, y: border + 80 * otherPlayerIndex + 50 }); + appendChildNodes($('playfield'), scoreTag); + $('playfield')['score-' + participant.login] = scoreTag; + otherPlayerIndex++; }
@@ -465,32 +528,41 @@ return retval; }
+function displayWhosTurnItIs(name) { + replaceChildNodes($('nextTurn'), + "Next: " + name); +} + function drawGameState (gameState) { - for (var i = 0; i < gameState.board.length; i++) { - var x = gameState.board[i][0]; - var y = gameState.board[i][1]; - var char = gameState.board[i][2]; - setLetter(x, y, char, gameState.board[i].length > 3); - } - var firstParticipant = gameState.participants[0]; - replaceChildNodes($('nextTurn'), - "It is " - + ((typeof firstParticipant.remainingTiles == 'number') ? (firstParticipant.name + "s") : "your") - + " turn"); - for (var i = 0; i < gameState.participants.length; i++) { - var participant = gameState.participants[i]; - if (typeof participant.remainingTiles == 'number') { - makeTheirTray(participant.name, participant.remainingTiles); - } else { - makeMyTray(participant.remainingTiles); + try { + for (var i = 0; i < gameState.board.length; i++) { + var x = gameState.board[i][0]; + var y = gameState.board[i][1]; + var char = gameState.board[i][2]; + setLetter(x, y, char, gameState.board[i].length > 3); } + var firstParticipant = gameState.participants[0]; + displayWhosTurnItIs(firstParticipant.name); + for (var i = 0; i < gameState.participants.length; i++) { + var participant = gameState.participants[i]; + makeTheirTray(participant); + if (typeof participant.remainingTiles != 'number') { + displayMyTray(participant.remainingTiles); + } + } + for (var i = 0; i < gameState.moves.length; i++) { + appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i]))); + } } - for (var i = 0; i < gameState.moves.length; i++) { - appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i]))); + catch (e) { + alert('error ' + e + ' in drawGameState'); } }
-var legalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); +function displayStatus(status) +{ + replaceChildNodes('status', status); +}
function init() { makeBoard(); @@ -503,7 +575,7 @@ { fn: functionKeyPressed, scope: this, correctScope: true }); functionKeyListener.enable();
- var moveDisplay = DIV({ id: 'move' }, "[no move yet]"); + var moveDisplay = DIV({ id: 'move' }, ""); moveDisplay.style.color = 'white'; moveDisplay.style.position = 'absolute'; setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });