From fcca4f01fec5c97a0e2a6ca6cd9088a87aa76816 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Sun, 31 Aug 2014 19:52:37 +0200 Subject: Added history management --- qml/javascript/goban_util.js | 116 ++++++++++++++++++++++++++++++++++++------- qml/pages/Board.qml | 4 +- qml/pages/Goban.qml | 31 ++++++++++-- 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; } } -- cgit v1.2.3