bknr-cvs
Threads by month
- ----- 2025 -----
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
November 2007
- 1 participants
- 33 discussions
Author: hhubner
Date: 2007-11-29 08:18:49 -0500 (Thu, 29 Nov 2007)
New Revision: 2294
Modified:
branches/trunk-reorg/thirdparty/emacs/javascript.el
Log:
Updated version from http://joost.zeekat.nl/wp-content/javascript.el
Modified: branches/trunk-reorg/thirdparty/emacs/javascript.el
===================================================================
--- branches/trunk-reorg/thirdparty/emacs/javascript.el 2007-11-29 11:57:01 UTC (rev 2293)
+++ branches/trunk-reorg/thirdparty/emacs/javascript.el 2007-11-29 13:18:49 UTC (rev 2294)
@@ -1,5 +1,14 @@
;;; javascript.el --- Major mode for editing JavaScript source text
+;; This version contains a few font-lock fixes for quoted strings
+;; and regular expressions by Joost Diepenmaat <joost(a)zeekat.nl>
+;; Joost's version - 2007-11-29
+
+;; Currently known issues:
+;;
+;; /* .. */ style comments inside quoted strings are shown as comments
+;; instead of quoted strings. Fixing this may get complicated.
+
;; Copyright (C) 2006 Karl Landström
;; Author: Karl Landström <kland(a)comhem.se>
@@ -8,9 +17,6 @@
;; Date: 2006-12-26
;; Keywords: languages, oop
-;; This version contains a few font-lock fixes for quoted strings
-;; and regular expressions by Joost Diepenmaat <joost(a)zeekat.nl>
-
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
@@ -117,6 +123,14 @@
(modify-syntax-entry ?' "." table)
(modify-syntax-entry ?\" "." table)
+ ;; partially disable comment detection. Our manual string detection
+ ;; won't work if there are automatically detected comments inside the
+ ;; string.
+ ;;
+ ;; note that we keep auto-detection of /* .. */ style comments since
+ ;; they are multi-line and can't easily be detected otherwise.
+ (modify-syntax-entry ?/ ". 14" table)
+
;; The syntax class of underscore should really be `symbol' ("_")
;; but that makes matching of tokens much more complex as e.g.
;; "\\<xyz\\>" matches part of e.g. "_xyz" and "xyz_abc". Defines
@@ -297,8 +311,10 @@
;; detect "autoquoted" object properties... clases with "switch { ... default: }"
;; may not be worth the trouble
- (list "\\(^[ \t]*\\|[,{][ \t]*\\)\\(\\w+\\):" 2 font-lock-string-face))
+ (list "\\(^[ \t]*\\|[,{][ \t]*\\)\\(\\w+\\):" 2 font-lock-string-face)
+ ;; find single-line comments
+ (list "\\(//.*\\)" 1 font-lock-comment-face))
"Level one font lock.")
(defconst js-font-lock-keywords-2
1
0

29 Nov '07
Author: hhubner
Date: 2007-11-29 06:57:01 -0500 (Thu, 29 Nov 2007)
New Revision: 2293
Modified:
branches/trunk-reorg/projects/scrabble/website/scrabble.js
Log:
nischt is mit foo
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-29 08:48:29 UTC (rev 2292)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-29 11:57:01 UTC (rev 2293)
@@ -292,8 +292,6 @@
}
function letterKeyPressed(e) {
- alert('foo');
-
if (e.which == 0 || e.altKey || e.ctrlKey || e.shiftKey) {
// not a letter key
return;
1
0

[bknr-cvs] r2292 - in branches/trunk-reorg/projects/scrabble: src website
by bknr@bknr.net 29 Nov '07
by bknr@bknr.net 29 Nov '07
29 Nov '07
Author: hhubner
Date: 2007-11-29 03:48:29 -0500 (Thu, 29 Nov 2007)
New Revision: 2292
Modified:
branches/trunk-reorg/projects/scrabble/src/make-letters.lisp
branches/trunk-reorg/projects/scrabble/src/web.lisp
branches/trunk-reorg/projects/scrabble/website/scrabble.js
Log:
Keyboard event handling fixes, still not perfect.
Modified: branches/trunk-reorg/projects/scrabble/src/make-letters.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/make-letters.lisp 2007-11-27 11:01:50 UTC (rev 2291)
+++ branches/trunk-reorg/projects/scrabble/src/make-letters.lisp 2007-11-29 08:48:29 UTC (rev 2292)
@@ -65,8 +65,9 @@
(set-rgb-fill 0 0 0))
(set-font bold-font 27)
(draw-centered-string 13 7 char-string)
- (set-font regular-font 11)
- (draw-centered-string 26 3 (princ-to-string score)))
+ (unless blank-used
+ (set-font regular-font 11)
+ (draw-centered-string 26 3 (princ-to-string score))))
(save-png pathname)
pathname)))
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-27 11:01:50 UTC (rev 2291)
+++ branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-29 08:48:29 UTC (rev 2292)
@@ -39,7 +39,8 @@
(encode-json-plist (list :remaining-tiles (remaining-tile-count tile-bag)) stream))
(defmethod encode-json ((tile tile) stream)
- (encode-json-plist (list :letter (letter-name-of tile)
+ (encode-json-plist (list :letter (letter-of tile)
+ :letter-name (letter-name-of tile)
:value (value-of tile))
stream))
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-27 11:01:50 UTC (rev 2291)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-29 08:48:29 UTC (rev 2292)
@@ -35,51 +35,51 @@
function checkMoveLegality(placedTiles)
{
- // Given the board and list of placed tiles, either throw an error or
- // return if the move is legal.
+ // 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)
- .sort(function (a, b) { return (a[0] - b[0]) || (a[1] - b[1])});
+ var positions = map(function (placement) { return [ placement[0], placement[1] ] }, 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
- && filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
- throw "not-in-a-row";
- }
+ if (filter(partial(operator.ne, positions[0][0]), map(function (position) { return position[0] }, positions)).length
+ && filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
+ throw "not-in-a-row";
+ }
- var startOfPlacement = positions[0];
- var endOfPlacement = positions[positions.length - 1];
+ var startOfPlacement = positions[0];
+ var endOfPlacement = positions[positions.length - 1];
- for (var x = startOfPlacement[0]; x <= endOfPlacement[0]; x++) {
- for (var y = startOfPlacement[1]; y <= endOfPlacement[1]; y++) {
- if (!letterAt(x, y) && (findValue(positions, [ x, y ]) == -1)) {
- throw "placement-with-holes";
- }
- }
+ for (var x = startOfPlacement[0]; x <= endOfPlacement[0]; x++) {
+ for (var y = startOfPlacement[1]; y <= endOfPlacement[1]; y++) {
+ if (!letterAt(x, y) && (findValue(positions, [ x, y ]) == -1)) {
+ throw "placement-with-holes";
+ }
}
+ }
- if (findValue(positions, [ 7, 7 ]) == -1) {
- var found = false;
- for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
- for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
- if (((x > 0) && letterAt(x - 1, y))
- || ((x < 14) && letterAt(x + 1, y))
- || ((y > 0) && letterAt(x, y - 1))
- || ((y < 14) && letterAt(x, y + 1))) {
- found = true;
- }
- }
- }
- if (!found) {
- throw "not-touching-other-tile";
- }
+ if (findValue(positions, [ 7, 7 ]) == -1) {
+ var found = false;
+ for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
+ for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
+ if (((x > 0) && letterAt(x - 1, y))
+ || ((x < 14) && letterAt(x + 1, y))
+ || ((y > 0) && letterAt(x, y - 1))
+ || ((y < 14) && letterAt(x, y + 1))) {
+ found = true;
+ }
+ }
}
+ if (!found) {
+ throw "not-touching-other-tile";
+ }
+ }
}
//
function getFieldScore(x, y) {
- return boardScoring[x][y] || 'standard';
+ return boardScoring[x][y] || 'standard';
}
var theirTrays;
@@ -91,235 +91,246 @@
var border = 10;
function makeBoard() {
- var container = $('playfield');
- board = [];
- for (x = 0; x < 15; x++) {
- board[x] = [];
- for (y = 0; y < 15; y++) {
- var element = DIV();
- element.style.position = 'absolute';
- element.style.width = '40px';
- element.style.height = '40px';
- var imageName = (x == 7 && y == 7) ? "start-field" : getFieldScore(x, y);
- element.style.backgroundImage = 'url(images/' + imageName + '.png)';
- element.x = x;
- element.y = y;
- setElementPosition(element, { x: border + x * 44, y: border + y * 44 });
- YAHOO.util.Event.on(element, 'click', emptyTileClicked)
- board[x][y] = element;
- }
- appendChildNodes(container, board[x]);
+ var container = $('playfield');
+ board = [];
+ for (x = 0; x < 15; x++) {
+ board[x] = [];
+ for (y = 0; y < 15; y++) {
+ var element = DIV();
+ element.style.position = 'absolute';
+ element.style.width = '40px';
+ element.style.height = '40px';
+ var imageName = (x == 7 && y == 7) ? "start-field" : getFieldScore(x, y);
+ element.style.backgroundImage = 'url(images/' + imageName + '.png)';
+ element.x = x;
+ element.y = y;
+ setElementPosition(element, { x: border + x * 44, y: border + y * 44 });
+ YAHOO.util.Event.on(element, 'click', emptyTileClicked)
+ board[x][y] = element;
}
+ appendChildNodes(container, board[x]);
+ }
- var shuffleButton = DIV(null, "shuffle");
- shuffleButton.style.color = 'white';
- shuffleButton.style.position = 'absolute';
- shuffleButton.onclick = shuffleMyTray;
- setElementPosition(shuffleButton, { x: border + 480, y: border + 665 });
- appendChildNodes(container, shuffleButton);
+ var shuffleButton = DIV(null, "shuffle");
+ shuffleButton.style.color = 'white';
+ shuffleButton.style.position = 'absolute';
+ shuffleButton.onclick = shuffleMyTray;
+ setElementPosition(shuffleButton, { x: border + 480, y: border + 665 });
+ appendChildNodes(container, shuffleButton);
- var gameLog = DIV({ id: 'gameLog' }, "");
- gameLog.style.position = 'absolute';
- gameLog.style.width = '280px';
- gameLog.style.height = '250px';
- gameLog.style.textAlign = 'left';
- gameLog.style.overflowY = 'scroll';
- setElementPosition(gameLog, { x: border + 680, y: border + 400 });
- appendChildNodes($('playfield'), gameLog);
+ var gameLog = DIV({ id: 'gameLog' }, "");
+ gameLog.style.position = 'absolute';
+ gameLog.style.width = '280px';
+ gameLog.style.height = '250px';
+ gameLog.style.textAlign = 'left';
+ gameLog.style.overflowY = 'scroll';
+ setElementPosition(gameLog, { x: border + 680, y: border + 400 });
+ appendChildNodes($('playfield'), gameLog);
+
+ var nextTurn = DIV({ id: 'nextTurn' }, "");
+ nextTurn.style.position = 'absolute';
+ nextTurn.style.width = '280px';
+ nextTurn.style.textAlign = 'left';
+ setElementPosition(nextTurn, { x: border + 680, y: border + 665 });
+ appendChildNodes($('playfield'), nextTurn);
}
function setLetter(x, y, letter, isBlank) {
- var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
- image.style.position = 'absolute';
- image.style.top = '3px';
- image.style.left = '3px';
- setElementPosition(image, { x: border + x * 44 + 3, y: border + y * 44 + 3 });
- appendChildNodes($('playfield'), image);
- board[x][y].letterNode = image;
- board[x][y].letter = letter;
+ var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
+ image.style.position = 'absolute';
+ image.style.top = '3px';
+ image.style.left = '3px';
+ setElementPosition(image, { x: border + x * 44 + 3, y: border + y * 44 + 3 });
+ appendChildNodes($('playfield'), image);
+ board[x][y].letterNode = image;
+ board[x][y].letter = letter;
}
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();
+ 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 letterAt(x, y) {
- return board[x][y].letter && !board[x][y].justPlaced;
+ return board[x][y].letter && !board[x][y].justPlaced;
}
function Cursor()
{
- var image = new IMG({ src: 'images/cursor.png' });
- image.style.position = 'absolute';
- image.style.top = '-3px';
- image.style.left = '-3px';
+ var image = new IMG({ src: 'images/cursor.png' });
+ image.style.position = 'absolute';
+ image.style.top = '-3px';
+ image.style.left = '-3px';
- this.image = image;
- this.x = -1;
- this.y = -1;
- this.direction = 0;
+ this.image = image;
+ this.x = -1;
+ this.y = -1;
+ this.direction = 0;
- this.set = function(x, y) {
- this.x = x;
- this.y = y;
- appendChildNodes(board[x][y], this.image);
- board[x][y].cursor = this.image;
- };
+ this.set = function(x, y) {
+ this.x = x;
+ this.y = y;
+ appendChildNodes(board[x][y], this.image);
+ board[x][y].cursor = this.image;
+ };
- this.clear = function() {
- if (this.x != -1) {
- removeElement(board[this.x][this.y].cursor);
- board[this.x][this.y].cursor = undefined;
- this.x = this.y = -1;
- this.direction = 0;
- }
- };
+ this.clear = function() {
+ if (this.x != -1) {
+ removeElement(board[this.x][this.y].cursor);
+ board[this.x][this.y].cursor = undefined;
+ this.x = this.y = -1;
+ this.direction = 0;
+ }
+ };
- this.advance = function(isHoriz) {
- var horizontal = 1;
- var vertical = 2;
- var direction = this.direction;
- if (direction == 0) {
- // Direction not determined
- if (isHoriz != undefined) {
- direction = isHoriz ? horizontal : vertical;
- } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
- || ((this.y > 1)
- && letterAt(this.x, this.y - 1)
- && !letterAt(this.x, this.y - 2))
- || ((this.x > 1)
- && letterAt(this.x - 1, this.y)
- && letterAt(this.x - 2, this.y))) {
- direction = vertical;
- } else {
- direction = horizontal;
- }
- }
- var x = this.x;
- var y = this.y;
- this.clear();
- this.direction = direction;
- if (this.direction == horizontal) {
- x++;
- } else {
- y++;
- }
- if ((x != 15) && (y != 15)) {
- this.set(x, y);
- }
- };
+ this.advance = function(isHoriz) {
+ var horizontal = 1;
+ var vertical = 2;
+ var direction = this.direction;
+ if (direction == 0) {
+ // Direction not determined
+ if (isHoriz != undefined) {
+ direction = isHoriz ? horizontal : vertical;
+ } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
+ || ((this.y > 1)
+ && letterAt(this.x, this.y - 1)
+ && !letterAt(this.x, this.y - 2))
+ || ((this.x > 1)
+ && letterAt(this.x - 1, this.y)
+ && letterAt(this.x - 2, this.y))) {
+ direction = vertical;
+ } else {
+ direction = horizontal;
+ }
+ }
+ var x = this.x;
+ var y = this.y;
+ this.clear();
+ this.direction = direction;
+ if (this.direction == horizontal) {
+ x++;
+ } else {
+ y++;
+ }
+ if ((x != 15) && (y != 15)) {
+ this.set(x, y);
+ }
+ };
}
var cursor = new Cursor;
function emptyTileClicked() {
- cursor.clear();
- cursor.set(this.x, this.y);
+ cursor.clear();
+ cursor.set(this.x, this.y);
}
var move = [];
function makeMove(x, y, letter, isBlank) {
- move[move.length] = [x, y, letter, isBlank];
- try {
- checkMoveLegality(move);
- $('move').onclick = submitMove;
- $('move').innerHTML = move.toString();
- }
- catch (e) {
- $('move').onclick = undefined;
- $('move').innerHTML = e.toString();
- }
+ move[move.length] = [x, y, letter, isBlank];
+ try {
+ checkMoveLegality(move);
+ $('move').onclick = submitMove;
+ $('move').innerHTML = move.toString();
+ }
+ catch (e) {
+ $('move').onclick = undefined;
+ $('move').innerHTML = e.toString();
+ }
}
function clearMove() {
- move = [];
- $('move').onclick = null;
- $('move').innerHTML = '[no move]';
+ move = [];
+ $('move').onclick = null;
+ $('move').innerHTML = '[no move]';
}
function submitMove()
{
- var queryString = MochiKit.Base.queryString({ move: move.toString(), game: gameID });
- var res = MochiKit.Async.doXHR("/place-tiles",
- { method: 'POST',
- sendContent: queryString,
- headers: { "Content-Type": "application/x-www-form-urlencoded" } });
- res.addCallbacks(moveSuccess, moveFailure);
+ var queryString = MochiKit.Base.queryString({ move: move.toString(), game: gameID });
+ var res = MochiKit.Async.doXHR("/place-tiles",
+ { method: 'POST',
+ sendContent: queryString,
+ headers: { "Content-Type": "application/x-www-form-urlencoded" } });
+ res.addCallbacks(moveSuccess, moveFailure);
}
function moveSuccess(result)
{
- var response;
- try {
- response = eval('(' + result.responseText + ')');
- }
- catch (e) {
- alert("invalid JSON reply: " + result.responseText);
- return;
- }
- if (response.error) {
- alert(response.error);
- } else {
- clearMove();
- makeMyTray(map(function (entry) { return entry.letter }, response.tray))
- }
+ var response;
+ try {
+ response = eval('(' + result.responseText + ')');
+ }
+ catch (e) {
+ alert("invalid JSON reply: " + result.responseText);
+ return;
+ }
+ if (response.error) {
+ alert(response.error);
+ } else {
+ clearMove();
+ makeMyTray(response.tray);
+ }
}
function moveFailure(e)
{
- alert('failed: ' + e);
+ alert('failed: ' + e);
}
-var specialKeyCodes = { 59: 'LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS',
- 192: 'LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS',
- 222: 'LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS' };
+function letterKeyPressed(e) {
+ alert('foo');
-function letterKeyPressed(type, args, obj) {
- var letter = specialKeyCodes[args[0]] || String.fromCharCode(args[0]);
- var x = cursor.x;
- var y = cursor.y;
- var tilePosition = -1;
+ if (e.which == 0 || e.altKey || e.ctrlKey || e.shiftKey) {
+ // not a letter key
+ return;
+ }
+
+ var letter = String.fromCharCode(e.which).toUpperCase();
+
+ var x = cursor.x;
+ var y = cursor.y;
+ var tilePosition = -1;
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == letter) {
+ tilePosition = i;
+ }
+ }
+ if (tilePosition == -1) {
for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
- if (tray[i].letter == letter) {
- tilePosition = i;
- }
+ if (tray[i].letter == undefined) {
+ tilePosition = i;
+ }
}
- if (tilePosition == -1) {
- for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
- if (tray[i].letter == undefined) {
- tilePosition = i;
- }
- }
+ }
+ if (tilePosition == -1) {
+ alert("You don't have letter + '" + letter + "'!");
+ } else {
+ var isHoriz;
+ if (move.length > 0) {
+ isHoriz = (move[0][0] != x);
}
- if (tilePosition == -1) {
- alert("You don't have that letter!");
- } else {
- var isHoriz;
- if (move.length > 0) {
- isHoriz = (move[0][0] != x);
- }
- cursor.advance(isHoriz);
- if (!letterAt(x, y)) {
- var tile = tray[tilePosition];
- tray.splice(tilePosition, 1);
- placeLetter(x, y, tile);
- makeMove(x, y, letter, tile.letter == undefined);
- }
+ 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);
}
+ }
}
var leftKey = 37;
@@ -329,180 +340,176 @@
var backspaceKey = 8;
function functionKeyPressed(type, args, obj) {
- var x = cursor.x;
- var y = cursor.y;
+ var x = cursor.x;
+ var y = cursor.y;
- switch (args[0]) {
- case rightKey:
- while (x < 14)
- if (!letterAt(++x, y))
- break;
- break;
- case leftKey:
- while (x > 0)
- if (!letterAt(--x, y))
- break;
- break;
- case upKey:
- while (y > 0)
- if (!letterAt(x, --y))
- break;
- break;
- case downKey:
- while (y < 14)
- if (!letterAt(x, ++y))
- break;
- break;
- }
- if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) {
- cursor.clear();
- cursor.set(x, y);
- }
- YAHOO.util.Event.preventDefault(args[1]);
+ switch (args[0]) {
+ case rightKey:
+ while (x < 14)
+ if (!letterAt(++x, y))
+ break;
+ break;
+ case leftKey:
+ while (x > 0)
+ if (!letterAt(--x, y))
+ break;
+ break;
+ case upKey:
+ while (y > 0)
+ if (!letterAt(x, --y))
+ break;
+ break;
+ case downKey:
+ while (y < 14)
+ if (!letterAt(x, ++y))
+ break;
+ break;
+ }
+ if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) {
+ cursor.clear();
+ cursor.set(x, y);
+ }
+ YAHOO.util.Event.preventDefault(args[1]);
}
function clearBoard() {
- for (x = 0; x < 15; x++) {
- for (y = 0; y < 15; y++) {
- var letterNode = board[x][y].letterNode;
- if (letterNode) {
- letterNode.anim = new YAHOO.util.Motion(letterNode, { points: { to: [ border + 7 * 44 + 3,
- border + 7 * 44 + 3 ]}},
- 0.15);
- letterNode.anim.onComplete.subscribe(function () { removeElement(this); });
- letterNode.anim.animate();
- }
- }
+ for (x = 0; x < 15; x++) {
+ for (y = 0; y < 15; y++) {
+ var letterNode = board[x][y].letterNode;
+ if (letterNode) {
+ letterNode.anim = new YAHOO.util.Motion(letterNode, { points: { to: [ border + 7 * 44 + 3,
+ border + 7 * 44 + 3 ]}},
+ 0.15);
+ letterNode.anim.onComplete.subscribe(function () { removeElement(this); });
+ letterNode.anim.animate();
+ }
}
+ }
}
function trayClick(letter) {
- this.clicked = !this.clicked;
- this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
- this.anim.animate();
+ this.clicked = !this.clicked;
+ this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
+ this.anim.animate();
}
function makeMyTray(letters) {
- map(removeElement, tray);
- tray = [];
- for (var i = 0; i < letters.length; i++) {
- var element = IMG({src: 'images/' + letters[i] + '.png'});
- element.letter = letters[i];
- element.style.position = 'absolute';
- element.style.width = '34px';
- element.style.height = '34px';
- element.style.zIndex = '10';
- element.onclick = trayClick;
- setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 });
- tray[i] = element;
- }
- appendChildNodes($('playfield'), tray);
+ map(removeElement, tray);
+ tray = [];
+ for (var i = 0; i < letters.length; i++) {
+ var element = IMG({src: 'images/' + letters[i].letterName + '.png'});
+ element.letter = letters[i].letter;
+ element.letterName = letters[i].letterName;
+ element.style.position = 'absolute';
+ element.style.width = '34px';
+ element.style.height = '34px';
+ element.style.zIndex = '10';
+ element.onclick = trayClick;
+ setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
}
function shuffleMyTray() {
- var count = tray.length;
- var newTray = [];
- for (var i = 0; i < count; i++) {
- do {
- index = Math.floor(Math.random() * count);
- } while (newTray[index]);
- newTray[index] = tray[i];
- newTray[index].anim = new YAHOO.util.Motion(tray[i], { points: { to: [ border + 194 + i * 40,
- border + 665 ] }},
- 0.5);
- newTray[index].anim.animate();
- newTray[index].clicked = false;
- }
- tray = newTray;
+ var count = tray.length;
+ var newTray = [];
+ for (var i = 0; i < count; i++) {
+ do {
+ index = Math.floor(Math.random() * count);
+ } while (newTray[index]);
+ newTray[index] = tray[i];
+ newTray[index].anim = new YAHOO.util.Motion(tray[i], { points: { to: [ border + 194 + i * 40,
+ border + 665 ] }},
+ 0.5);
+ newTray[index].anim.animate();
+ newTray[index].clicked = false;
+ }
+ tray = newTray;
}
var otherPlayerIndex = 0;
function makeTheirTray (name, tileCount) {
- var tray = [];
- for (var i = 0; i < tileCount; i++) {
- var element = IMG({src: 'images/null.png'});
- element.style.position = 'absolute';
- element.style.width = '34px';
- element.style.height = '34px';
- element.style.zIndex = '10';
- setElementPosition(element, { x: border + 680 + i * 40, y: border + 80 * otherPlayerIndex });
- tray[i] = element;
- }
- appendChildNodes($('playfield'), tray);
+ var tray = [];
+ for (var i = 0; i < tileCount; i++) {
+ var element = IMG({src: 'images/null.png'});
+ element.style.position = 'absolute';
+ element.style.width = '34px';
+ element.style.height = '34px';
+ element.style.zIndex = '10';
+ setElementPosition(element, { x: border + 680 + i * 40, y: border + 80 * otherPlayerIndex });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
- var nameTag = DIV(null, 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);
- otherPlayerIndex++;
+ var nameTag = DIV(null, 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);
+ otherPlayerIndex++;
}
function renderMoveAsText(move)
{
- var retval = move.participantLogin;
- if (move.type == 'move') {
- retval += " score: " + move.score;
- for (var i = 0; i < move.words.length; i++) {
- retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
- }
- } else {
- retval += move.type;
+ var retval = move.participantLogin;
+ if (move.type == 'move') {
+ retval += " score: " + move.score;
+ for (var i = 0; i < move.words.length; i++) {
+ retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
}
+ } else {
+ retval += move.type;
+ }
- return retval;
+ return retval;
}
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);
+ 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);
}
- 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(map(function (entry) { return entry.letter }, 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])));
+ }
}
var legalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
function init() {
- makeBoard();
+ makeBoard();
- var letterKeyCodes = [];
- for (var i = 0; i < legalLetters.length; i++) {
- letterKeyCodes[i] = legalLetters[i].charCodeAt(0);
- }
- // add mozilla key codes
- letterKeyCodes.push(59); // u"
- letterKeyCodes.push(192); // o"
- letterKeyCodes.push(222); // a"
- var letterKeyListener = new YAHOO.util.KeyListener(document,
- { keys: letterKeyCodes },
- { fn: letterKeyPressed, scope: this, correctScope: true });
- letterKeyListener.enable();
+ // does not work for ie (document.body needed)?
+ YAHOO.util.Event.on(window, 'keypress', letterKeyPressed);
- var functionKeyListener = new YAHOO.util.KeyListener(document,
- { keys: [ leftKey, upKey, rightKey, downKey, backspaceKey ] },
- { fn: functionKeyPressed, scope: this, correctScope: true });
- functionKeyListener.enable();
+ var functionKeyListener = new YAHOO.util.KeyListener(document,
+ { keys: [ leftKey, upKey, rightKey, downKey, backspaceKey ] },
+ { fn: functionKeyPressed, scope: this, correctScope: true });
+ functionKeyListener.enable();
- var moveDisplay = DIV({ id: 'move' }, "[no move yet]");
- moveDisplay.style.color = 'white';
- moveDisplay.style.position = 'absolute';
- setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });
- appendChildNodes(document.body, moveDisplay);
- var d = loadJSONDoc("/game/" + gameID);
- d.addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
+ var moveDisplay = DIV({ id: 'move' }, "[no move yet]");
+ moveDisplay.style.color = 'white';
+ moveDisplay.style.position = 'absolute';
+ setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });
+ appendChildNodes(document.body, moveDisplay);
+ var d = loadJSONDoc("/game/" + gameID);
+ d.addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
}
1
0
Author: hhubner
Date: 2007-11-27 06:01:50 -0500 (Tue, 27 Nov 2007)
New Revision: 2291
Added:
branches/trunk-reorg/thirdparty/emacs/javascript.el
branches/trunk-reorg/thirdparty/emacs/js-mode.el
branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
Log:
Add Javascript development aids.
Added: branches/trunk-reorg/thirdparty/emacs/javascript.el
===================================================================
--- branches/trunk-reorg/thirdparty/emacs/javascript.el 2007-11-26 12:43:25 UTC (rev 2290)
+++ branches/trunk-reorg/thirdparty/emacs/javascript.el 2007-11-27 11:01:50 UTC (rev 2291)
@@ -0,0 +1,736 @@
+;;; javascript.el --- Major mode for editing JavaScript source text
+
+;; Copyright (C) 2006 Karl Landström
+
+;; Author: Karl Landström <kland(a)comhem.se>
+;; Maintainer: Karl Landström <kland(a)comhem.se>
+;; Version: 2.0 Beta 8
+;; Date: 2006-12-26
+;; Keywords: languages, oop
+
+;; This version contains a few font-lock fixes for quoted strings
+;; and regular expressions by Joost Diepenmaat <joost(a)zeekat.nl>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; The main features of this JavaScript mode are syntactic
+;; highlighting (enabled with `font-lock-mode' or
+;; `global-font-lock-mode'), automatic indentation and filling of
+;; comments.
+;;
+;; This package has (only) been tested with GNU Emacs 21.4 (the latest
+;; stable release).
+;;
+;; Installation:
+;;
+;; Put this file in a directory where Emacs can find it (`C-h v
+;; load-path' for more info). Then add the following lines to your
+;; Emacs initialization file:
+;;
+;; (add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode))
+;; (autoload 'javascript-mode "javascript" nil t)
+;;
+;; General Remarks:
+;;
+;; This mode assumes that block comments are not nested inside block
+;; comments and that strings do not contain line breaks.
+;;
+;; Exported names start with "javascript-" whereas private names start
+;; with "js-".
+;;
+;; Changes:
+;;
+;; See javascript.el.changelog.
+
+;;; Code:
+
+(require 'cc-mode)
+(require 'font-lock)
+(require 'newcomment)
+
+(defgroup javascript nil
+ "Customization variables for `javascript-mode'."
+ :tag "JavaScript"
+ :group 'languages)
+
+(defcustom javascript-indent-level 4
+ "Number of spaces for each indentation step."
+ :type 'integer
+ :group 'javascript)
+
+(defcustom javascript-auto-indent-flag t
+ "Automatic indentation with punctuation characters. If non-nil, the
+current line is indented when certain punctuations are inserted."
+ :type 'boolean
+ :group 'javascript)
+
+
+;; --- Keymap ---
+
+(defvar javascript-mode-map nil
+ "Keymap used in JavaScript mode.")
+
+(unless javascript-mode-map
+ (setq javascript-mode-map (make-sparse-keymap)))
+
+(when javascript-auto-indent-flag
+ (mapc (lambda (key)
+ (define-key javascript-mode-map key 'javascript-insert-and-indent))
+ '("{" "}" "(" ")" ":" ";" ",")))
+
+(defun javascript-insert-and-indent (key)
+ "Run command bound to key and indent current line. Runs the command
+bound to KEY in the global keymap and indents the current line."
+ (interactive (list (this-command-keys)))
+ (call-interactively (lookup-key (current-global-map) key))
+ (indent-according-to-mode))
+
+
+;; --- Syntax Table And Parsing ---
+
+(defvar javascript-mode-syntax-table
+ (let ((table (make-syntax-table)))
+ (c-populate-syntax-table table)
+
+ ;; switch off build-in quoted string detection
+ ;; since that just makes it really hard to detect
+ ;; regular expressions and comments
+ ;;
+ ;; this also has the benefit that multiline strings
+ ;; are now not recognized as strings (since javascript does
+ ;; not allow them)
+ (modify-syntax-entry ?' "." table)
+ (modify-syntax-entry ?\" "." table)
+
+ ;; The syntax class of underscore should really be `symbol' ("_")
+ ;; but that makes matching of tokens much more complex as e.g.
+ ;; "\\<xyz\\>" matches part of e.g. "_xyz" and "xyz_abc". Defines
+ ;; it as word constituent for now.
+ (modify-syntax-entry ?_ "w" table)
+
+ table)
+ "Syntax table used in JavaScript mode.")
+
+
+(defun js-re-search-forward-inner (regexp &optional bound count)
+ "Auxiliary function for `js-re-search-forward'."
+ (let ((parse)
+ (saved-point (point-min)))
+ (while (> count 0)
+ (re-search-forward regexp bound)
+ (setq parse (parse-partial-sexp saved-point (point)))
+ (cond ((nth 3 parse)
+ (re-search-forward
+ (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))
+ (save-excursion (end-of-line) (point)) t))
+ ((nth 7 parse)
+ (forward-line))
+ ((or (nth 4 parse)
+ (and (eq (char-before) ?\/) (eq (char-after) ?\*)))
+ (re-search-forward "\\*/"))
+ (t
+ (setq count (1- count))))
+ (setq saved-point (point))))
+ (point))
+
+
+(defun js-re-search-forward (regexp &optional bound noerror count)
+ "Search forward but ignore strings and comments. Invokes
+`re-search-forward' but treats the buffer as if strings and
+comments have been removed."
+ (let ((saved-point (point))
+ (search-expr
+ (cond ((null count)
+ '(js-re-search-forward-inner regexp bound 1))
+ ((< count 0)
+ '(js-re-search-backward-inner regexp bound (- count)))
+ ((> count 0)
+ '(js-re-search-forward-inner regexp bound count)))))
+ (condition-case err
+ (eval search-expr)
+ (search-failed
+ (goto-char saved-point)
+ (unless noerror
+ (error (error-message-string err)))))))
+
+
+(defun js-re-search-backward-inner (regexp &optional bound count)
+ "Auxiliary function for `js-re-search-backward'."
+ (let ((parse)
+ (saved-point (point-min)))
+ (while (> count 0)
+ (re-search-backward regexp bound)
+ (when (and (> (point) (point-min))
+ (save-excursion (backward-char) (looking-at "/[/*]")))
+ (forward-char))
+ (setq parse (parse-partial-sexp saved-point (point)))
+ (cond ((nth 3 parse)
+ (re-search-backward
+ (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))
+ (save-excursion (beginning-of-line) (point)) t))
+ ((nth 7 parse)
+ (goto-char (nth 8 parse)))
+ ((or (nth 4 parse)
+ (and (eq (char-before) ?/) (eq (char-after) ?*)))
+ (re-search-backward "/\\*"))
+ (t
+ (setq count (1- count))))))
+ (point))
+
+
+(defun js-re-search-backward (regexp &optional bound noerror count)
+ "Search backward but ignore strings and comments. Invokes
+`re-search-backward' but treats the buffer as if strings and
+comments have been removed."
+ (let ((saved-point (point))
+ (search-expr
+ (cond ((null count)
+ '(js-re-search-backward-inner regexp bound 1))
+ ((< count 0)
+ '(js-re-search-forward-inner regexp bound (- count)))
+ ((> count 0)
+ '(js-re-search-backward-inner regexp bound count)))))
+ (condition-case err
+ (eval search-expr)
+ (search-failed
+ (goto-char saved-point)
+ (unless noerror
+ (error (error-message-string err)))))))
+
+
+(defun js-continued-var-decl-list-p ()
+ "Return non-nil if point is inside a continued variable declaration
+list."
+ (interactive)
+ (let ((start (save-excursion (js-re-search-backward "\\<var\\>" nil t))))
+ (and start
+ (save-excursion (re-search-backward "\n" start t))
+ (not (save-excursion
+ (js-re-search-backward
+ ";\\|[^, \t][ \t]*\\(/[/*]\\|$\\)" start t))))))
+
+
+;; --- Font Lock ---
+
+(defun js-inside-param-list-p ()
+ "Return non-nil if point is inside a function parameter list."
+ (condition-case err
+ (save-excursion
+ (up-list -1)
+ (and (looking-at "(")
+ (progn (backward-word 1)
+ (or (looking-at "function")
+ (progn (backward-word 1) (looking-at "function"))))))
+ (error nil)))
+
+
+(defconst js-function-heading-1-re
+ "^[ \t]*function[ \t]+\\(\\w+\\)"
+ "Regular expression matching the start of a function header.")
+
+(defconst js-function-heading-2-re
+ "^[ \t]*\\(\\w+\\)[ \t]*:[ \t]*function\\>"
+ "Regular expression matching the start of a function entry in
+ an associative array.")
+
+(defconst js-keyword-re
+ (regexp-opt '("abstract" "break" "case" "catch" "class" "const"
+ "continue" "debugger" "default" "delete" "do" "else"
+ "enum" "export" "extends" "final" "finally" "for"
+ "function" "goto" "if" "implements" "import" "in"
+ "instanceof" "interface" "native" "new" "package"
+ "private" "protected" "public" "return" "static"
+ "super" "switch" "synchronized" "this" "throw"
+ "throws" "transient" "try" "typeof" "var" "void"
+ "volatile" "while" "with") 'words)
+ "Regular expression matching any JavaScript keyword.")
+
+(defconst js-basic-type-re
+ (regexp-opt '("boolean" "byte" "char" "double" "float" "int" "long"
+ "short" "void") 'words)
+ "Regular expression matching any predefined type in JavaScript.")
+
+(defconst js-constant-re
+ (regexp-opt '("false" "null" "true") 'words)
+ "Regular expression matching any future reserved words in JavaScript.")
+
+
+(defconst js-quoted-string-re "\\(\".*?[^\\]\"\\|'.*?[^\\]'\\)")
+(defconst js-quoted-string-or-regex-re "\\(/.*?[^\\]/\\w*\\|\".*?[^\\]\"\\|'.*?[^\\]'\\)")
+
+
+(defconst js-font-lock-keywords-1
+ (list
+ "\\<import\\>"
+ (list js-function-heading-1-re 1 font-lock-function-name-face)
+ (list js-function-heading-2-re 1 font-lock-function-name-face)
+
+ ;; detect literal strings following a + operator
+ (list (concat "+[ \t]*" js-quoted-string-re) 1 font-lock-string-face)
+
+ ;; detect literal strings used in "literal object" keys
+ (list (concat "[,{][ \t]*" js-quoted-string-re "[ \t]*:" ) 1 font-lock-string-face)
+
+ ;; detects strings and regexes when assigned, passed, returned
+ ;; used as an object key string (i.e. bla["some string"]), when used
+ ;; as a literal object value (i.e. key: "string"), used as an array
+ ;; element, or when they appear as the first expression on a line
+ ;; and a few other hairy cases
+ (list (concat "[=(:,;[][ \t]*" js-quoted-string-or-regex-re) 1 font-lock-string-face)
+ (list (concat "^[ \t]*" js-quoted-string-or-regex-re) 1 font-lock-string-face)
+ (list (concat "return[ \t]*" js-quoted-string-or-regex-re) 1 font-lock-string-face)
+
+ ;; detect "autoquoted" object properties... clases with "switch { ... default: }"
+ ;; may not be worth the trouble
+ (list "\\(^[ \t]*\\|[,{][ \t]*\\)\\(\\w+\\):" 2 font-lock-string-face))
+
+ "Level one font lock.")
+
+(defconst js-font-lock-keywords-2
+ (append js-font-lock-keywords-1
+ (list (list js-keyword-re 1 font-lock-keyword-face)
+ (cons js-basic-type-re font-lock-type-face)
+ (cons js-constant-re font-lock-constant-face)))
+ "Level two font lock.")
+
+
+;; Limitations with variable declarations: There seems to be no
+;; sensible way to highlight variables occuring after an initialized
+;; variable in a variable list. For instance, in
+;;
+;; var x, y = f(a, b), z
+;;
+;; z will not be highlighted.
+
+(defconst js-font-lock-keywords-3
+ (append
+ js-font-lock-keywords-2
+ (list
+
+ ;; variable declarations
+ (list
+ (concat "\\<\\(const\\|var\\)\\>\\|" js-basic-type-re)
+ (list "\\(\\w+\\)[ \t]*\\([=;].*\\|,\\|/[/*]\\|$\\)"
+ nil
+ nil
+ '(1 font-lock-variable-name-face)))
+
+ ;; continued variable declaration list
+ (list
+ (concat "^[ \t]*\\w+[ \t]*\\([,;=]\\|/[/*]\\|$\\)")
+ (list "\\(\\w+\\)[ \t]*\\([=;].*\\|,\\|/[/*]\\|$\\)"
+ '(if (save-excursion (backward-char) (js-continued-var-decl-list-p))
+ (backward-word 1)
+ (end-of-line))
+ '(end-of-line)
+ '(1 font-lock-variable-name-face)))
+
+ ;; formal parameters
+ (list
+ (concat "\\<function\\>\\([ \t]+\\w+\\)?[ \t]*([ \t]*\\w")
+ (list "\\(\\w+\\)\\([ \t]*).*\\)?"
+ '(backward-char)
+ '(end-of-line)
+ '(1 font-lock-variable-name-face)))
+
+ ;; continued formal parameter list
+ (list
+ (concat "^[ \t]*\\w+[ \t]*[,)]")
+ (list "\\w+"
+ '(if (save-excursion (backward-char) (js-inside-param-list-p))
+ (backward-word 1)
+ (end-of-line))
+ '(end-of-line)
+ '(0 font-lock-variable-name-face)))))
+ "Level three font lock.")
+
+(defconst js-font-lock-keywords
+ '(js-font-lock-keywords-3 js-font-lock-keywords-1 js-font-lock-keywords-2
+ js-font-lock-keywords-3)
+ "See `font-lock-keywords'.")
+
+
+;; --- Indentation ---
+
+(defconst js-possibly-braceless-keyword-re
+ (regexp-opt
+ '("catch" "do" "else" "finally" "for" "if" "try" "while" "with")
+ 'words)
+ "Regular expression matching keywords that are optionally
+ followed by an opening brace.")
+
+(defconst js-indent-operator-re
+ (concat "[-+*/%<>=&^|?:]\\([^-+*/]\\|$\\)\\|"
+ (regexp-opt '("in" "instanceof") 'words))
+ "Regular expression matching operators that affect indentation
+ of continued expressions.")
+
+
+(defun js-looking-at-operator-p ()
+ "Return non-nil if text after point is an operator (that is not
+a comma)."
+ (save-match-data
+ (and (looking-at js-indent-operator-re)
+ (or (not (looking-at ":"))
+ (save-excursion
+ (and (js-re-search-backward "[?:{]\\|\\<case\\>" nil t)
+ (looking-at "?")))))))
+
+
+(defun js-continued-expression-p ()
+ "Returns non-nil if the current line continues an expression."
+ (save-excursion
+ (back-to-indentation)
+ (or (js-looking-at-operator-p)
+ (and (js-re-search-backward "\n" nil t)
+ (progn
+ (skip-chars-backward " \t")
+ (backward-char)
+ (and (> (point) (point-min))
+ (save-excursion (backward-char) (not (looking-at "[/*]/")))
+ (js-looking-at-operator-p)
+ (and (progn (backward-char)
+ (not (looking-at "++\\|--\\|/[/*]"))))))))))
+
+
+(defun js-end-of-do-while-loop-p ()
+ "Returns non-nil if word after point is `while' of a do-while
+statement, else returns nil. A braceless do-while statement
+spanning several lines requires that the start of the loop is
+indented to the same column as the current line."
+ (interactive)
+ (save-excursion
+ (save-match-data
+ (when (looking-at "\\s-*\\<while\\>")
+ (if (save-excursion
+ (skip-chars-backward "[ \t\n]*}")
+ (looking-at "[ \t\n]*}"))
+ (save-excursion
+ (backward-list) (backward-word 1) (looking-at "\\<do\\>"))
+ (js-re-search-backward "\\<do\\>" (point-at-bol) t)
+ (or (looking-at "\\<do\\>")
+ (let ((saved-indent (current-indentation)))
+ (while (and (js-re-search-backward "^[ \t]*\\<" nil t)
+ (/= (current-indentation) saved-indent)))
+ (and (looking-at "[ \t]*\\<do\\>")
+ (not (js-re-search-forward
+ "\\<while\\>" (point-at-eol) t))
+ (= (current-indentation) saved-indent)))))))))
+
+
+(defun js-ctrl-statement-indentation ()
+ "Returns the proper indentation of the current line if it
+starts the body of a control statement without braces, else
+returns nil."
+ (save-excursion
+ (back-to-indentation)
+ (when (save-excursion
+ (and (not (looking-at "[{]"))
+ (progn
+ (js-re-search-backward "[[:graph:]]" nil t)
+ (forward-char)
+ (when (= (char-before) ?\)) (backward-list))
+ (skip-syntax-backward " ")
+ (skip-syntax-backward "w")
+ (looking-at js-possibly-braceless-keyword-re))
+ (not (js-end-of-do-while-loop-p))))
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (+ (current-indentation) javascript-indent-level)))))
+
+
+(defun js-proper-indentation (parse-status)
+ "Return the proper indentation for the current line."
+ (save-excursion
+ (back-to-indentation)
+ (let ((ctrl-stmt-indent (js-ctrl-statement-indentation))
+ (same-indent-p (looking-at "[]})]\\|\\<case\\>\\|\\<default\\>"))
+ (continued-expr-p (js-continued-expression-p)))
+ (cond (ctrl-stmt-indent)
+ ((js-continued-var-decl-list-p)
+ (js-re-search-backward "\\<var\\>" nil t)
+ (+ (current-indentation) javascript-indent-level))
+ ((nth 1 parse-status)
+ (goto-char (nth 1 parse-status))
+ (if (looking-at "[({[][ \t]*\\(/[/*]\\|$\\)")
+ (progn
+ (skip-syntax-backward " ")
+ (when (= (char-before) ?\)) (backward-list))
+ (back-to-indentation)
+ (cond (same-indent-p
+ (current-column))
+ (continued-expr-p
+ (+ (current-column) (* 2 javascript-indent-level)))
+ (t
+ (+ (current-column) javascript-indent-level))))
+ (unless same-indent-p
+ (forward-char)
+ (skip-chars-forward " \t"))
+ (current-column)))
+ (continued-expr-p javascript-indent-level)
+ (t 0)))))
+
+
+(defun javascript-indent-line ()
+ "Indent the current line as JavaScript source text."
+ (interactive)
+ (let ((parse-status
+ (save-excursion (parse-partial-sexp (point-min) (point-at-bol))))
+ (offset (- (current-column) (current-indentation))))
+ (when (not (nth 8 parse-status))
+ (indent-line-to (js-proper-indentation parse-status))
+ (when (> offset 0) (forward-char offset)))))
+
+
+;; --- Filling ---
+
+;; FIXME: It should be possible to use the more sofisticated function
+;; `c-fill-paragraph' in `cc-cmds.el' instead. However, just setting
+;; `fill-paragraph-function' to `c-fill-paragraph' does not work;
+;; inside `c-fill-paragraph', `fill-paragraph-function' evaluates to
+;; nil!?
+
+(defun js-backward-paragraph ()
+ "Move backward to start of paragraph. Postcondition: Point is at
+beginning of buffer or the previous line contains only whitespace."
+ (forward-line -1)
+ (while (not (or (bobp) (looking-at "^[ \t]*$")))
+ (forward-line -1))
+ (when (not (bobp)) (forward-line 1)))
+
+
+(defun js-forward-paragraph ()
+ "Move forward to end of paragraph. Postcondition: Point is at
+end of buffer or the next line contains only whitespace."
+ (forward-line 1)
+ (while (not (or (eobp) (looking-at "^[ \t]*$")))
+ (forward-line 1))
+ (when (not (eobp)) (backward-char 1)))
+
+
+(defun js-fill-block-comment-paragraph (parse-status justify)
+ "Fill current paragraph as a block comment. PARSE-STATUS is the
+result of `parse-partial-regexp' from beginning of buffer to
+point. JUSTIFY has the same meaning as in `fill-paragraph'."
+ (let ((offset (save-excursion
+ (goto-char (nth 8 parse-status)) (current-indentation))))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (save-excursion
+ (goto-char (nth 8 parse-status)) (point-at-bol))
+ (save-excursion
+ (goto-char (nth 8 parse-status))
+ (re-search-forward "*/")))
+ (narrow-to-region (save-excursion
+ (js-backward-paragraph)
+ (when (looking-at "^[ \t]*$") (forward-line 1))
+ (point))
+ (save-excursion
+ (js-forward-paragraph)
+ (when (looking-at "^[ \t]*$") (backward-char))
+ (point)))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (delete-horizontal-space)
+ (forward-line 1))
+ (let ((fill-column (- fill-column offset))
+ (fill-paragraph-function nil))
+ (fill-paragraph justify))
+
+ ;; In Emacs 21.4 as opposed to CVS Emacs 22,
+ ;; `fill-paragraph' seems toadd a newline at the end of the
+ ;; paragraph. Remove it!
+ (goto-char (point-max))
+ (when (looking-at "^$") (backward-delete-char 1))
+
+ (goto-char (point-min))
+ (while (not (eobp))
+ (indent-to offset)
+ (forward-line 1))))))
+
+
+(defun js-sline-comment-par-start ()
+ "Return point at the beginning of the line where the current
+single-line comment paragraph starts."
+ (save-excursion
+ (beginning-of-line)
+ (while (and (not (bobp))
+ (looking-at "^[ \t]*//[ \t]*[[:graph:]]"))
+ (forward-line -1))
+ (unless (bobp) (forward-line 1))
+ (point)))
+
+
+(defun js-sline-comment-par-end ()
+ "Return point at end of current single-line comment paragraph."
+ (save-excursion
+ (beginning-of-line)
+ (while (and (not (eobp))
+ (looking-at "^[ \t]*//[ \t]*[[:graph:]]"))
+ (forward-line 1))
+ (unless (bobp) (backward-char))
+ (point)))
+
+
+(defun js-sline-comment-offset (line)
+ "Return the column at the start of the current single-line
+comment paragraph."
+ (save-excursion
+ (goto-line line)
+ (re-search-forward "//" (point-at-eol))
+ (goto-char (match-beginning 0))
+ (current-column)))
+
+
+(defun js-sline-comment-text-offset (line)
+ "Return the column at the start of the text of the current
+single-line comment paragraph."
+ (save-excursion
+ (goto-line line)
+ (re-search-forward "//[ \t]*" (point-at-eol))
+ (current-column)))
+
+
+(defun js-at-empty-sline-comment-p ()
+ "Return non-nil if inside an empty single-line comment."
+ (and (save-excursion
+ (beginning-of-line)
+ (not (looking-at "^.*//.*[[:graph:]]")))
+ (save-excursion
+ (re-search-backward "//" (point-at-bol) t))))
+
+
+(defun js-fill-sline-comments (parse-status justify)
+ "Fill current paragraph as a sequence of single-line comments.
+PARSE-STATUS is the result of `parse-partial-regexp' from
+beginning of buffer to point. JUSTIFY has the same meaning as in
+`fill-paragraph'."
+ (when (not (js-at-empty-sline-comment-p))
+ (let* ((start (js-sline-comment-par-start))
+ (start-line (1+ (count-lines (point-min) start)))
+ (end (js-sline-comment-par-end))
+ (offset (js-sline-comment-offset start-line))
+ (text-offset (js-sline-comment-text-offset start-line)))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (re-search-forward "^[ \t]*//[ \t]*" nil t)
+ (replace-match "")
+ (forward-line 1))
+ (let ((fill-paragraph-function nil)
+ (fill-column (- fill-column text-offset)))
+ (fill-paragraph justify))
+
+ ;; In Emacs 21.4 as opposed to CVS Emacs 22,
+ ;; `fill-paragraph' seems toadd a newline at the end of the
+ ;; paragraph. Remove it!
+ (goto-char (point-max))
+ (when (looking-at "^$") (backward-delete-char 1))
+
+ (goto-char (point-min))
+ (while (not (eobp))
+ (indent-to offset)
+ (insert "//")
+ (indent-to text-offset)
+ (forward-line 1)))))))
+
+
+(defun js-trailing-comment-p (parse-status)
+ "Return non-nil if inside a trailing comment. PARSE-STATUS is
+the result of `parse-partial-regexp' from beginning of buffer to
+point."
+ (save-excursion
+ (when (nth 4 parse-status)
+ (goto-char (nth 8 parse-status))
+ (skip-chars-backward " \t")
+ (not (bolp)))))
+
+
+(defun js-block-comment-p (parse-status)
+ "Return non-nil if inside a block comment. PARSE-STATUS is the
+result of `parse-partial-regexp' from beginning of buffer to
+point."
+ (save-excursion
+ (save-match-data
+ (when (nth 4 parse-status)
+ (goto-char (nth 8 parse-status))
+ (looking-at "/\\*")))))
+
+
+(defun javascript-fill-paragraph (&optional justify)
+ "If inside a comment, fill the current comment paragraph.
+Trailing comments are ignored."
+ (interactive)
+ (let ((parse-status (parse-partial-sexp (point-min) (point))))
+ (when (and (nth 4 parse-status)
+ (not (js-trailing-comment-p parse-status)))
+ (if (js-block-comment-p parse-status)
+ (js-fill-block-comment-paragraph parse-status justify)
+ (js-fill-sline-comments parse-status justify))))
+ t)
+
+
+;; --- Imenu ---
+
+(defconst js-imenu-generic-expression
+ (list
+ (list
+ nil
+ "function\\s-+\\(\\w+\\)\\s-*("
+ 1))
+ "Regular expression matching top level procedures. Used by imenu.")
+
+
+;; --- Main Function ---
+
+;;;###autoload
+(defun javascript-mode ()
+ "Major mode for editing JavaScript source text.
+
+Key bindings:
+
+\\{javascript-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+
+ (use-local-map javascript-mode-map)
+ (set-syntax-table javascript-mode-syntax-table)
+ (set (make-local-variable 'indent-line-function) 'javascript-indent-line)
+ (set (make-local-variable 'font-lock-defaults) (list js-font-lock-keywords))
+
+ (set (make-local-variable 'parse-sexp-ignore-comments) t)
+
+ ;; Comments
+ (setq comment-start "// ")
+ (setq comment-end "")
+ (set (make-local-variable 'fill-paragraph-function)
+ 'javascript-fill-paragraph)
+
+ ;; Imenu
+ (setq imenu-case-fold-search nil)
+ (set (make-local-variable 'imenu-generic-expression)
+ js-imenu-generic-expression)
+
+ (setq major-mode 'javascript-mode)
+ (setq mode-name "JavaScript")
+ (run-hooks 'javascript-mode-hook))
+
+
+(provide 'javascript-mode)
+;;; javascript.el ends here
Added: branches/trunk-reorg/thirdparty/emacs/js-mode.el
===================================================================
--- branches/trunk-reorg/thirdparty/emacs/js-mode.el 2007-11-26 12:43:25 UTC (rev 2290)
+++ branches/trunk-reorg/thirdparty/emacs/js-mode.el 2007-11-27 11:01:50 UTC (rev 2291)
@@ -0,0 +1,759 @@
+;;; js-mode.el --- minor mode for interacting with Mozilla
+;;
+;; Copyright (C) 2004 Helmut Eller
+;;
+;; You can redistribute this file under the terms of the GNU General
+;; Public License.
+;;
+
+;;; Commentary:
+;;
+;; This file implements some commands for interacting with Mozilla
+;; from Emacs. Emacs uses a TCP connection to communicate with
+;; Mozilla. The available commands are:
+;;
+;; C-c : Sends a piece of Javascript code to Mozilla for evaluation
+;; and prints the result.
+;;
+;; C-M-x Evaluates the current function defintion in Mozilla.
+;; C-c C-e Evaluates the current line.
+;; C-c C-r Evaluates the current region
+;;
+;; C-c C-l Loads a javascript file.
+;;
+;; M-. Finds the source location of function definitions.
+;; M-, Returns to the origin of the last M-. command.
+;;
+;; C-c C-d Can be used to inspect the Javascript objects.
+;;
+;; This file also implements a simple debugger. The debugger is
+;; invoked when an error occurs. The debugger can show the backtrace,
+;; the values of local variables in frames and the source location
+;; corresponding to frames. It is also possible to invoke the
+;; debugger exlicitly by inserting the "debugger" keyword in javacript
+;; code. Furthermore, the debugger can be invoked on throw
+;; statements. Use C-c C-b t to enable debugging on throw.
+;;
+;; Installation:
+;;
+;; - First you have to load the server in Mozilla. You can add the
+;; file emacsslave.js to your rc file or make the neccessary
+;; modifications to conkeror itself. The server can be started with
+;; M-x start-server in Conkeror.
+;;
+;; - Put this file into your Emacs load path add something like this
+;; to your .emacs:
+;;
+;; (add-hook 'javascript-mode-hook 'js-mode)
+;; (autoload 'js-mode "js-mode" nil t)
+;;
+;; - Then open a javascript file and make sure js-mode is enabled. To
+;; connect to Mozilla type M-x js-connect.
+;;
+;; - Then you can try the commands from above.
+;;
+;;;
+;;
+;; The code should work in Emacs 20.7 and Emacs 21. XEmacs
+;; compatibility is a bit problematic at the moment.
+
+;;; Code:
+
+(eval-and-compile
+ (require 'cl)
+ (unless (fboundp 'define-minor-mode)
+ (require 'easy-mmode)
+ (defalias 'define-minor-mode 'easy-mmode-define-minor-mode)))
+
+(require 'pp)
+(require 'cc-mode)
+
+(defvar js-mode-map (make-sparse-keymap))
+
+(define-minor-mode js-mode
+ "Minor mode for interacting with Mozilla.
+
+Use \\[js-connect] to establish a connection with Mozilla.
+Some other commands are:
+\\{js-mode-map}"
+ nil nil ())
+
+(add-to-list 'minor-mode-alist
+ '(js-mode (js-mozilla-connection " [js]" " js")))
+
+(define-key js-mode-map (kbd "M-C-x") 'js-eval-defun)
+(define-key js-mode-map (kbd "C-c :") 'js-interactive-eval)
+(define-key js-mode-map (kbd "C-c C-e") 'js-eval-current-line)
+(define-key js-mode-map (kbd "C-c C-r") 'js-eval-region)
+(define-key js-mode-map (kbd "C-c C-l") 'js-load-file)
+(define-key js-mode-map (kbd "M-.") 'js-find-definitions)
+(define-key js-mode-map (kbd "M-,") 'js-pop-find-definition-stack)
+(define-key js-mode-map (kbd "C-c C-d") 'js-inspect)
+(define-key js-mode-map (kbd "C-c C-b t") 'js-toggle-break-on-throw)
+(define-key js-mode-map (kbd "C-c C-b C-t") 'js-toggle-break-on-throw)
+
+
+;;; Generally useful stuff
+
+(defun js-symbol-at-point ()
+ "Return the symbol at point as string, or nil."
+ (save-restriction
+ (save-excursion
+ (let ((string (thing-at-point 'symbol)))
+ (and string (not (equal string ""))
+ (substring-no-properties string))))))
+
+(defun js-read-symbol (prompt &optional query)
+ "Either read a symbol name or choose the one at point.
+The user is prompted if a prefix argument is in effect, if there is no
+symbol at point, or if QUERY is non-nil."
+ (cond ((or current-prefix-arg query (not (js-symbol-at-point)))
+ (read-from-minibuffer prompt (js-symbol-at-point)))
+ (t (js-symbol-at-point))))
+
+(make-variable-buffer-local
+ (defvar js-old-window-config nil
+ "The window configuration before when before temp-buffer was displayed.
+Buffer local in temp-buffers."))
+
+
+
+;;; Networking
+
+(defvar js-mozilla-connection nil)
+
+(defun js-connect (port)
+ "Connect to Mozilla on PORT."
+ (interactive (list (read-from-minibuffer "Port: " "4007" nil t)))
+ (let ((socket (js-net-connect port)))
+ (setq js-mozilla-connection socket)
+ (js-eval `(mozilla_info) (lambda (info)
+ (message "Connected to: %s" (car info))))))
+
+(defun js-disconnect ()
+ "Close the connection to Mozilla."
+ (interactive)
+ (delete-process js-mozilla-connection)
+ (setq js-mozilla-connection nil))
+
+(defun js-connection ()
+ (when (not js-mozilla-connection)
+ (error "Not connected"))
+ js-mozilla-connection)
+
+(defun js-make-net-buffer (name)
+ "Make a buffer suitable for a network process."
+ (let ((buffer (generate-new-buffer name)))
+ (with-current-buffer buffer
+ (when (fboundp 'set-buffer-multibyte)
+ (set-buffer-multibyte nil))
+ (buffer-disable-undo))
+ buffer))
+
+(defun js-net-connect (port)
+ (let* ((socket (open-network-stream "Mozilla" nil "localhost" port))
+ (buffer (js-make-net-buffer "*mozilla*")))
+ (set-process-buffer socket buffer)
+ (set-process-filter socket 'js-net-filter)
+ (set-process-sentinel socket 'js-net-sentinel)
+ (when (fboundp 'set-process-coding-system)
+ (set-process-coding-system socket 'no-conversion 'no-conversion))
+ socket))
+
+(defun js-net-send (string connection)
+ (let ((string (concat (js-net-encode-length (length string)) string)))
+ (process-send-string connection (string-make-unibyte string))))
+
+(defun js-net-encode-length (n)
+ (format "%06x" n))
+
+(defun js-net-filter (process string)
+ "Accept output from the socket and input all complete messages."
+ (with-current-buffer (process-buffer process)
+ (save-excursion
+ (goto-char (point-max))
+ (insert string))
+ (goto-char (point-min))
+ (js-process-available-input)))
+
+(defun js-process-available-input ()
+ "Process all complete messages that have arrived from Mozilla."
+ (unwind-protect
+ (when (js-connection)
+ (with-current-buffer (process-buffer (js-connection))
+ (while (js-net-have-input-p)
+ (let ((event (condition-case error (js-net-read)
+ (error (js-net-panic error)))))
+ (save-current-buffer
+ (js-dispatch-event event))))))
+ (when (js-connection)
+ (with-current-buffer (process-buffer (js-connection))
+ (when (js-net-have-input-p)
+ (run-at-time 0 nil 'js-process-available-input))))))
+
+(defun js-net-panic (error)
+ (message "net-read error: %S" error)
+ (let ((string (buffer-string)))
+ (ignore-errors
+ (js-disconnect)
+ (kill-buffer (current-buffer)))
+ (ding)
+ (sleep-for 2)
+ (with-current-buffer (generate-new-buffer "*saved-connecton-buffer*")
+ (insert string)
+ (error "PANIC!" error))))
+
+(defun js-net-have-input-p ()
+ "Return true if a complete message is available."
+ (and (>= (buffer-size) 6)
+ (>= (- (buffer-size) 6) (js-net-read-length))))
+
+(defun js-net-read-length ()
+ (string-to-number (buffer-substring (point) (+ (point) 6)) 16))
+
+(defun js-net-read ()
+ (let* ((length (js-net-read-length))
+ (start (+ 6 (point)))
+ (end (+ start length)))
+ (let ((string (buffer-substring start end)))
+ (prog1 (read string)
+ (delete-region (point-min) end)))))
+
+(defun js-net-sentinel (process message)
+ (message "Mozilla connection closed unexpectedly: %s" message)
+ (when (eq process js-mozilla-connection)
+ (setq js-mozilla-connection nil))
+ (kill-buffer (process-buffer process)))
+
+(defun js-send (term)
+ (js-log-event (list 'send term))
+ (js-net-send (js-term-to-string term) (js-connection)))
+
+(defun js-term-to-string (term)
+ (etypecase term
+ (symbol (concat "'" (symbol-name term) "'"))
+ (string (with-temp-buffer
+ (let ((print-escape-nonascii t)
+ (print-escape-newlines t))
+ (prin1 term (current-buffer))
+ (buffer-string))))
+ (number (number-to-string term))
+ (cons (concat "[" (mapconcat 'js-term-to-string term ", ") "]"))))
+
+;;; Event logging
+
+(defvar js-log-events t
+ "*Log protocol events to the *js-events* buffer.")
+
+(defvar js-log-buffer-name "*js-events*"
+ "The name of the js event buffer.")
+
+(defun js-log-event (event)
+ "Record the fact that EVENT occurred."
+ (when js-log-events
+ (with-current-buffer (js-events-buffer)
+ ;; trim?
+ (when (> (buffer-size) 100000)
+ (goto-char (/ (buffer-size) 2))
+ (re-search-forward "^(" nil t)
+ (delete-region (point-min) (point)))
+ (goto-char (point-max))
+ (save-excursion
+ (js-pprint-event event (current-buffer)))
+ (goto-char (point-max)))))
+
+(defun js-pprint-event (event buffer)
+ "Pretty print EVENT in BUFFER with limited depth and width."
+ (let ((print-length 20)
+ (print-level 6)
+ (pp-escape-newlines t))
+ (pp event buffer)))
+
+(defun js-events-buffer ()
+ (get-buffer-create js-log-buffer-name))
+
+;;; RPCing
+
+(defvar js-continuations ()
+ "An alist of (ID . FUNCTION) functions waiting for results.")
+
+(defvar js-continuation-counter 0
+ "Counter to generate serial number for continuations.")
+
+(defun js-dispatch-event (event)
+ (js-log-event event)
+ (apply (car event) (cdr event)))
+
+(defun js-eval (term cont)
+ "Evaluate term in Mozilla and call the function CONT with the result."
+ (let ((id (incf js-continuation-counter))
+ (cont (lexical-let ((cont cont) (buffer (current-buffer)))
+ (lambda (status value)
+ (with-current-buffer (js-buffer-for-eval buffer)
+ (ecase status
+ (ok (funcall cont value))
+ (error (message "Evaluation aborted: %s" value))))))))
+ (push (cons id cont) js-continuations)
+ (js-send `(eval_for_emacs ,term ,id))))
+
+(defun js-buffer-for-eval (saved-buffer)
+ (let ((alive (buffer-name saved-buffer)))
+ (cond (alive saved-buffer)
+ (t (generate-new-buffer (format "*killed %s*" saved-buffer))))))
+
+(defun js-return (id status value)
+ (let ((rec (assq id js-continuations)))
+ (cond (rec (setq js-continuations (delete rec js-continuations))
+ (funcall (cdr rec) status value))
+ (t
+ (error "Unexpected reply: %S %S" id value)))))
+
+(defvar js-wait-tags ())
+
+(defun js-eval-wait (term)
+ "Evaluate TERM in Mozilla and wait until the result is available."
+ (let* ((id (incf js-continuation-counter))
+ (tag (gensym))
+ (unwind (lexical-let ((tag tag))
+ (lambda (status value)
+ (unless (memq tag js-wait-tags)
+ (error "Wait-tag not active: %S." tag))
+ (throw tag (list status value))))))
+ (push (cons id unwind) js-continuations)
+ (js-send `(eval_for_emacs ,term ,id))
+ (destructuring-bind (status value) (js-wait tag)
+ (ecase status
+ (ok value)
+ (error (error "Syncronous evaluation aborted: %s" value))))))
+
+(defun js-wait (wait-tag)
+ (let ((js-wait-tags (cons wait-tag js-wait-tags))
+ (debug-on-quit t)
+ (inhibit-quit nil))
+ (catch wait-tag
+ (while t (accept-process-output nil 0 10000)))))
+
+(defun js-show-result (result)
+ (message "%S" result))
+
+;;; Evaluation Commands
+
+(defun js-beginning-of-defun ()
+ "Move to the beginning of the current function.
+Point is placed before foo in the folling example:
+
+foo = function (bar)
+{
+ ...
+}"
+ (interactive)
+ (c-beginning-of-defun 1)
+ (beginning-of-line)
+ (when (looking-at "[ \t]*{")
+ (forward-line -1)))
+
+(defconst js-identifier
+ "[a-zA-Z_\\$][a-zA-Z0-9_\\$]*"
+ "Expression for matching Javascript identifiers.")
+
+(defun js-hack-defun (string)
+ "If STRING looks like function <name> { convert it to <name> = function {"
+ (cond ((string-match (concat "^function\\s +\\(" js-identifier "\\)\\s *(")
+ string)
+ (format "%s = function %s" (match-string 1 string)
+ (substring string (position ?\( string))))
+ (t string)))
+
+(defun js-eval-defun ()
+ "Evaluate the current function."
+ (interactive)
+ (save-excursion
+ (c-end-of-defun)
+ (let ((end (point)))
+ (js-beginning-of-defun)
+ (let ((string (buffer-substring-no-properties (point) end)))
+ (js-eval `(interactive_eval ,(js-hack-defun string))
+ (lambda (result) (message "%s" result)))))))
+
+(defun js-interactive-eval (string &optional insertp)
+ (interactive "Mjavascript eval: \nP")
+ (cond (insertp
+ (beginning-of-line 2)
+ (js-eval `(interactive_eval ,string) #'insert))
+ (t
+ (js-eval `(interactive_eval ,string)
+ (lambda (result) (message "%s" result))))))
+
+(defun js-eval-region (start end &optional insertp)
+ "Eval region in Mozilla.
+Insert the result in the current buffer when called with a prefix argument."
+ (interactive "r\nP")
+ (js-interactive-eval (buffer-substring-no-properties start end) insertp))
+
+(defun js-eval-current-line (&optional insertp)
+ "Eval the current line. See `js-eval-region'."
+ (interactive "P")
+ (js-eval-region (line-beginning-position) (line-end-position) insertp))
+
+(defun js-load-file (filename)
+ "Load the javascript file FILENAME in Mozilla."
+ (interactive (list (read-file-name "Load file: " nil nil
+ nil (file-name-nondirectory
+ (buffer-file-name)))))
+ (let ((url (concat "file:" (expand-file-name filename))))
+ (js-eval `(load_file_for_emacs ,url)
+ (lambda (message)
+ (message "Loaded: %s" message)))))
+
+
+;;;; Find definitions
+
+(defvar js-find-definition-history-ring (make-ring 20)
+ "History ring recording the definition-finding \"stack\".")
+
+(defun js-push-definition-stack ()
+ "Add MARKER to the edit-definition history stack.
+If MARKER is nil, use the point."
+ (ring-insert-at-beginning js-find-definition-history-ring (point-marker)))
+
+(defun js-pop-find-definition-stack ()
+ "Pop the edit-definition stack and goto the location."
+ (interactive)
+ (unless (ring-empty-p js-find-definition-history-ring)
+ (let* ((marker (ring-remove js-find-definition-history-ring))
+ (buffer (marker-buffer marker)))
+ (if (buffer-live-p buffer)
+ (progn (switch-to-buffer buffer)
+ (goto-char (marker-position marker)))
+ ;; If this buffer was deleted, recurse to try the next one
+ (js-pop-find-definition-stack)))))
+
+(defun js-find-definitions (name)
+ "Lookup the definition of the symbol at point."
+ (interactive (list (js-read-symbol "Name: ")))
+ (js-eval `(find_definitions ,name)
+ (lexical-let ((name name))
+ (lambda (defs) (js-show-definitions name defs)))))
+
+(defun js-show-definitions (name defs)
+ (unless (not defs)
+ (js-push-definition-stack))
+ (cond ((null defs) (message "No definitions for: %s" name) (ding))
+ ((null (cdr defs)) (js-goto-definition (car defs)))
+ (t (js-display-multiple-definitions defs))))
+
+(defun js-goto-definition (definition &optional other-window)
+ (destructuring-bind (filename line) definition
+ (let ((buffer (js-find-source-buffer filename)))
+ (cond (other-window (switch-to-buffer-other-window buffer))
+ (t (switch-to-buffer buffer)))
+ (goto-line line))))
+
+(defun js-find-source-buffer (filename)
+ (cond ((string-match "^file:" filename)
+ (find-file-noselect (substring filename (length "file:"))))
+ ((string-match "^\\(http\\|chrome\\):" filename)
+ (or (get-buffer filename)
+ (with-current-buffer (get-buffer-create filename)
+ (insert (js-eval-wait `(load_source ,filename)))
+ (not-modified)
+ (setq buffer-read-only t)
+ (setq buffer-file-name filename)
+ (normal-mode)
+ (js-mode 1)
+ (current-buffer))))
+ (t (error "cannot resolve url: %s" filename))))
+
+(defun js-display-multiple-definitions (defs)
+ "Display a buffer to browse the list of definitions DEFS."
+ (with-current-buffer (get-buffer-create "*definitions*")
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (setq js-old-window-config (current-window-configuration))
+ (let ((keymap (make-sparse-keymap)))
+ (define-key keymap (kbd "RET") 'js-show-definition-other-window)
+ (define-key keymap (kbd "SPC") 'js-pop-to-definition)
+ (define-key keymap [?q] 'js-quit)
+ (use-local-map keymap)
+ (dolist (def defs)
+ (destructuring-bind (file line) def
+ (let ((start (point)))
+ (insert (format "%s:%d\n" file line))
+ (add-text-properties start (1- (point)) `(definition ,def)))))
+ (goto-char (point-min))
+ (setq buffer-read-only t)
+ (let ((w (select-window (display-buffer (current-buffer)))))
+ (shrink-window-if-larger-than-buffer w)))))
+
+(defun js-quit ()
+ "Kill the current buffer and restore the old window configuration."
+ (interactive)
+ (let ((buffer (current-buffer)))
+ (set-window-configuration js-old-window-config)
+ (kill-buffer buffer)))
+
+(defun js-property-at-point (prop)
+ (or (get-text-property (point) prop)
+ (error "No %s at point" prop)))
+
+(defun js-pop-to-definition (definition)
+ "Jump to the definition at point and close the current window."
+ (interactive (list (js-property-at-point 'definition)))
+ (delete-window)
+ (js-goto-definition definition))
+
+(defun js-show-definition-other-window (definition)
+ "Display the defintion at point in window."
+ (interactive (list (js-property-at-point 'definition)))
+ (save-selected-window
+ (js-goto-definition definition t)
+ (let ((overlay (make-overlay (line-beginning-position)
+ (line-end-position))))
+ (overlay-put overlay 'face 'secondary-selection)
+ (run-with-timer 0.3 nil 'delete-overlay overlay))))
+
+;;; Debugger
+
+(defvar js-debugger-level 0)
+
+(define-derived-mode js-debugger-mode fundamental-mode "jsdbg"
+ "Mode to inspect backtraces.
+See also `js-toggle-break-on-throw'.
+
+\\{js-debugger-mode-map}"
+ (erase-buffer)
+ (set (make-local-variable 'truncate-lines) t)
+ (set-syntax-table c++-mode-syntax-table))
+
+(let ((m js-debugger-mode-map))
+ (define-key m "v" 'js-debugger-show-source)
+ (define-key m "q" 'js-debugger-quit)
+ (define-key m "t" 'js-debugger-toggle-locals)
+ (define-key m "i" 'js-debugger-inspect-variable))
+
+(defun js-debugger-buffer ()
+ (get-buffer-create "*js-debugger*"))
+
+(defun js-debugger-activate (level)
+ (with-current-buffer (js-debugger-buffer)
+ (unless (equal js-debugger-level level)
+ (with-lexical-bindings (level)
+ (js-eval `(debugger_info_for_emacs 0 1)
+ (lambda (info)
+ (apply #'js-debugger-setup level info)))))))
+
+(defun js-debugger-setup (level message backtrace)
+ (with-current-buffer (js-debugger-buffer)
+ (unless (equal js-debugger-level level)
+ (setq buffer-read-only nil)
+ (js-debugger-mode)
+ (js-mode 1)
+ (unless js-old-window-config
+ (setq js-old-window-config (current-window-configuration)))
+ (setq mode-name (format "js-debugger[%d]" js-debugger-level))
+ (insert message "\n")
+ (insert "\nBacktrace: \n")
+ (save-excursion (js-insert-backtrace backtrace))
+ (setq buffer-read-only t)
+ (pop-to-buffer (current-buffer))
+ (when (and js-wait-tags
+ (y-or-n-p "Enter recursive edit? "))
+ (message "Entering recursive edit..")
+ (recursive-edit)))))
+
+(defun js-insert-backtrace (backtrace)
+ (mapc #'js-insert-frame backtrace))
+
+(defun js-insert-frame (frame)
+ (destructuring-bind (number text) frame
+ (let ((start (point-marker)))
+ (set-marker-insertion-type start nil)
+ (insert text)
+ (let ((end (point-marker)))
+ (insert "\n")
+ (set-marker-insertion-type end t)
+ (add-text-properties start end
+ (list 'frame number
+ 'text text
+ 'start start 'end end))))))
+
+(defun js-debugger-show-source (frame)
+ "Show the source buffer for the frame at point."
+ (interactive (list (js-property-at-point 'frame)))
+ (js-eval `(frame_source_location ,frame)
+ (lambda (location)
+ (destructuring-bind (file baseline line) location
+ (js-show-definition-other-window (list file line))))))
+
+(defun js-debugger-quit ()
+ "Exit from the debugger and continue execution."
+ (interactive)
+ (js-eval `(debugger_quit)
+ (lambda (x)
+ (message "%S" x)
+ (let ((buffer (current-buffer)))
+ (set-window-configuration js-old-window-config)
+ (kill-buffer buffer)))))
+
+(defun js-debugger-toggle-locals (frame)
+ "Show the local variables for the current frame."
+ (interactive (list (js-property-at-point 'frame)))
+ (let ((inhibit-read-only t))
+ (destructuring-bind (text start end detailsp)
+ (loop for p in '(text start end detailsp)
+ collect (get-text-property (point) p))
+ (cond ((not detailsp)
+ (let ((locals (js-eval-wait `(frame_locals ,frame))))
+ (goto-char end)
+ (let ((new-start (point)))
+ (insert-and-inherit text "\n")
+ (loop for l in locals for i from 0
+ do (js-insert-line-with-props (concat " " l )
+ `(local-var ,i)))
+ (delete-region start new-start)
+ (put-text-property start end 'detailsp t))))
+ (t
+ (goto-char end)
+ (let ((new-start (point)))
+ (insert-and-inherit text)
+ (delete-region start new-start)
+ (put-text-property start end 'detailsp nil))))
+ (goto-char start))))
+
+(defun js-insert-line-with-props (text props)
+ (let ((start (point)))
+ (insert-and-inherit text)
+ (let ((end (point)))
+ (insert-and-inherit "\n")
+ (add-text-properties start end props))))
+
+(defun js-debugger-inspect-variable (frame var)
+ "Inspect the variable at point."
+ (interactive (list (js-property-at-point 'frame)
+ (js-property-at-point 'local-var)))
+ (js-eval `(inspect_local_variable ,frame ,var)
+ 'js-open-inspector))
+
+(defun js-toggle-break-on-throw ()
+ "Enable or disable debugging on throws."
+ (interactive)
+ (js-eval `(toggle_break_on_throw) (lambda (m) (message "%s" m))))
+
+
+;;; Inspector
+
+(defvar js-inspect-hist ())
+
+(defun js-inspect (string)
+ "Evalute STRING and inspect the result."
+ (interactive (list (read-from-minibuffer "Inspect value (evaluated): "
+ nil nil nil 'js-inspect-hist)))
+ (js-eval `(init_inspector ,string) 'js-open-inspector))
+
+(define-derived-mode js-inspector-mode fundamental-mode "Javascript-Inspector"
+ "Mode to inspect Javascript objects.
+
+\\{js-debugger-mode-map}"
+ (set-syntax-table java-mode-syntax-table)
+ (set (make-local-variable 'truncate-lines) t)
+ (setq buffer-read-only t))
+
+(let ((m js-inspector-mode-map))
+ (define-key m (kbd "RET") 'js-inspect-part)
+ (define-key m "l" 'js-inspector-last)
+ (define-key m "n" 'js-inspector-next)
+ (define-key m "a" 'js-inspector-apply-part)
+ (define-key m "q" 'js-quit-inspector))
+
+(defun js-inspector-buffer ()
+ (or (get-buffer "*Javascript Inspector*")
+ (with-current-buffer (get-buffer-create "*Javascript Inspector*")
+ (setq js-inspector-mark-stack '())
+ (js-inspector-mode)
+ (js-mode 1)
+ (setq js-old-window-config (current-window-configuration))
+ (current-buffer))))
+
+(defun js-open-inspector (parts &optional point)
+ (with-current-buffer (js-inspector-buffer)
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (destructuring-bind (printed type lines) parts
+ (insert printed "\n")
+ (insert " [type: " type "]\n\n")
+ (save-excursion
+ (loop for (label text) in lines for i from 0
+ do (js-insert-line-with-props (concat label ": " text)
+ `(part ,i))))
+ (pop-to-buffer (current-buffer))
+ (when point
+ (goto-char (min (point-max) point)))))))
+
+(defun js-inspect-part (id)
+ "Inspect the slot at point."
+ (interactive (list (js-property-at-point 'part)))
+ (js-eval `(inspect_nth_part ,id) 'js-open-inspector)
+ (push (point) js-inspector-mark-stack))
+
+(defun js-inspector-next ()
+ "Inspect the next object in the history."
+ (interactive)
+ (js-eval `(inspector_next)
+ (lambda (parts)
+ (cond ((eq parts 'false)
+ (message "No next object")
+ (ding))
+ (t
+ (push (point) js-inspector-mark-stack)
+ (js-open-inspector parts))))))
+
+(defun js-inspector-last ()
+ "Inspect the previous object."
+ (interactive)
+ (js-eval `(inspector_pop)
+ (lambda (result)
+ (cond ((eq result 'false)
+ (message "No previous object")
+ (ding))
+ (t
+ (let ((point (pop js-inspector-mark-stack)))
+ (js-open-inspector result point)))))))
+
+(defun js-inspector-apply-part (number &optional args)
+ "Call the function at the current slot and inspect the result.
+Call this command with a prefix argument to supply arguments."
+ (interactive (list (js-property-at-point 'part)
+ (if current-prefix-arg
+ (read-from-minibuffer "Argument vector: " "[]"))))
+ (let ((args (or args "[]")))
+ (js-eval `(inspector_apply_part ,number ,args) 'js-open-inspector)
+ (push (point) js-inspector-mark-stack)))
+
+(defun js-quit-inspector ()
+ "Close the inspector."
+ (interactive)
+ (js-eval `(quit_inspector)
+ (lambda (x)
+ (set-window-configuration js-old-window-config)
+ (kill-buffer (current-buffer)))))
+
+;;; Portability kludges
+
+(unless (fboundp 'substring-no-properties)
+ (defun substring-no-properties (string &optional start end)
+ (let* ((start (or start 0))
+ (end (or end (length string)))
+ (string (substring string start end)))
+ (set-text-properties start end nil string)
+ string)))
+
+(unless (fboundp 'string-make-unibyte)
+ (defalias 'string-make-unibyte #'identity))
+
+;;;
+
+(run-hooks 'js-load-hook)
+
+(provide 'js-mode)
+
+;;; js-mode.el ends here
Property changes on: branches/trunk-reorg/thirdparty/emacs/js-mode.el
___________________________________________________________________
Name: svn:executable
+ *
Added: branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
1
0

26 Nov '07
Author: hhubner
Date: 2007-11-26 07:43:25 -0500 (Mon, 26 Nov 2007)
New Revision: 2290
Modified:
branches/trunk-reorg/projects/scrabble/website/scrabble.html
Log:
alpha test tweak
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.html
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.html 2007-11-26 12:42:03 UTC (rev 2289)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.html 2007-11-26 12:43:25 UTC (rev 2290)
@@ -12,7 +12,7 @@
<body onload="init()">
<div id="playfield">
</div>
- <div style="position: absolute; right: 20px; top: 20px;"><a style="color: white;" href="/login?login=user1">user1</a></div>
- <div style="position: absolute; right: 20px; top: 40px;"><a style="color: white;" href="/login?login=user2">user2</a></div>
+ <div style="position: absolute; right: 20px; top: 20px;"><a style="color: white;" href="/login?login=hans">hans</a></div>
+ <div style="position: absolute; right: 20px; top: 40px;"><a style="color: white;" href="/login?login=marna">marna</a></div>
</body>
-</html>
\ No newline at end of file
+</html>
1
0

26 Nov '07
Author: hhubner
Date: 2007-11-26 07:42:03 -0500 (Mon, 26 Nov 2007)
New Revision: 2289
Modified:
branches/trunk-reorg/bknr/datastore/src/data/object.lisp
Log:
enhance error message
Modified: branches/trunk-reorg/bknr/datastore/src/data/object.lisp
===================================================================
--- branches/trunk-reorg/bknr/datastore/src/data/object.lisp 2007-11-26 11:54:55 UTC (rev 2288)
+++ branches/trunk-reorg/bknr/datastore/src/data/object.lisp 2007-11-26 12:42:03 UTC (rev 2289)
@@ -81,8 +81,8 @@
(defmethod (setf slot-value-using-class) :before (newval (class persistent-class) object slotd)
(when (and (persistent-slot-p slotd)
(not (in-transaction-p)))
- (error "Attempt to set persistent slot outside of a transaction : (~A ~A)"
- (slot-definition-name slotd) (type-of object))))
+ (error "Attempt to set persistent slot ~A of ~A outside of a transaction"
+ (slot-definition-name slotd) object)))
(defmethod (setf slot-value-using-class) :after (newval (class persistent-class) object slotd)
(when (in-anonymous-transaction-p)
1
0

[bknr-cvs] r2288 - in branches/trunk-reorg/projects/scrabble: src website
by bknr@bknr.net 26 Nov '07
by bknr@bknr.net 26 Nov '07
26 Nov '07
Author: hhubner
Date: 2007-11-26 06:54:55 -0500 (Mon, 26 Nov 2007)
New Revision: 2288
Modified:
branches/trunk-reorg/projects/scrabble/src/rules.lisp
branches/trunk-reorg/projects/scrabble/src/start-webserver.lisp
branches/trunk-reorg/projects/scrabble/src/web.lisp
branches/trunk-reorg/projects/scrabble/website/scrabble.js
Log:
Prepare for first pre-alpha user test
Modified: branches/trunk-reorg/projects/scrabble/src/rules.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/rules.lisp 2007-11-26 11:24:22 UTC (rev 2287)
+++ branches/trunk-reorg/projects/scrabble/src/rules.lisp 2007-11-26 11:54:55 UTC (rev 2288)
@@ -63,8 +63,8 @@
(defmethod print-object ((board board) stream)
(print-unreadable-object (board stream :type t :identity t)
(terpri stream)
- (dotimes (x 15)
- (dotimes (y 15)
+ (dotimes (y 15)
+ (dotimes (x 15)
(format stream "~C " (aif (at-xy board x y) (used-for it) #\.)))
(terpri stream))))
Modified: branches/trunk-reorg/projects/scrabble/src/start-webserver.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/start-webserver.lisp 2007-11-26 11:24:22 UTC (rev 2287)
+++ branches/trunk-reorg/projects/scrabble/src/start-webserver.lisp 2007-11-26 11:54:55 UTC (rev 2288)
@@ -8,8 +8,8 @@
:subsystems (list (make-instance 'store-object-subsystem)))
(unless (class-instances 'user)
(format t "creating test users and game~%")
- (let ((user1 (make-user "user1" :class 'player :full-name "User Eins"))
- (user2 (make-user "user2" :class 'player :full-name "User Zwei")))
+ (let ((user1 (make-user "hans" :class 'player :full-name "Hans"))
+ (user2 (make-user "marna" :class 'player :full-name "Marna")))
(make-game :de (list user1 user2)))))
(defparameter *website-directory*
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-26 11:24:22 UTC (rev 2287)
+++ branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-26 11:54:55 UTC (rev 2288)
@@ -56,8 +56,7 @@
:score (score-of move)
:placed-tiles (placed-tiles-of move)
:words (mapcar (lambda (word-cons)
- (list :word (car word-cons)
- :score (cdr word-cons)))
+ (list (car word-cons) (cdr word-cons)))
(words-formed-of move)))
stream))
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-26 11:24:22 UTC (rev 2287)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-26 11:54:55 UTC (rev 2288)
@@ -118,12 +118,14 @@
setElementPosition(shuffleButton, { x: border + 480, y: border + 665 });
appendChildNodes(container, shuffleButton);
-// var clearButton = DIV(null, "clear");
-// clearButton.style.color = 'white';
-// clearButton.style.position = 'absolute';
-// clearButton.onclick = clearBoard;
-// setElementPosition(clearButton, { x: border + 480, y: border + 680 });
-// appendChildNodes(container, clearButton);
+ var gameLog = DIV({ id: 'gameLog' }, "");
+ gameLog.style.position = 'absolute';
+ gameLog.style.width = '280px';
+ gameLog.style.height = '250px';
+ gameLog.style.textAlign = 'left';
+ gameLog.style.overflowY = 'scroll';
+ setElementPosition(gameLog, { x: border + 680, y: border + 400 });
+ appendChildNodes($('playfield'), gameLog);
}
function setLetter(x, y, letter, isBlank) {
@@ -438,6 +440,21 @@
otherPlayerIndex++;
}
+function renderMoveAsText(move)
+{
+ var retval = move.participantLogin;
+ if (move.type == 'move') {
+ retval += " score: " + move.score;
+ for (var i = 0; i < move.words.length; i++) {
+ retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
+ }
+ } else {
+ retval += move.type;
+ }
+
+ return retval;
+}
+
function drawGameState (gameState) {
for (var i = 0; i < gameState.board.length; i++) {
var x = gameState.board[i][0];
@@ -453,6 +470,9 @@
makeMyTray(map(function (entry) { return entry.letter }, participant.remainingTiles));
}
}
+ for (var i = 0; i < gameState.moves.length; i++) {
+ appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i])));
+ }
}
var legalLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
1
0

26 Nov '07
Author: hhubner
Date: 2007-11-26 06:24:22 -0500 (Mon, 26 Nov 2007)
New Revision: 2287
Modified:
branches/trunk-reorg/projects/scrabble/src/
Log:
ignore TAGS file
Property changes on: branches/trunk-reorg/projects/scrabble/src
___________________________________________________________________
Name: svn:ignore
+ TAGS
1
0

[bknr-cvs] r2286 - in branches/trunk-reorg/projects/scrabble: src website
by bknr@bknr.net 26 Nov '07
by bknr@bknr.net 26 Nov '07
26 Nov '07
Author: hhubner
Date: 2007-11-26 06:19:32 -0500 (Mon, 26 Nov 2007)
New Revision: 2286
Added:
branches/trunk-reorg/projects/scrabble/src/portable-queue.lisp
branches/trunk-reorg/projects/scrabble/src/publish-subscribe.lisp
branches/trunk-reorg/projects/scrabble/src/queue.lisp
Modified:
branches/trunk-reorg/projects/scrabble/src/game.lisp
branches/trunk-reorg/projects/scrabble/src/package.lisp
branches/trunk-reorg/projects/scrabble/src/scrabble.asd
branches/trunk-reorg/projects/scrabble/src/web.lisp
branches/trunk-reorg/projects/scrabble/website/scrabble.js
Log:
Add publish/subscribe mechanism.
Add queue implementation so that threads can signal each other with
some data. The queue implementation for OpenMCL uses CCL primitives
with timeout, the portable version uses the HUNCHENTOOT-MP package
and polling.
Modified: branches/trunk-reorg/projects/scrabble/src/game.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/game.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/game.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -50,10 +50,20 @@
(vector-push-extend tile (tiles-of tile-bag)))
(shake-tile-bag tile-bag))
-(defclass player (user)
- ((games :initform nil :accessor games-of))
+(defclass player (user subscriber)
+ ((games :initform nil
+ :accessor games-of)
+ (event-queue :initform (make-instance 'queue)
+ :reader event-queue-of
+ :transient t)
+ (publish-subscribe:subscriptions :transient t))
(:metaclass persistent-class))
+(defmethod wait-for-event ((player player) timeout)
+ "Return next event for PLAYER or nil if TIMEOUT seconds have elapsed
+without any new events occuring on the queue."
+ (queue-pop (event-queue-of player) timeout))
+
(defclass participant (store-object)
((player :initarg :player :reader player-of)
(tray :initarg :tray :accessor tray-of)
@@ -74,7 +84,12 @@
(defclass move (store-object)
((participant :initarg :participant
:reader participant-of)
- (placed-tiles :initarg :placed-tiles
+ (time :initarg :time
+ :reader time-of))
+ (:metaclass persistent-class))
+
+(defclass letter-placement (move)
+ ((placed-tiles :initarg :placed-tiles
:reader placed-tiles-of)
(new-tiles-drawn :initarg :new-tiles-drawn
:reader new-tiles-drawn-of
@@ -93,7 +108,7 @@
(score-of move)
(words-formed-of move))))
-(defclass game (store-object)
+(defclass game (store-object publication)
((language :initarg :language
:reader language-of)
(board :initarg :board
@@ -105,7 +120,8 @@
:documentation "List of participants in this game")
(moves :initform nil
:accessor moves-of
- :documentation "List of moves that have been made in this game"))
+ :documentation "List of moves that have been made in this game")
+ (publish-subscribe:subscriptions :transient t))
(:metaclass persistent-class))
(deftransaction make-game (language players)
@@ -186,7 +202,17 @@
(append drawn (tray-of participant)))
drawn))
-(deftransaction make-move% (game participant placed-tiles)
+(defmethod signal-subscriber ((player player) (game game) move)
+ (queue-push (list :type "move" :game-id (store-object-id game) :move move)
+ (event-queue-of player)))
+
+(defun make-move (participant class &rest initargs)
+ (apply #'make-object class
+ :participant participant
+ :time (get-universal-time)
+ initargs))
+
+(deftransaction make-letter-placement% (game participant placed-tiles)
(dolist (placed-tile placed-tiles)
(when (used-for placed-tile)
(setf (used-for (tile-of placed-tile)) (used-for placed-tile))))
@@ -201,31 +227,29 @@
(when (eql 7 (length tiles-used))
(incf score 50))
(incf (score-of participant) score)
- (let ((move (make-object 'move
- :participant participant
- :placed-tiles placed-tiles
- :new-tiles-drawn tiles-drawn
- :words-formed words-formed
- :score score)))
+ (let ((move (make-move participant 'letter-placement
+ :placed-tiles placed-tiles
+ :new-tiles-drawn tiles-drawn
+ :words-formed words-formed
+ :score score)))
(push move (moves-of game))
(rotate-participants game)
+ (publish game move)
move))))
-(defun make-move (game participant placed-tiles)
+(defun make-letter-placement (game participant placed-tiles)
(ensure-participants-turn game participant)
(ensure-participant-has-tiles participant placed-tiles)
(check-move-legality (board-of game) placed-tiles)
- (make-move% game participant (mapcar (lambda (placement)
- (list (x-of placement)
- (y-of placement)
- (tile-of placement)
- (used-for placement)))
- placed-tiles)))
+ (make-letter-placement% game participant (mapcar (lambda (placement)
+ (list (x-of placement)
+ (y-of placement)
+ (tile-of placement)
+ (used-for placement)))
+ placed-tiles)))
-(defclass move-withdrawal (store-object)
- ((participant :initarg :participant
- :reader participant-of)
- (reason :initarg :reason
+(defclass move-withdrawal (move)
+ ((reason :initarg :reason
:reader reason-of))
(:metaclass persistent-class))
@@ -252,10 +276,8 @@
(error "last move was not a letter placement, can't be withdrawn"))
(withdraw-last-move% game reason move)))
-(defclass tile-swap (store-object)
- ((participant :initarg :participant
- :reader participant-of)
- (count :initarg :count
+(defclass tile-swap (move)
+ ((count :initarg :count
:reader count-of))
(:metaclass persistent-class))
Modified: branches/trunk-reorg/projects/scrabble/src/package.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/package.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/package.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -1,10 +1,38 @@
+#+openmcl
+(defpackage :mp-utils
+ (:use :cl :ccl)
+ (:export "QUEUE"
+ "QUEUE-PUSH"
+ "QUEUE-POP"))
+
+#-openmcl
+(defpackage :mp-utils
+ (:use :cl :hunchentoot-mp)
+ (:export "QUEUE"
+ "QUEUE-PUSH"
+ "QUEUE-POP"))
+
+(defpackage :publish-subscribe
+ (:use :cl)
+ (:export "PUBLICATION"
+ "SUBSCRIBER"
+ "SUBSCRIBE-TO"
+ "SUBSCRIPTIONS"
+ "CANCEL-SUBSCRIPTION"
+ "CANCEL-SUBSCRIPTIONS"
+ "PUBLISH"
+ "SIGNAL-SUBSCRIBER"))
+
(defpackage :scrabble
(:use :cl
:alexandria
:anaphora
+ :publish-subscribe
+ :mp-utils
:bknr.datastore
:bknr.user)
+ (:shadowing-import-from :bknr.user "SUBSCRIPTIONS")
(:export "*BOARD-SCORING*"
"*TILE-SETS*"
@@ -25,6 +53,7 @@
"PLAYER"
"GAMES-OF"
+ "WAIT-FOR-EVENT"
"PARTICIPANT"
"PLAYER-OF"
@@ -35,17 +64,18 @@
"Y-OF"
"TILE-OF"
- "MAKE-MOVE"
-
- "MOVE"
+ "MAKE-LETTER-PLACEMENT"
+ "LETTER-PLACEMENT"
"SCORE-OF"
"PARTICIPANT-OF"
"WORDS-FORMED-OF"
"PLACED-TILES-OF"
- "MOVE-WITHDRAWAL"
+ "MAKE-MOVE-WITHDRAWAL"
+ "MOVE-WITHDRAWAL"
"REASON-OF"
+ "MAKE-TILE-SWAP"
"TILE-SWAP"
"COUNT-OF"
@@ -70,11 +100,13 @@
:hunchentoot
:bknr.datastore
:bknr.user
+ :publish-subscribe
:cl-who
:cl-interpol
:cl-ppcre
:json
- :scrabble)
+ :scrabble
+ :mp-utils)
+ (:shadowing-import-from :bknr.user "SUBSCRIPTIONS")
(:shadowing-import-from :cl-interpol "QUOTE-META-CHARS")
- (:export "START-WEBSERVER"))
-
\ No newline at end of file
+ (:export "START-WEBSERVER"))
\ No newline at end of file
Added: branches/trunk-reorg/projects/scrabble/src/portable-queue.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/portable-queue.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/portable-queue.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -0,0 +1,35 @@
+(in-package :mp-utils)
+
+(defclass queue ()
+ ((count :initform 0 :accessor count-of)
+ (lock :initform (make-lock "queue") :reader lock-of)
+ (head :initform nil :accessor head-of)
+ (tail :initform nil :accessor tail-of)))
+
+(defmethod print-object ((queue queue) stream)
+ (print-unreadable-object (queue stream :type t :identity t)
+ (format stream "~A" (head-of queue))))
+
+(defmethod queue-push (data (queue queue))
+ (with-lock ((lock-of queue))
+ (let ((new-cell (cons data nil)))
+ (when (tail-of queue)
+ (setf (cdr (tail-of queue)) new-cell))
+ (setf (tail-of queue) new-cell)
+ (unless (head-of queue)
+ (setf (head-of queue) new-cell)))
+ (incf (count-of queue)))
+ queue)
+
+(defmethod queue-pop ((queue queue) timeout)
+ (loop while (plusp timeout)
+ do (with-lock ((lock-of queue))
+ (when (plusp (count-of queue))
+ (decf (count-of queue))
+ (let ((retval (pop (head-of queue))))
+ (unless (head-of queue)
+ (setf (tail-of queue) nil))
+ (return-from queue-pop (values retval t)))))
+ do (decf timeout)
+ do (sleep 1))
+ (values nil nil))
\ No newline at end of file
Added: branches/trunk-reorg/projects/scrabble/src/publish-subscribe.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/publish-subscribe.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/publish-subscribe.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -0,0 +1,42 @@
+
+(in-package :publish-subscribe)
+
+(defclass publication ()
+ ((subscriptions :initform nil :accessor subscriptions-of)))
+
+(defclass subscription ()
+ ((subscriber :initarg :subscriber :reader subscriber-of)
+ (publication :initarg :publication :reader publication-of)))
+
+(defclass subscriber ()
+ ((subscriptions :initform nil :accessor subscriptions-of)))
+
+(defmethod subscribe-to ((subscriber subscriber)
+ (publication publication))
+ (make-instance 'subscription
+ :subscriber subscriber
+ :publication publication))
+
+(defmethod initialize-instance :after ((subscription subscription) &key)
+ (pushnew subscription (subscriptions-of (publication-of subscription)))
+ (pushnew subscription (subscriptions-of (subscriber-of subscription))))
+
+(defmethod cancel-subscription ((subscription subscription))
+ (with-slots (publication subscriber) subscription
+ (setf (subscriptions-of publication)
+ (remove subscription (subscriptions-of publication)))
+ (setf (subscriptions-of subscriber)
+ (remove subscription (subscriptions-of subscriber)))))
+
+(defmethod cancel-subscriptions (holder)
+ (mapcar #'cancel-subscription (subscriptions-of holder)))
+
+(defgeneric signal-subscriber (subscriber publication payload)
+ (:documentation "Notify SUBSCRIBER that PULICATION has been
+published with the given PAYLOAD."))
+
+(defmethod publish ((publication publication) payload)
+ (dolist (subscription (subscriptions-of publication))
+ (signal-subscriber (subscriber-of subscription)
+ (publication-of subscription)
+ payload)))
Added: branches/trunk-reorg/projects/scrabble/src/queue.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/queue.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/queue.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -0,0 +1,31 @@
+(in-package :mp-utils)
+
+(defclass queue ()
+ ((semaphore :initform (make-semaphore) :reader semaphore-of)
+ (lock :initform (make-lock) :reader lock-of)
+ (head :initform nil :accessor head-of)
+ (tail :initform nil :accessor tail-of)))
+
+(defmethod print-object ((queue queue) stream)
+ (print-unreadable-object (queue stream :type t :identity t)
+ (format stream "~A" (head-of queue))))
+
+(defmethod queue-push (data (queue queue))
+ (with-lock-grabbed ((lock-of queue))
+ (let ((new-cell (cons data nil)))
+ (when (tail-of queue)
+ (setf (cdr (tail-of queue)) new-cell))
+ (setf (tail-of queue) new-cell)
+ (unless (head-of queue)
+ (setf (head-of queue) new-cell)))
+ (signal-semaphore (semaphore-of queue)))
+ queue)
+
+(defmethod queue-pop ((queue queue) timeout)
+ (if (timed-wait-on-semaphore (semaphore-of queue) timeout)
+ (with-lock-grabbed ((lock-of queue))
+ (let ((retval (pop (head-of queue))))
+ (unless (head-of queue)
+ (setf (tail-of queue) nil))
+ (values retval t)))
+ (values nil nil)))
\ No newline at end of file
Modified: branches/trunk-reorg/projects/scrabble/src/scrabble.asd
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/scrabble.asd 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/scrabble.asd 2007-11-26 11:19:32 UTC (rev 2286)
@@ -23,6 +23,11 @@
:cl-json)
:serial t
:components ((:file "package")
+ (:file "publish-subscribe")
+ #+openmcl
+ (:file "queue")
+ #-openmcl
+ (:file "portable-queue")
(:file "game-constants")
(:file "rules")
(:file "game")
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-26 11:19:32 UTC (rev 2286)
@@ -5,14 +5,16 @@
(defparameter *ignore-slots* '(bknr.datastore::id bknr.indices::destroyed-p))
(defun encode-json-plist (plist stream)
- (princ #\{ stream)
- (loop for (key value &rest rest) on plist by #'cddr
- do (encode-json key stream)
- do (princ #\: stream)
- do (encode-json value stream)
- when rest
- do (princ #\, stream))
- (princ #\} stream))
+ (let (printed)
+ (princ #\{ stream)
+ (loop for (key value) on plist by #'cddr
+ when printed
+ do (princ #\, stream)
+ do (setf printed t)
+ do (encode-json key stream)
+ do (princ #\: stream)
+ do (encode-json value stream))
+ (princ #\} stream)))
(defmethod encode-json ((object store-object) stream)
(let (printed)
@@ -28,6 +30,11 @@
(encode-json (slot-value object (closer-mop:slot-definition-name slotdef)) stream)))
(princ #\} stream)))
+(defmethod encode-json ((game game) stream)
+ (let ((*ignore-slots* (append *ignore-slots*
+ '(publish-subscribe::subscriptions))))
+ (call-next-method)))
+
(defmethod encode-json ((tile-bag tile-bag) stream)
(encode-json-plist (list :remaining-tiles (remaining-tile-count tile-bag)) stream))
@@ -43,7 +50,7 @@
(list :used-for it)))
stream))
-(defmethod encode-json ((move move) stream)
+(defmethod encode-json ((move letter-placement) stream)
(encode-json-plist (list :type "move"
:participant-login (user-login (player-of (participant-of move)))
:score (score-of move)
@@ -83,23 +90,23 @@
(defmethod encode-json ((participant participant) stream)
(start-session)
- (format t "user: ~A~%" (session-value :user))
(encode-json-plist (append (list :login (user-login (player-of participant))
:name (user-full-name (player-of participant))
:remaining-tiles)
- (list (if (equal (user-login (player-of participant))
- (session-value :user))
+ (list (if (eq (player-of participant)
+ (session-value :user))
(tray-of participant)
(length (tray-of participant)))))
stream))
-(define-easy-handler (login :uri "/login" :default-request-type :get)
+(define-easy-handler (login :uri "/login")
(login password)
(format t "warning: password not checked~*~%" password)
- (when (and login
- (find-user login))
+ (no-cache)
+ (awhen (and login
+ (find-user login))
(start-session)
- (setf (session-value :user) login)
+ (setf (session-value :user) it)
(redirect "/scrabble.html"))
(with-html-output-to-string (*standard-output* nil)
(:html
@@ -123,7 +130,6 @@
list-of-moves)
(labels
((use-letter (letter is-blank)
- (format t "use-letter ~A ~A~%" letter is-blank)
(awhen (find (if is-blank nil letter) tray :key #'letter-of)
(setf tray (remove it tray))
(return-from use-letter it))
@@ -151,25 +157,37 @@
(defmethod find-game ((game-id string))
(find-game (parse-integer game-id)))
-(define-easy-handler (make-move-handler :uri "/make-move" :default-request-type :post)
+(define-easy-handler (place-tiles-handler :uri "/place-tiles")
(move game)
(start-session)
+ (no-cache)
;; MOVE contains the move to make, GAME is the object ID of the game.
(with-output-to-string (s)
(handler-case
(progn
(let* ((game (find-game game))
- (participant (find (find-user (session-value :user)) (participants-of game) :key #'player-of)))
+ (participant (find (session-value :user) (participants-of game) :key #'player-of)))
(encode-json-plist
- (list :move (scrabble:make-move game
- participant
- (parse-move participant move))
+ (list :move (make-letter-placement game
+ participant
+ (parse-move participant move))
:tray (tray-of participant)) s)))
(error (e)
(encode-json-plist (list :error (princ-to-string e)) s)))))
+(defparameter *no-event-timeout* 60)
+
+(define-easy-handler (wait-event-handler :uri "/wait-event") ()
+ (start-session)
+ (no-cache)
+ (unless (session-value :user)
+ (redirect "/login"))
+ (with-output-to-string (s)
+ (encode-json-plist (wait-for-event (session-value :user) *no-event-timeout*) s)))
+
(define-easy-handler (games :uri "/games") ()
(start-session)
+ (no-cache)
(with-html-output-to-string (*standard-output* nil)
(:html
(:head
@@ -177,7 +195,7 @@
(:body
(:ul
(dolist (game (remove-if-not (lambda (game)
- (member (find-user (session-value :user)) (participants-of game)
+ (member (session-value :user) (participants-of game)
:key #'player-of))
(class-instances 'game)))
(htm
@@ -185,13 +203,16 @@
(defun game-handler ()
(start-session)
+ (no-cache)
(register-groups-bind (object-id-string) (#?r".*/(\d+)$" (request-uri))
- (let ((object (and object-id-string ; avoid sbcl warning
+ (let ((game (and object-id-string ; avoid sbcl warning
(find-store-object (parse-integer object-id-string)))))
- (when (typep object 'game)
+ (when (typep game 'game)
+ (awhen (session-value :user)
+ (subscribe-to it game))
(return-from game-handler
(with-output-to-string (s)
- (encode-json object s))))))
+ (encode-json game s))))))
(with-html-output-to-string (*standard-output* nil)
(:html
(:head
@@ -199,10 +220,11 @@
(:body
(:div "Invalid game ID")))))
-(define-easy-handler (move :uri "/move" :default-request-type :get)
+(define-easy-handler (move :uri "/move")
((game-id :parameter-type 'integer)
(move :parameter-type 'json:decode-json-from-string))
(start-session)
+ (no-cache)
(assert game-id)
(let ((game (find-store-object game-id)))
(assert game)
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-25 05:37:30 UTC (rev 2285)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-26 11:19:32 UTC (rev 2286)
@@ -111,13 +111,6 @@
appendChildNodes(container, board[x]);
}
- theirTrays = DIV();
- theirTrays.style.position = 'absolute';
- theirTrays.style.width = 7 * 44 + 'px';
- theirTrays.style.height = '70px';
- setElementPosition(theirTrays, { x: border + 16 * 40, y: border + 40 });
- appendChildNodes(container, theirTrays);
-
var shuffleButton = DIV(null, "shuffle");
shuffleButton.style.color = 'white';
shuffleButton.style.position = 'absolute';
@@ -193,13 +186,15 @@
}
};
- this.advance = function() {
+ this.advance = function(isHoriz) {
var horizontal = 1;
var vertical = 2;
var direction = this.direction;
if (direction == 0) {
// Direction not determined
- if (((this.y < 14) && letterAt(this.x, this.y + 1))
+ if (isHoriz != undefined) {
+ direction = isHoriz ? horizontal : vertical;
+ } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
|| ((this.y > 1)
&& letterAt(this.x, this.y - 1)
&& !letterAt(this.x, this.y - 2))
@@ -257,7 +252,7 @@
function submitMove()
{
var queryString = MochiKit.Base.queryString({ move: move.toString(), game: gameID });
- var res = MochiKit.Async.doXHR("/make-move",
+ var res = MochiKit.Async.doXHR("/place-tiles",
{ method: 'POST',
sendContent: queryString,
headers: { "Content-Type": "application/x-www-form-urlencoded" } });
@@ -311,7 +306,11 @@
if (tilePosition == -1) {
alert("You don't have that letter!");
} else {
- cursor.advance();
+ var isHoriz;
+ if (move.length > 0) {
+ isHoriz = (move[0][0] != x);
+ }
+ cursor.advance(isHoriz);
if (!letterAt(x, y)) {
var tile = tray[tilePosition];
tray.splice(tilePosition, 1);
@@ -392,8 +391,7 @@
element.style.height = '34px';
element.style.zIndex = '10';
element.onclick = trayClick;
- // setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 });
- YAHOO.util.Dom.setXY(element, [ border + 194 + i * 40, border + 665 ]);
+ setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 });
tray[i] = element;
}
appendChildNodes($('playfield'), tray);
@@ -416,11 +414,28 @@
tray = newTray;
}
-function addTheirTray (participant) {
- appendChildNodes(theirTrays, DIV(null,
- DIV(null, participant.name),
- DIV(null, map(function () { return IMG({ src: 'images/null.png' }) },
- new Array(participant.remainingTiles)))));
+var otherPlayerIndex = 0;
+
+function makeTheirTray (name, tileCount) {
+ var tray = [];
+ for (var i = 0; i < tileCount; i++) {
+ var element = IMG({src: 'images/null.png'});
+ element.style.position = 'absolute';
+ element.style.width = '34px';
+ element.style.height = '34px';
+ element.style.zIndex = '10';
+ setElementPosition(element, { x: border + 680 + i * 40, y: border + 80 * otherPlayerIndex });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
+
+ var nameTag = DIV(null, 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);
+ otherPlayerIndex++;
}
function drawGameState (gameState) {
@@ -433,7 +448,7 @@
for (var i = 0; i < gameState.participants.length; i++) {
var participant = gameState.participants[i];
if (typeof participant.remainingTiles == 'number') {
- addTheirTray(participant);
+ makeTheirTray(participant.name, participant.remainingTiles);
} else {
makeMyTray(map(function (entry) { return entry.letter }, participant.remainingTiles));
}
1
0

[bknr-cvs] r2285 - in branches/trunk-reorg/projects/scrabble: src website website/images/de website/images/en
by bknr@bknr.net 25 Nov '07
by bknr@bknr.net 25 Nov '07
25 Nov '07
Author: hhubner
Date: 2007-11-25 00:37:30 -0500 (Sun, 25 Nov 2007)
New Revision: 2285
Added:
branches/trunk-reorg/projects/scrabble/website/images/de/A-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/B-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/C-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/D-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/E-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/F-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/G-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/H-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/I-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/J-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/K-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/L-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/M-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/N-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/O-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/P-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/Q-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/R-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/S-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/T-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/U-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/V-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/W-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/X-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/Y-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/Z-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/null-blank.png
branches/trunk-reorg/projects/scrabble/website/images/de/null.png
branches/trunk-reorg/projects/scrabble/website/images/de/start-field.png
branches/trunk-reorg/projects/scrabble/website/images/en/null.png
Removed:
branches/trunk-reorg/projects/scrabble/website/images/de/NIL.png
branches/trunk-reorg/projects/scrabble/website/images/en/NIL.png
Modified:
branches/trunk-reorg/projects/scrabble/src/game.lisp
branches/trunk-reorg/projects/scrabble/src/make-letters.lisp
branches/trunk-reorg/projects/scrabble/src/package.lisp
branches/trunk-reorg/projects/scrabble/src/rules.lisp
branches/trunk-reorg/projects/scrabble/src/web.lisp
branches/trunk-reorg/projects/scrabble/website/images/de/charmap.xml
branches/trunk-reorg/projects/scrabble/website/images/de/double-letter.png
branches/trunk-reorg/projects/scrabble/website/images/de/double-word.png
branches/trunk-reorg/projects/scrabble/website/images/de/triple-letter.png
branches/trunk-reorg/projects/scrabble/website/images/de/triple-word.png
branches/trunk-reorg/projects/scrabble/website/scrabble.css
branches/trunk-reorg/projects/scrabble/website/scrabble.html
branches/trunk-reorg/projects/scrabble/website/scrabble.js
Log:
Checkpoint: Various gameplay fixes, add start-field with star, add second
set of letter tiles with red lettering to signify placed blank tiles. Fix
json encoding for IE.
Modified: branches/trunk-reorg/projects/scrabble/src/game.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/game.lisp 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/src/game.lisp 2007-11-25 05:37:30 UTC (rev 2285)
@@ -62,10 +62,11 @@
(defmethod print-object ((participant participant) stream)
(print-unreadable-object (participant stream :type t)
- (format stream "~A score: ~A, ~A tile~:P"
+ (format stream "~A score: ~A, ~A tile~:P: ~{~A~^, ~}"
(user-login (player-of participant))
(score-of participant)
- (length (tray-of participant)))))
+ (length (tray-of participant))
+ (mapcar #'letter-of (tray-of participant)))))
(defmethod tray-size ((participant participant))
(length (tray-of participant)))
@@ -133,7 +134,7 @@
(eq participant (next-participant-of game)))
(defun ensure-participants-turn (game participant)
- (unless (participants-turn-p game participant)
+ (unless (participants-turn-p game participant)
(error "It's not ~A's turn." (user-login (player-of participant)))))
(defun rotate-participants (game)
@@ -150,6 +151,12 @@
(defmethod letter-equal ((letter1 character) (letter2 (eql nil)))
nil)
+(defmethod letter-equal ((letter1 (eql nil)) (letter2 character))
+ nil)
+
+(defmethod letter-equal ((letter1 (eql nil)) (letter2 (eql nil)))
+ t)
+
(defmethod letter-equal ((tile1 tile) (tile2 tile))
(letter-equal (letter-of tile1) (letter-of tile2)))
@@ -157,9 +164,9 @@
(let ((tray-letters (mapcar #'letter-of (tray-of participant)))
(placed-letters (mapcar (compose #'letter-of #'tile-of) placed-tiles)))
(dolist (letter placed-letters)
- (let ((has-letter (find letter tray-letters :test #'letter-equal)))
+ (let ((has-letter (position letter tray-letters :test #'letter-equal)))
(unless (or has-letter (find nil tray-letters))
- (error "participant ~A does not have tile ~A" participant letter))
+ (error "participant ~A does not have tile ~A" participant letter))
(setf tray-letters
(if has-letter
(remove letter tray-letters :test #'letter-equal :count 1)
@@ -180,9 +187,12 @@
drawn))
(deftransaction make-move% (game participant placed-tiles)
+ (dolist (placed-tile placed-tiles)
+ (when (used-for placed-tile)
+ (setf (used-for (tile-of placed-tile)) (used-for placed-tile))))
(let ((words-formed (mapcar (lambda (word-result)
(cons (word-text word-result) (word-score word-result)))
- (words-formed (board-of game) placed-tiles))))
+ (words-formed (board-of game) placed-tiles))))
(dolist (placed-tile placed-tiles)
(put-letter (board-of game) (tile-of placed-tile) (x-of placed-tile) (y-of placed-tile)))
(let ((tiles-used (remove-letters-from-participant-tray participant (mapcar #'tile-of placed-tiles)))
@@ -206,7 +216,10 @@
(ensure-participant-has-tiles participant placed-tiles)
(check-move-legality (board-of game) placed-tiles)
(make-move% game participant (mapcar (lambda (placement)
- (list (x-of placement) (y-of placement) (tile-of placement)))
+ (list (x-of placement)
+ (y-of placement)
+ (tile-of placement)
+ (used-for placement)))
placed-tiles)))
(defclass move-withdrawal (store-object)
Modified: branches/trunk-reorg/projects/scrabble/src/make-letters.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/make-letters.lisp 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/src/make-letters.lisp 2007-11-25 05:37:30 UTC (rev 2285)
@@ -39,23 +39,30 @@
(defparameter *tile-color* '(1.0 0.98 0.8))
-(defparameter *bold-font* #.(merge-pathnames #p"../fonts/DIN/DINMd___.ttf" *default-pathname-defaults*))
-(defparameter *regular-font* #.(merge-pathnames #p"../fonts/DIN/DINRg___.ttf" *default-pathname-defaults*))
+(defparameter *bold-font* #.(merge-pathnames #p"/home/hans/fonts/DIN/DINMd___.ttf" *default-pathname-defaults*))
+(defparameter *regular-font* #.(merge-pathnames #p"/home/hans/fonts/DIN/DINRg___.ttf" *default-pathname-defaults*))
-(defun make-letter-tile (char score)
+(defun make-letter-tile (char score blank-used)
(with-canvas (:width 34 :height 34)
(let* ((bold-font (get-font *bold-font*))
(regular-font (get-font *regular-font*))
(char-string (princ-to-string char))
- (pathname (make-pathname :name (if (and char (> (char-code char) 127))
- (char-name char)
- char-string)
+ (filename (format nil "~A~@[-blank~]"
+ (if char
+ (if (> (char-code char) 127)
+ (char-name char)
+ char-string)
+ "null")
+ blank-used))
+ (pathname (make-pathname :name filename
:type "png")))
(apply #'set-rgb-fill *tile-color*)
(rounded-rectangle 0 0 34 34 4 4)
(fill-path)
(when char
- (set-rgb-fill 0 0 0)
+ (if (and blank-used char)
+ (set-rgb-fill 0.9 0 0)
+ (set-rgb-fill 0 0 0))
(set-font bold-font 27)
(draw-centered-string 13 7 char-string)
(set-font regular-font 11)
@@ -77,11 +84,12 @@
:external-format :utf-8)
(cxml:with-xml-output (cxml:make-character-stream-sink letter-map-file)
(cxml:with-element "chars"
- (dolist (entry (gethash language *tile-sets*))
+ (dolist (entry (getf *tile-sets* language))
(destructuring-bind (letter score count) entry
(declare (ignore count))
(cxml:with-element "char"
- (cxml:attribute "filename" (namestring (make-letter-tile letter score)))
+ (cxml:attribute "filename" (namestring (make-letter-tile letter score nil)))
+ (cxml:attribute "blank-filename" (namestring (make-letter-tile letter score t)))
(cxml:text (princ-to-string letter)))))))))
(defun make-cursor ()
@@ -92,6 +100,21 @@
(stroke)
(save-png #P"cursor.png")))
+(defun draw-star (size border)
+ (with-graphics-state
+ (let ((half-size (/ size 2))
+ (angle 0)
+ (step (* 2 (/ (* pi 2) 5))))
+ (translate (+ border half-size) (+ border half-size))
+ (move-to 0 half-size)
+ (dotimes (i 5)
+ (setf angle (+ angle step))
+ (line-to (* (sin angle) half-size)
+ (* (cos angle) half-size)))
+ (close-subpath)
+ (set-rgb-fill 0 0 0)
+ (fill-path))))
+
(defun make-special-field (name color &key text star)
(with-canvas (:width 40 :height 40)
(let ((regular-font (get-font *regular-font*)))
@@ -108,7 +131,7 @@
(draw-centered-string 20 position line)
(decf position 6))))
(star
- ))
+ (draw-star 30 5)))
(save-png (make-pathname :name (string-downcase (symbol-name name)) :type "png")))))
(defun make-special-field-set (language)
@@ -117,7 +140,7 @@
(getf *special-field-colors* tile-name)
:text (getf (gethash language *special-field-texts*) tile-name)))
(make-special-field :standard (getf *special-field-colors* :standard) :star nil)
- (make-special-field :standard (getf *special-field-colors* :double-word) :star t))
+ (make-special-field :start-field (getf *special-field-colors* :double-word) :star t))
(defun make-tile-set (directory language)
(let ((*default-pathname-defaults*
@@ -128,3 +151,21 @@
(make-letter-tile-set language)
(make-special-field-set language)
(make-cursor)))
+
+
+
+(defun star-test (size border)
+ (with-canvas (:width size :height size)
+ (let ((star-size (/ (- size (* 2 border)) 2))
+ (angle 0)
+ (step (* 2 (/ (* pi 2) 5))))
+ (translate (+ border star-size) (+ border star-size))
+ (move-to 0 star-size)
+ (dotimes (i 5)
+ (setf angle (+ angle step))
+ (line-to (* (sin angle) star-size)
+ (* (cos angle) star-size)))
+ (close-subpath)
+ (set-rgb-fill 0 0 0)
+ (fill-path)
+ (save-png "/home/hans/bknr-svn/projects/scrabble/website/images/de/star.png"))))
Modified: branches/trunk-reorg/projects/scrabble/src/package.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/package.lisp 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/src/package.lisp 2007-11-25 05:37:30 UTC (rev 2285)
@@ -12,7 +12,10 @@
"TILE"
"LETTER-OF"
+ "LETTER-NAME-OF"
"VALUE-OF"
+ "BLANK-TILE"
+ "USED-FOR"
"BOARD"
"AT-XY"
@@ -43,6 +46,9 @@
"MOVE-WITHDRAWAL"
"REASON-OF"
+ "TILE-SWAP"
+ "COUNT-OF"
+
"GAME"
"LANGUAGE-OF"
"PARTICIPANTS-OF"
Modified: branches/trunk-reorg/projects/scrabble/src/rules.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/rules.lisp 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/src/rules.lisp 2007-11-25 05:37:30 UTC (rev 2285)
@@ -24,15 +24,20 @@
(defclass tile-placement ()
((x :reader x-of :initarg :x)
(y :reader y-of :initarg :y)
- (tile :reader tile-of :initarg :tile))
+ (tile :reader tile-of :initarg :tile)
+ (used-for :reader used-for :initarg :used-for))
(:documentation "Represents placement of a letter tile on the board"))
(defmethod print-object ((tile-placement tile-placement) stream)
(print-unreadable-object (tile-placement stream :type t)
- (format stream "~A ~A => ~A" (x-of tile-placement) (y-of tile-placement) (tile-of tile-placement))))
+ (format stream "~A ~A => ~A ~@[(~A)~]"
+ (x-of tile-placement)
+ (y-of tile-placement)
+ (tile-of tile-placement)
+ (used-for tile-placement))))
-(defun make-tile-placement (x y tile)
- (make-instance 'tile-placement :x x :y y :tile tile))
+(defun make-tile-placement (x y tile used-for)
+ (make-instance 'tile-placement :x x :y y :tile tile :used-for used-for))
(defun make-tile-placements (list-of-moves)
(mapcar (curry #'apply 'make-tile-placement) list-of-moves))
@@ -60,7 +65,7 @@
(terpri stream)
(dotimes (x 15)
(dotimes (y 15)
- (format stream "~C " (aif (at-xy board x y) (letter-of it) #\.)))
+ (format stream "~C " (aif (at-xy board x y) (used-for it) #\.)))
(terpri stream))))
(defmethod at-xy ((board board) x y)
@@ -77,14 +82,47 @@
(value :reader value-of :initarg :value))
(:metaclass persistent-class))
+(defmethod used-for ((tile tile))
+ (letter-of tile))
+
+(defclass blank-tile (tile)
+ ((used-for :accessor used-for :initform nil))
+ (:default-initargs :letter nil :value 0)
+ (:metaclass persistent-class))
+
+(defmethod letter-name-of ((character character))
+ (if (and (char-name character)
+ (< 127 (char-code character)))
+ (string-upcase (char-name character))
+ (make-string 1 :initial-element character)))
+
+(defmethod letter-name-of ((tile tile))
+ (letter-name-of (letter-of tile)))
+
+(defmethod letter-name-of ((tile blank-tile))
+ (awhen (used-for tile)
+ (letter-name-of it)))
+
(defmethod print-object ((tile tile) stream)
(print-unreadable-object (tile stream :type t :identity nil)
(with-slots (letter value) tile
- (format stream "~A (~A) ID:~A" (when letter (char-name letter)) value (store-object-id tile)))))
+ (format stream "~A (~A) ID:~A" (when letter (letter-name-of letter)) value (store-object-id tile)))))
-(defun make-tile (letter value)
+(defmethod print-object ((tile blank-tile) stream)
+ (print-unreadable-object (tile stream :type t :identity nil)
+ (with-slots (letter value) tile
+ (format stream "~@[used for ~A ~]ID:~A"
+ (when (used-for tile)
+ (letter-name-of (used-for tile)))
+ (store-object-id tile)))))
+
+(defmethod make-tile ((letter character) value)
(make-object 'tile :letter letter :value value))
+(defmethod make-tile ((letter (eql nil)) value)
+ (declare (ignore value))
+ (make-object 'blank-tile))
+
(defmethod placed-tile-adjacent ((board board) (tile-placement tile-placement))
"Check whether the given TILE-PLACEMENT on the board is adjacent to
another tile or if it is the start position."
@@ -125,7 +163,7 @@
(error 'not-in-a-row))
(when (some (curry #'at-placement board) placed-tiles)
- (error 'tile-placed-on-occupied-field))
+ (error 'placed-on-occupied-field))
(unless (equal placed-tiles
(remove-duplicates placed-tiles :test #'equal-position))
@@ -142,7 +180,7 @@
(unless (or (find '(7 7) placed-tiles :test #'position-equal)
(some (curry #'placed-tile-adjacent board) placed-tiles))
(error 'not-touching-other-tile))
-
+
t)
(defmethod x-of ((placement list))
@@ -154,6 +192,9 @@
(defmethod tile-of ((placement list))
(third placement))
+(defmethod used-for ((placement list))
+ (fourth placement))
+
(defun words-formed% (board placed-tiles verticalp)
"Scan for words that would be formed by placing PLACED-TILES on
BOARD. VERTICALP determines the scan order, if nil, the board is
@@ -164,11 +205,13 @@
(when (find x placed-tiles :key (if verticalp #'y-of #'x-of) :test #'=)
(let (word is-new-word)
(dotimes (y 15)
- (multiple-value-bind (placed-tile being-placed) (placed-or-being-placed board placed-tiles (if verticalp (list y x) (list x y)))
+ (multiple-value-bind (placed-tile being-placed)
+ (placed-or-being-placed board placed-tiles (if verticalp (list y x) (list x y)))
(when (and word (null placed-tile))
(when (and (cdr word) is-new-word)
(push (nreverse word) words))
- (setf word nil is-new-word nil))
+ (setf word nil
+ is-new-word nil))
(when placed-tile
(push (list placed-tile (and being-placed (field-type x y))) word)
(when being-placed
@@ -205,5 +248,4 @@
(defun word-text (word-result)
"Convert the letter in a word result returned by WORDS-FORMED to a
string."
- (coerce (mapcar (compose #'letter-of #'car) word-result) 'string))
-
+ (coerce (mapcar (compose #'used-for #'car) word-result) 'string))
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp
===================================================================
--- branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/src/web.lisp 2007-11-25 05:37:30 UTC (rev 2285)
@@ -6,27 +6,43 @@
(defun encode-json-plist (plist stream)
(princ #\{ stream)
- (loop for (key value) on plist by #'cddr
+ (loop for (key value &rest rest) on plist by #'cddr
do (encode-json key stream)
do (princ #\: stream)
do (encode-json value stream)
+ when rest
do (princ #\, stream))
(princ #\} stream))
(defmethod encode-json ((object store-object) stream)
- (princ #\{ stream)
- (dolist (slotdef (closer-mop:class-slots (class-of object)))
- (when (and (slot-boundp object (closer-mop:slot-definition-name slotdef))
- (not (find (closer-mop:slot-definition-name slotdef) *ignore-slots*)))
- (encode-json (closer-mop:slot-definition-name slotdef) stream)
- (princ #\: stream)
- (encode-json (slot-value object (closer-mop:slot-definition-name slotdef)) stream)
- (princ #\, stream)))
- (princ #\} stream))
+ (let (printed)
+ (princ #\{ stream)
+ (dolist (slotdef (closer-mop:class-slots (class-of object)))
+ (when (and (slot-boundp object (closer-mop:slot-definition-name slotdef))
+ (not (find (closer-mop:slot-definition-name slotdef) *ignore-slots*)))
+ (if printed
+ (princ #\, stream)
+ (setf printed t))
+ (encode-json (closer-mop:slot-definition-name slotdef) stream)
+ (princ #\: stream)
+ (encode-json (slot-value object (closer-mop:slot-definition-name slotdef)) stream)))
+ (princ #\} stream)))
(defmethod encode-json ((tile-bag tile-bag) stream)
(encode-json-plist (list :remaining-tiles (remaining-tile-count tile-bag)) stream))
+(defmethod encode-json ((tile tile) stream)
+ (encode-json-plist (list :letter (letter-name-of tile)
+ :value (value-of tile))
+ stream))
+
+(defmethod encode-json ((tile blank-tile) stream)
+ (encode-json-plist (append (list :letter nil
+ :value 0)
+ (awhen (used-for tile)
+ (list :used-for it)))
+ stream))
+
(defmethod encode-json ((move move) stream)
(encode-json-plist (list :type "move"
:participant-login (user-login (player-of (participant-of move)))
@@ -44,17 +60,30 @@
: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)))
+ :reason (count-of move))
+ stream))
+
(defmethod encode-json ((board board) stream)
- (princ #\[ stream)
- (dotimes (x 15)
- (dotimes (y 15)
- (awhen (at-xy board x y)
- (encode-json (list x y (letter-of it) (value-of it)) stream)
- (princ #\, stream))))
- (princ #\] stream))
+ (let (printed)
+ (princ #\[ stream)
+ (dotimes (x 15)
+ (dotimes (y 15)
+ (awhen (at-xy board x y)
+ (if printed
+ (princ #\, stream)
+ (setf printed t))
+ (encode-json (append (list x y (letter-name-of it))
+ (when (typep it 'scrabble::blank-tile)
+ (list 1)))
+ stream))))
+ (princ #\] stream)))
(defmethod encode-json ((participant participant) stream)
(start-session)
+ (format t "user: ~A~%" (session-value :user))
(encode-json-plist (append (list :login (user-login (player-of participant))
:name (user-full-name (player-of participant))
:remaining-tiles)
@@ -84,27 +113,31 @@
(:tr (:td) (:td (:input :type "SUBMIT")))))))))
(defun parse-move (participant string)
- "Given a string X1,Y1,LETTER1,X2,Y2,LETTER2..., return a list of
-moves ((X1 Y1 LETTER-TILE2) (X2 Y2 LETTER-TILE2) ...). LETTERx may
-either be a single-character letter which will be used directly or a
-character name (like LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS) which will
-be converted into a character using NAME-CHAR."
+ "Given a string X1,Y1,LETTER1,FLAG1,X2,Y2,LETTER2,FLAG2..., return a
+list of moves ((X1 Y1 LETTER-TILE1 FLAG1) (X2 Y2 LETTER-TILE2 FLAG2)
+...). LETTERx may either be a single-character letter which will be
+used directly or a character name (like
+LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS) which will be converted into a
+character using NAME-CHAR."
(let ((tray (tray-of participant))
list-of-moves)
(labels
- ((use-letter (letter)
- (awhen (or (find letter tray :key #'letter-of)
- (find nil tray :key #'letter-of))
+ ((use-letter (letter is-blank)
+ (format t "use-letter ~A ~A~%" letter is-blank)
+ (awhen (find (if is-blank nil letter) tray :key #'letter-of)
(setf tray (remove it tray))
(return-from use-letter it))
(error "tray of ~A does not contain letter ~A" participant letter))
- (recurse (x-string y-string letter &rest more)
- (push (list (parse-integer x-string)
- (parse-integer y-string)
- (use-letter (if (= 1 (length letter))
- (aref letter 0)
- (name-char letter))))
- list-of-moves)
+ (recurse (x-string y-string letter is-blank &rest more)
+ (let ((letter (if (= 1 (length letter))
+ (aref letter 0)
+ (name-char letter)))
+ (is-blank (string-equal "true" is-blank)))
+ (push (list (parse-integer x-string)
+ (parse-integer y-string)
+ (use-letter letter is-blank)
+ (when is-blank letter))
+ list-of-moves))
(when more
(apply #'recurse more))))
(apply #'recurse (split "," string)))
Added: branches/trunk-reorg/projects/scrabble/website/images/de/A-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/A-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/B-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/B-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/C-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/C-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/D-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/D-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/E-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/E-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/F-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/F-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/G-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/G-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/H-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/H-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/I-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/I-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/J-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/J-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/K-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/K-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/L-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/L-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/M-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/M-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/N-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/N-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Deleted: branches/trunk-reorg/projects/scrabble/website/images/de/NIL.png
===================================================================
(Binary files differ)
Added: branches/trunk-reorg/projects/scrabble/website/images/de/O-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/O-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/P-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/P-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/Q-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/Q-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/R-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/R-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/S-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/S-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/T-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/T-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/U-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/U-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/V-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/V-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/W-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/W-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/X-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/X-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/Y-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/Y-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/trunk-reorg/projects/scrabble/website/images/de/Z-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/Z-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: branches/trunk-reorg/projects/scrabble/website/images/de/charmap.xml
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/images/de/charmap.xml 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/website/images/de/charmap.xml 2007-11-25 05:37:30 UTC (rev 2285)
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
-<chars><char filename="A.png">A</char><char filename="B.png">B</char><char filename="C.png">C</char><char filename="D.png">D</char><char filename="E.png">E</char><char filename="F.png">F</char><char filename="G.png">G</char><char filename="H.png">H</char><char filename="I.png">I</char><char filename="J.png">J</char><char filename="K.png">K</char><char filename="L.png">L</char><char filename="M.png">M</char><char filename="N.png">N</char><char filename="O.png">O</char><char filename="P.png">P</char><char filename="Q.png">Q</char><char filename="R.png">R</char><char filename="S.png">S</char><char filename="T.png">T</char><char filename="U.png">U</char><char filename="V.png">V</char><char filename="W.png">W</char><char filename="X.png">X</char><char filename="Y.png">Y</char><char filename="Z.png">Z</char><char filename="LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS.png">Ä</char><char filename="LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS.png">Ö</char><char filename="LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS.png">Ü</char><char filename="NIL.png">NIL</char></chars>
\ No newline at end of file
+<chars><char filename="A.png" blank-filename="A-blank.png">A</char><char filename="B.png" blank-filename="B-blank.png">B</char><char filename="C.png" blank-filename="C-blank.png">C</char><char filename="D.png" blank-filename="D-blank.png">D</char><char filename="E.png" blank-filename="E-blank.png">E</char><char filename="F.png" blank-filename="F-blank.png">F</char><char filename="G.png" blank-filename="G-blank.png">G</char><char filename="H.png" blank-filename="H-blank.png">H</char><char filename="I.png" blank-filename="I-blank.png">I</char><char filename="J.png" blank-filename="J-blank.png">J</char><char filename="K.png" blank-filename="K-blank.png">K</char><char filename="L.png" blank-filename="L-blank.png">L</char><char filename="M.png" blank-filename="M-blank.png">M</char><char filename="N.png" blank-filename="N-blank.png">N</char><char filename="O.png" blank-filename="O-blank.png">O</char><char filename="P.png" blank-filename="P-blank.png">P</char><char filename="Q.png" blank-filename="Q-blank.png">Q</char><char filename="R.png" blank-filename="R-blank.png">R</char><char filename="S.png" blank-filename="S-blank.png">S</char><char filename="T.png" blank-filename="T-blank.png">T</char><char filename="U.png" blank-filename="U-blank.png">U</char><char filename="V.png" blank-filename="V-blank.png">V</char><char filename="W.png" blank-filename="W-blank.png">W</char><char filename="X.png" blank-filename="X-blank.png">X</char><char filename="Y.png" blank-filename="Y-blank.png">Y</char><char filename="Z.png" blank-filename="Z-blank.png">Z</char><char filename="LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS.png" blank-filename="LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS-blank.png">Ä</char><char filename="LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS.png" blank-filename="LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS-blank.png">Ö</char><char filename="LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS.png" blank-filename="LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS-blank.png">Ü</char><char filename="null.png" blank-filename="null-blank.png">NIL</char></chars>
\ No newline at end of file
Modified: branches/trunk-reorg/projects/scrabble/website/images/de/double-letter.png
===================================================================
(Binary files differ)
Modified: branches/trunk-reorg/projects/scrabble/website/images/de/double-word.png
===================================================================
(Binary files differ)
Added: branches/trunk-reorg/projects/scrabble/website/images/de/null-blank.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/null-blank.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Copied: branches/trunk-reorg/projects/scrabble/website/images/de/null.png (from rev 2277, branches/trunk-reorg/projects/scrabble/website/images/de/NIL.png)
Added: branches/trunk-reorg/projects/scrabble/website/images/de/start-field.png
===================================================================
(Binary files differ)
Property changes on: branches/trunk-reorg/projects/scrabble/website/images/de/start-field.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: branches/trunk-reorg/projects/scrabble/website/images/de/triple-letter.png
===================================================================
(Binary files differ)
Modified: branches/trunk-reorg/projects/scrabble/website/images/de/triple-word.png
===================================================================
(Binary files differ)
Deleted: branches/trunk-reorg/projects/scrabble/website/images/en/NIL.png
===================================================================
(Binary files differ)
Copied: branches/trunk-reorg/projects/scrabble/website/images/en/null.png (from rev 2277, branches/trunk-reorg/projects/scrabble/website/images/en/NIL.png)
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.css
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.css 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.css 2007-11-25 05:37:30 UTC (rev 2285)
@@ -1,2 +1,2 @@
body { background-color: #004B36; color: #ffffff; font-family: sans-serif }
-#playfield { position: absolute }
+#playfield { position: absolute; top: 0px; left: 0px }
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.html
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.html 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.html 2007-11-25 05:37:30 UTC (rev 2285)
@@ -10,7 +10,7 @@
<script type="text/javascript" src="scrabble.js"> </script>
</head>
<body onload="init()">
- <div id='playfield'>
+ <div id="playfield">
</div>
<div style="position: absolute; right: 20px; top: 20px;"><a style="color: white;" href="/login?login=user1">user1</a></div>
<div style="position: absolute; right: 20px; top: 40px;"><a style="color: white;" href="/login?login=user2">user2</a></div>
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
===================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-17 10:28:57 UTC (rev 2284)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js 2007-11-25 05:37:30 UTC (rev 2285)
@@ -39,7 +39,7 @@
// return if the move is legal.
var positions = map(function (placement) { return [ placement[0], placement[1] ] }, placedTiles)
- .sort(function (a, b) { (a[0] > b[0]) || (a[1] > b[1])});
+ .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
&& filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
@@ -59,8 +59,8 @@
if (findValue(positions, [ 7, 7 ]) == -1) {
var found = false;
- for (var x = startOfPlacement[0]; !found && x <= endOfPlacement[0]; x++) {
- for (var y = startOfPlacement[1]; !found && y <= endOfPlacement[1]; y++) {
+ for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
+ for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
if (((x > 0) && letterAt(x - 1, y))
|| ((x < 14) && letterAt(x + 1, y))
|| ((y > 0) && letterAt(x, y - 1))
@@ -83,6 +83,7 @@
}
var theirTrays;
+var tray = [];
var gameID = 108;
var board;
@@ -99,7 +100,8 @@
element.style.position = 'absolute';
element.style.width = '40px';
element.style.height = '40px';
- element.style.backgroundImage = 'url(images/' + getFieldScore(x, y) + '.png)';
+ var imageName = (x == 7 && y == 7) ? "start-field" : getFieldScore(x, y);
+ element.style.backgroundImage = 'url(images/' + imageName + '.png)';
element.x = x;
element.y = y;
setElementPosition(element, { x: border + x * 44, y: border + y * 44 });
@@ -109,13 +111,6 @@
appendChildNodes(container, board[x]);
}
- myTrayContainer = DIV();
- myTrayContainer.style.position = 'absolute';
- myTrayContainer.style.width = 7 * 44 + 'px';
- myTrayContainer.style.height = '44px';
- setElementPosition(myTrayContainer, { x: border + 194, y: border + 665 });
- appendChildNodes(container, myTrayContainer);
-
theirTrays = DIV();
theirTrays.style.position = 'absolute';
theirTrays.style.width = 7 * 44 + 'px';
@@ -138,25 +133,34 @@
// appendChildNodes(container, clearButton);
}
-function setLetter(x, y, letter, justPlaced) {
- var image = IMG({ src: 'images/' + letter + '.png'});
+function setLetter(x, y, letter, isBlank) {
+ var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
image.style.position = 'absolute';
image.style.top = '3px';
image.style.left = '3px';
- replaceChildNodes(board[x][y], image);
- if (justPlaced) {
- var mask = IMG({ src: 'images/mask.png'});
- mask.style.position = 'absolute';
- mask.style.top = '3px';
- mask.style.left = '3px';
- appendChildNodes(board[x][y], mask);
- }
+ setElementPosition(image, { x: border + x * 44 + 3, y: border + y * 44 + 3 });
+ appendChildNodes($('playfield'), image);
board[x][y].letterNode = image;
board[x][y].letter = letter;
- board[x][y].justPlaced = justPlaced;
- YAHOO.util.Event.purgeElement(board[x][y], false, 'click');
}
+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 letterAt(x, y) {
return board[x][y].letter && !board[x][y].justPlaced;
}
@@ -176,12 +180,14 @@
this.set = function(x, y) {
this.x = x;
this.y = y;
- replaceChildNodes(board[x][y], this.image);
+ appendChildNodes(board[x][y], this.image);
+ board[x][y].cursor = this.image;
};
this.clear = function() {
if (this.x != -1) {
- replaceChildNodes(board[this.x][this.y]);
+ removeElement(board[this.x][this.y].cursor);
+ board[this.x][this.y].cursor = undefined;
this.x = this.y = -1;
this.direction = 0;
}
@@ -211,18 +217,8 @@
this.direction = direction;
if (this.direction == horizontal) {
x++;
- for (; x < 15; x++) {
- if (board[x][y].childNodes.length == 0) {
- break;
- }
- }
} else {
y++;
- for (; y < 15; y++) {
- if (board[x][y].childNodes.length == 0) {
- break;
- }
- }
}
if ((x != 15) && (y != 15)) {
this.set(x, y);
@@ -239,8 +235,8 @@
var move = [];
-function makeMove(x, y, letter) {
- move[move.length] = [x, y, letter];
+function makeMove(x, y, letter, isBlank) {
+ move[move.length] = [x, y, letter, isBlank];
try {
checkMoveLegality(move);
$('move').onclick = submitMove;
@@ -299,9 +295,30 @@
var letter = specialKeyCodes[args[0]] || String.fromCharCode(args[0]);
var x = cursor.x;
var y = cursor.y;
- cursor.advance();
- setLetter(x, y, letter, true);
- makeMove(x, y, letter);
+ var tilePosition = -1;
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == letter) {
+ tilePosition = i;
+ }
+ }
+ if (tilePosition == -1) {
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == undefined) {
+ tilePosition = i;
+ }
+ }
+ }
+ if (tilePosition == -1) {
+ alert("You don't have that letter!");
+ } else {
+ cursor.advance();
+ if (!letterAt(x, y)) {
+ var tile = tray[tilePosition];
+ tray.splice(tilePosition, 1);
+ placeLetter(x, y, tile);
+ makeMove(x, y, letter, tile.letter == undefined);
+ }
+ }
}
var leftKey = 37;
@@ -358,8 +375,6 @@
}
}
-var tray;
-
function trayClick(letter) {
this.clicked = !this.clicked;
this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
@@ -367,6 +382,7 @@
}
function makeMyTray(letters) {
+ map(removeElement, tray);
tray = [];
for (var i = 0; i < letters.length; i++) {
var element = IMG({src: 'images/' + letters[i] + '.png'});
@@ -374,11 +390,13 @@
element.style.position = 'absolute';
element.style.width = '34px';
element.style.height = '34px';
+ element.style.zIndex = '10';
element.onclick = trayClick;
- setElementPosition(element, { x: i * 40 });
+ // setElementPosition(element, { x: border + 194 + i * 40, y: border + 665 });
+ YAHOO.util.Dom.setXY(element, [ border + 194 + i * 40, border + 665 ]);
tray[i] = element;
}
- replaceChildNodes(myTrayContainer, tray);
+ appendChildNodes($('playfield'), tray);
}
function shuffleMyTray() {
@@ -401,7 +419,7 @@
function addTheirTray (participant) {
appendChildNodes(theirTrays, DIV(null,
DIV(null, participant.name),
- DIV(null, map(function () { return IMG({ src: 'images/NIL.png' }) },
+ DIV(null, map(function () { return IMG({ src: 'images/null.png' }) },
new Array(participant.remainingTiles)))));
}
@@ -410,7 +428,7 @@
var x = gameState.board[i][0];
var y = gameState.board[i][1];
var char = gameState.board[i][2];
- setLetter(x, y, char);
+ setLetter(x, y, char, gameState.board[i].length > 3);
}
for (var i = 0; i < gameState.participants.length; i++) {
var participant = gameState.participants[i];
@@ -451,5 +469,5 @@
setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });
appendChildNodes(document.body, moveDisplay);
var d = loadJSONDoc("/game/" + gameID);
- d.addCallbacks(drawGameState, alert);
+ d.addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
}
1
0