From 6c2cc134abf3f32d1d6ec172c6201f8d990c88ab Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Sun, 24 Aug 2014 12:52:10 +0200 Subject: Initial commit --- qml/pages/Board.qml | 92 ++++++++++++++++++ qml/pages/Goban.qml | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++ qml/pages/Point.qml | 29 ++++++ 3 files changed, 383 insertions(+) create mode 100644 qml/pages/Board.qml create mode 100644 qml/pages/Goban.qml create mode 100644 qml/pages/Point.qml (limited to 'qml/pages') diff --git a/qml/pages/Board.qml b/qml/pages/Board.qml new file mode 100644 index 0000000..37a0e89 --- /dev/null +++ b/qml/pages/Board.qml @@ -0,0 +1,92 @@ + +import QtQuick 2.0 +import Sailfish.Silica 1.0 + + +import io.thp.pyotherside 1.2 + + + +Page { + + width: Screen.width; height: Screen.height; + + + anchors.fill: parent + + Column { + + width:parent.width + height: parent.height + + spacing: 2 +// Row { + +// height: 60 + +// //anchors.horizontalCenter: parent.horizontalCenter +// Repeater { +// model: 3 +// Rectangle { +// width: 100; height: 40 +// border.width: 1 +// color: "yellow" +// } +// } +// } + + + Goban { + id:goban + width: parent.width + height: 650 + } + + + SlideshowView { + id: view + width: parent.width + height: 100 + itemWidth: width / 2 + onCurrentIndexChanged: {py.call('board.getGame', [view.currentIndex], goban.setGoban)} + + model: 5 + delegate: Text { + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: view.itemWidth + height: view.height + text: "Level " + index + color: "white" + + } + } + } + + Python { + id:py + Component.onCompleted: { + var pythonpath = Qt.resolvedUrl('../python').substr('file://'.length); + addImportPath(pythonpath); + console.log(pythonpath); + + importModule('board', function() { + console.log('module loaded'); + console.log('Python version: ' + pythonVersion()); + }) + + setHandler('log', function (content) { + console.log(content); + }); + + call('board.setPath', [pythonpath]); + call('board.loadBoard', ["easy.sgf"], function (result) { + console.log(result + " problems found in the file") + view.model = result + call('board.getGame', [0], goban.setGoban); + }); + + } + } + +} diff --git a/qml/pages/Goban.qml b/qml/pages/Goban.qml new file mode 100644 index 0000000..64475ec --- /dev/null +++ b/qml/pages/Goban.qml @@ -0,0 +1,262 @@ +import QtQuick 2.0 + +import "../actions.js" as Actions + +Item { + + /** + * This property represent a case size on the board. + * The value is calculated at initialization, and depends on the goban size. + */ + property int caseSize + + /** + * Booleans flags telling if the board is limited in each directions + */ + property bool limitTop: true; + property bool limitBottom: true; + property bool limitLeft: true; + property bool limitRight: true; + + /* + * The current color to play : + * - true for white + * - false for black + */ + property bool currentPlayer: true; + + function setGoban(ret) { + + limitTop = ret.side.TOP; + limitBottom = ret.side.BOTTOM; + limitLeft = ret.side.LEFT; + limitRight = ret.side.RIGHT; + + goban.columns = ret.size[0] + goban.rows = ret.size[1] + + currentPlayer = true; + + var maxWidth = width / ret.size[0] + var maxHeight = height / ret.size[1] + + if (maxWidth > maxHeight) { + caseSize = maxHeight; + } else { + caseSize = maxWidth; + } + + /* + * Put the initials stones + */ + var initial = ret.tree[0] + + var aw = initial.AW; + if (aw !== undefined) { + aw.forEach(function (pos) { + goban.getItemAt(pos[0], pos[1]).setColor(currentPlayer); + }); + } + + var ab = initial.AB; + if (ab !== undefined) { + ab.forEach(function (pos) { + goban.getItemAt(pos[0], pos[1]).setColor(!currentPlayer); + + }); + } + } + + /** + * Handle a click on the goban. + */ + function clickHandler(index) { + + + if ( !limitLeft && Actions.isFirstCol(index, goban.columns) + || !limitRight && Actions.isLastCol(index, goban.columns) + || !limitTop && Actions.isFirstRow(index, goban.rows) + || !limitBottom && Actions.isLastRow(index, goban.columns, goban.rows) ) { + return; + } + + var point = repeater.itemAt(index); + var elementType = point.getType(); + + if (elementType !== "") { + return; + } + + var neighbors = Actions.getNeighbors(index, goban.columns, goban.rows); + + function isPlayer(x) { + return repeater.itemAt(x).getType() === (currentPlayer ? "white" : "black"); + } + + function isOponnent(x) { + return repeater.itemAt(x).getType() === (currentPlayer ? "black" : "white"); + } + + /* + * Check for pieces to remove. + */ + var toRemove = neighbors.filter(isOponnent); + +// function freeOrChain(x) { +// var pointType = repeater.itemAt(x).getType(); +// return pointType === "" || pointType === (currentPlayer ? "white" : "black"); +// } +// /* +// * Single suicide is not allowed… +// */ +// if (neighbors.length !== 0 && toRemove.length === 0 && !neighbors.some(freeOrChain)) { +// return; +// } + + point.setColor(currentPlayer); + + if (neighbors.length !== 0) { + + toRemove.forEach(function(neighbor) { + Actions.getChainToRemove(neighbor, repeater, goban.columns, goban.rows, isOponnent). + forEach(function(x) { + repeater.itemAt(x).remove(); + }) + }); + + /* + * Check for suicide. + */ + Actions.getChainToRemove(index, repeater, goban.columns, goban.rows, isPlayer). + forEach(function(x) { + repeater.itemAt(x).remove(); + }); + + /* + * 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 + * same pieces. + */ + for (var i = 0; i < goban.columns * goban.rows; i++) { + repeater.itemAt(i).mark = false; + } + + } + currentPlayer = !currentPlayer; + + } + + /** + * Background + */ + Image { + width: goban.width + (caseSize / 2); height: goban.height + (caseSize / 2); + source: "../content/gfx/board.png" + anchors.centerIn: goban + } + + /* + * Horizontal lines + */ + Repeater { + model: goban.rows + + Rectangle { + + function isOpen(index) { + if ( (index === goban.rows - 1 && !limitBottom) || (index === 0 && !limitTop)) { + return "transparent" + } + return "black" + } + + x: goban.x + (caseSize / 2) + + y: goban.y + (caseSize / 2) + (index * caseSize) + + width: goban.width - caseSize; + + color: isOpen(index) + height: 1 + + } + } + + /* + * Verticals lines + */ + Repeater { + model: goban.columns + + Rectangle { + + function isOpen(index) { + if ( (index === goban.columns - 1 && !limitRight) || (index === 0 && !limitLeft)) { + return "transparent" + } + return "black" + } + + x: goban.x + (caseSize / 2) + (index * caseSize) + + y: goban.y + (caseSize / 2) + + height: goban.height - caseSize; + + color: isOpen(index) + width: 1 + } + + + } + + /* + * The grid for the game. + */ + Grid { + id: goban + anchors.centerIn: parent + columns: 0 + rows : 0 + spacing: 0 + + function getItemAt(x, y) { + return repeater.itemAt(x + y * columns) + } + + Repeater { + model: goban.columns * goban.rows + id : repeater + + Item { + + function setColor(isWhite) { + piece.type = isWhite ? "white" : "black" + } + + function remove() { + piece.type = ""; + } + + function getType() { + return piece.type; + } + + width: caseSize; height: caseSize + + property bool mark: false + + Point{ + id : piece + width: caseSize; height: caseSize + + } + } + } + } +} diff --git a/qml/pages/Point.qml b/qml/pages/Point.qml new file mode 100644 index 0000000..f610461 --- /dev/null +++ b/qml/pages/Point.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 + +import "../actions.js" as Actions + +Item { + + property string type: ""; + + function getImageForType() { + if ("" === type) { + return "" + } + + return "../content/gfx/" + type + ".png" + } + + MouseArea { + + id: interactiveArea + anchors.fill: parent + onClicked: clickHandler(index); + } + + Image { + id: piece + anchors.fill: parent + source: getImageForType(); + } +} -- cgit v1.2.3