summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@chimrod.com>2014-08-31 19:52:37 +0200
committerSébastien Dailly <sebastien@chimrod.com>2014-08-31 19:52:37 +0200
commitfcca4f01fec5c97a0e2a6ca6cd9088a87aa76816 (patch)
treea9e5ec1e732ac9becad328935fb4224e72addf9a
parentd48ac3970ef04a404c42f30c72cbdc327178f0dc (diff)
Added history management
-rw-r--r--qml/javascript/goban_util.js116
-rw-r--r--qml/pages/Board.qml4
-rw-r--r--qml/pages/Goban.qml31
3 files changed, 126 insertions, 25 deletions
diff --git a/qml/javascript/goban_util.js b/qml/javascript/goban_util.js
index dfaa70c..f6f48c9 100644
--- a/qml/javascript/goban_util.js
+++ b/qml/javascript/goban_util.js
@@ -53,6 +53,8 @@ function getNeighbors(index, cols, rows) {
return neighbors;
}
+
+
function getChainToRemove(index, grid, filter) {
var piecesToCheck = [];
@@ -112,6 +114,64 @@ function getChainToRemove(index, grid, filter) {
}
+/*
+ * Undo a move on the board.
+ */
+function undo(grid, step) {
+
+ /*
+ * Fill the space with the given color.
+ */
+ function fillWith(index, color) {
+
+ /*
+ * filter wich keep only free places.
+ */
+ function freePlaces(x) {
+ return grid.getElementAtIndex(x).getType() === "";
+ }
+
+ var piece = index;
+
+ var space = [];
+
+ while (piece !== undefined) {
+
+ var point = grid.getElementAtIndex(piece);
+
+ if (point.mark || !point.getType === "") {
+ piece = space.pop();
+ continue;
+ }
+ point.mark = true;
+
+ point.put(color, false);
+
+ getNeighbors(piece, grid.columns, grid.rows).filter(freePlaces).forEach(function(x) {
+ space.push(x);
+ });
+ piece = space.pop();
+ }
+ }
+
+ /*
+ * First add each point marked as removed.
+ * Only the first point is recorded, so we fill all the other points
+ */
+
+ if (step.suicide) {
+ fillWith(step.added, step.player);
+ } else {
+ var removed = step.removed;
+ if (removed !== undefined) {
+ fillWith(step.removed, !step.player);
+ }
+ grid.getElementAtIndex(step.added).remove(false);
+ }
+
+ clearMarks(grid);
+}
+
/**
* Add a new stone on the goban.
*
@@ -126,7 +186,7 @@ function getChainToRemove(index, grid, filter) {
* animation(bool): should we add animation on the goban
* allowSuicide(bool): if suicide an autorized action
*
- * return true if the movement has been allowed.
+ * return a step object if the movement has been allowed.
*/
function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOveride) {
@@ -134,11 +194,15 @@ function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOver
var elementType = point.getType();
if (!allowOveride && elementType !== "") {
- return false;
+ return undefined;
}
var neighbors = getNeighbors(index, grid.columns, grid.rows);
+ var step = {};
+ step.added = index;
+ step.player = currentPlayer;
+
function isPlayer(x) {
return grid.getElementAtIndex(x).getType() === (currentPlayer ? "white" : "black");
}
@@ -155,7 +219,7 @@ function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOver
point.put(currentPlayer, animation);
if (neighbors.length === 0) {
- return true;
+ return step;
}
var somethingToRemove = false;
@@ -164,15 +228,20 @@ function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOver
/*
* Check for pieces to remove.
*/
- neighbors.filter(isOponnent).forEach(function(neighbor) {
+ neighbors.forEach(function(neighbor) {
+
+ if (!isOponnent(neighbor)) {
+ return;
+ }
var piecesToRemove = getChainToRemove(neighbor, grid, isOponnent);
if (piecesToRemove.length !== 0) {
+ step.removed = piecesToRemove[0];
somethingToRemove = true;
+ piecesToRemove.forEach(function(x) {
+ grid.getElementAtIndex(x).remove(animation);
+ });
}
- piecesToRemove.forEach(function(x) {
- grid.getElementAtIndex(x).remove(animation);
- })
});
/*
@@ -182,6 +251,9 @@ function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOver
var suicides = getChainToRemove(index, grid, isPlayer);
if (suicides.length !== 0) {
if (allowSuicide) {
+
+ step.suicide = true;
+
suicides.forEach(function(x) {
grid.getElementAtIndex(x).remove(animation);
});
@@ -193,20 +265,28 @@ function addPiece(index, grid, currentPlayer, animation, allowSuicide, allowOver
}
- /*
- * Remove the marks in the cases.
- *
- * The call to getChainToRemove add marks on the cases in order to
- * prevent infinite looping. We need to clean the cases before any new
- * click.
- *
- * We do not need to remove them before as we are not filtering the
+ /* We do not need to clear the marks before as we are not filtering the
* same pieces.
*/
- for (var i = 0; i < grid.columns * grid.rows; i++) {
- grid.getElementAtIndex(i).mark = false;
+ clearMarks(grid);
+
+ if (movementAutorized) {
+ return step;
+ } else {
+ return undefined;
}
+}
- return movementAutorized;
+/*
+ * Remove the marks in the cases.
+ *
+ * Some functions add marks on each stone in order to prevent infinite looping.
+ * We need to clean the cases before any new action.
+ *
+ */
+function clearMarks(grid) {
+ for (var i = 0; i < grid.columns * grid.rows; i++) {
+ grid.getElementAtIndex(i).mark = false;
+ }
}
diff --git a/qml/pages/Board.qml b/qml/pages/Board.qml
index cee8492..16c4e6b 100644
--- a/qml/pages/Board.qml
+++ b/qml/pages/Board.qml
@@ -4,8 +4,6 @@ import Sailfish.Silica 1.0
import io.thp.pyotherside 1.2
-
-
Page {
width: Screen.width; height: Screen.height;
@@ -27,7 +25,7 @@ Page {
IconButton {
width: (parent.width - parent.height) / 2;
icon.source: "image://theme/icon-m-back"
- onClicked: console.log("Previous!")
+ onClicked: goban.undo();
}
Image {
diff --git a/qml/pages/Goban.qml b/qml/pages/Goban.qml
index 420d22d..5c86700 100644
--- a/qml/pages/Goban.qml
+++ b/qml/pages/Goban.qml
@@ -27,6 +27,8 @@ Item {
property variant tree;
+ property variant history;
+
/*
* Start the game.
*
@@ -48,13 +50,13 @@ Item {
i++;
}
- initial = tree[i]
+ initial = tree[i];
+ history = [];
var aw = initial.AW;
if (aw !== undefined) {
aw.forEach(function (pos) {
goban.getItemAt(pos[0], pos[1]).put(currentPlayer, false);
-// Actions.addPiece(pos[0] + (pos[1] * goban.columns), goban, currentPlayer, false, true, true);
});
}
@@ -62,7 +64,6 @@ Item {
if (ab !== undefined) {
ab.forEach(function (pos) {
goban.getItemAt(pos[0], pos[1]).put(!currentPlayer, false);
-// Actions.addPiece(pos[0] + (pos[1] * goban.columns), goban, !currentPlayer, false, true, true);
});
}
}
@@ -94,6 +95,22 @@ Item {
start();
}
+ /*
+ * Undo the last move.
+ */
+ function undo() {
+ if (history.length === 0) {
+ return;
+ }
+
+ var currentHistory = history;
+ var step = currentHistory.pop();
+ history = currentHistory;
+
+ Actions.undo(goban, step);
+ currentPlayer = step.player;
+ }
+
/**
* Handle a click on the goban.
*/
@@ -107,8 +124,14 @@ Item {
return;
}
- if (Actions.addPiece(index, goban, currentPlayer, true, false, false)) {
+ var step = Actions.addPiece(index, goban, currentPlayer, true, false, false);
+
+ if (step !== undefined) {
currentPlayer = !currentPlayer;
+
+ var currentHistory = history;
+ currentHistory.push(step);
+ history = currentHistory;
}
}