diff --git a/CHANGELOG.md b/CHANGELOG.md
index 09bb581..c5e1e53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- UMA-17: Give the user the option of standard or ultimate tic-tac-toe
- UMA-19: Create interactive 9x9 board and allow player to make a turn
- UMA-20: Force ultimate players to play in the correct square after a move is placed
+- UMA-21: Make game completable through correct outer square selection and evaluation
## [0.2.1] - 07/11/2023
- UMA-11: Allow players to make their turns
diff --git a/src/app/game/game.py b/src/app/game/game.py
index feb2bf0..208d5a8 100644
--- a/src/app/game/game.py
+++ b/src/app/game/game.py
@@ -1,5 +1,6 @@
from flask import render_template, url_for, redirect, Blueprint
+from src.app.model.board.threeboard import ThreeBoard
from src.app.model.mood import Mood
from src.app.model.status import Status
from src.version.version import __version__
@@ -128,7 +129,12 @@ def place_ultimate_move(game_id, user_id, outer_square, inner_square):
print(board)
# Set next playable outer square
- redis.set("playableSquare", inner_square)
+ if get_game_state(redis, board[int(inner_square)]) != Status.IN_PROGRESS:
+ redis.set("playableSquare", "-1") # -1 is all squares...
+ else:
+ redis.set("playableSquare", inner_square)
+
+ print("[place_ultimate_move] playableSquare: " + redis.get("playableSquare"))
# Switch player turn
if redis.get("whoseTurn") == 'player1':
@@ -143,18 +149,6 @@ def place_ultimate_move(game_id, user_id, outer_square, inner_square):
def get_game_state(redis, board):
-
- if isinstance(board[0], list):
- print("[get_game_state] board[0]: " + str(board[0]))
- outer_state = Status.IN_PROGRESS
- inner_states = []
- for outer_square in board:
- inner_state = get_game_state(redis, outer_square)
- inner_states.append(inner_state.value)
- print("[get_game_state] inner_states: " + str(inner_states))
- redis.set_complex("innerStates", inner_states)
- return Status.IN_PROGRESS
-
winning_combos = [
[0, 1, 2],
[3, 4, 5],
@@ -166,6 +160,19 @@ def get_game_state(redis, board):
[2, 4, 6]
]
+ if isinstance(board[0], list):
+ print("[get_game_state] board[0]: " + str(board[0]))
+ outer_state = Status.IN_PROGRESS
+ inner_states = []
+ for outer_square in board:
+ inner_state = get_game_state(redis, outer_square)
+ inner_states.append(inner_state.value)
+ print("[get_game_state] inner_states: " + str(inner_states))
+ if inner_states.count('1') == 0:
+ return Status.DRAW
+ redis.set_complex("innerStates", inner_states)
+ return get_game_state(redis, create_false_board(inner_states))
+
if board.count(0) == 0:
return Status.DRAW
# FixMe :: this check needs to happen after test each player has won...
@@ -196,3 +203,26 @@ def get_player_moves(player, board):
player_moves.append(index)
return player_moves
+
+
+def convert_states_to_symbols(state):
+ if state == 1: return 0
+ if state == 2: return 0
+ if state == 3: return 1
+ if state == 4: return 2
+
+
+def create_false_board(states):
+ board = ThreeBoard()
+ board.top_lhs = convert_states_to_symbols(states[0])
+ board.top_mid = convert_states_to_symbols(states[1])
+ board.top_rhs = convert_states_to_symbols(states[2])
+ board.mid_lhs = convert_states_to_symbols(states[3])
+ board.mid_mid = convert_states_to_symbols(states[4])
+ board.mid_rhs = convert_states_to_symbols(states[5])
+ board.bot_lhs = convert_states_to_symbols(states[6])
+ board.bot_mid = convert_states_to_symbols(states[7])
+ board.bot_rhs = convert_states_to_symbols(states[8])
+
+ print("[create_false_board] board: " + str(board.list()))
+ return board.list()
diff --git a/src/resources/static/scripts/game.js b/src/resources/static/scripts/game.js
index 3b8c874..69ada4e 100644
--- a/src/resources/static/scripts/game.js
+++ b/src/resources/static/scripts/game.js
@@ -39,12 +39,16 @@ function initUltimate(thisUserId, thisSymbol) {
for (let i = 0; i < 9; i++) {
const outerSquare = document.getElementById(`nine-square-${i}`);
- if (playableSquare === "-1" || playableSquare === i.toString()) outerSquare.classList.add("playable")
if (innerStates[i] === 2) { outerSquare.classList.add("draw") }
if (innerStates[i] === 3) { outerSquare.classList.add(thisSymbol === '1' ? "this-user" : "opponent-user"); console.log(i) }
if (innerStates[i] === 4) { outerSquare.classList.add(thisSymbol === '2' ? "this-user" : "opponent-user") }
+ if (
+ (playableSquare === "-1" || playableSquare === i.toString()) &&
+ (!outerSquare.classList.contains("this-user") && !outerSquare.classList.contains("opponent-user") && !outerSquare.classList.contains("draw"))
+ ) { outerSquare.classList.add("playable") }
+
let outerBoard = []
for (let j = 0; j < 9; j++) {
const innerSquare = document.getElementById(`nine-square-${i}-${j}`).getElementsByClassName("square")[0];
diff --git a/src/resources/static/styles/css/game.css b/src/resources/static/styles/css/game.css
index 1ba707a..3f18a6b 100644
--- a/src/resources/static/styles/css/game.css
+++ b/src/resources/static/styles/css/game.css
@@ -22,14 +22,6 @@ header #badge {
height: 2.25rem;
margin: 0.5rem;
}
-header h1 {
- margin: 0.5rem;
- text-transform: uppercase;
- letter-spacing: 0.25rem;
- font-weight: 200;
- font-size: 1.5rem;
- line-height: 2.25rem;
-}
/** Tooltip */
.tooltip .tooltip-text {
@@ -256,6 +248,9 @@ header h1 {
background-color: #e70453 !important;
cursor: default !important;
}
+.nineboard .shadow-square.outer.draw .shadow-square.inner {
+ opacity: 0.1;
+}
.nineboard .shadow-square.inner {
margin: 0.375rem;
border: 1px solid rgba(231, 4, 83, 0.2509803922);
diff --git a/src/resources/static/styles/css/game.css.map b/src/resources/static/styles/css/game.css.map
index 27a23a1..a57b6e3 100644
--- a/src/resources/static/styles/css/game.css.map
+++ b/src/resources/static/styles/css/game.css.map
@@ -1 +1 @@
-{"version":3,"sourceRoot":"","sources":["../scss/base.scss","../scss/colours.scss","../scss/game.scss","../scss/spacing.scss"],"names":[],"mappings":"AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE,kBCRO;EDSP,OCSc;EDRd;;;AEZF;AACA;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAIJ;AAEE;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;;AAIJ;AACA;EACE;EACA;;AAEA;EACE,OD5BS;;AC+BX;EACE;EACA;;AAEA;EACE;;AACA;EAAwB;;AAExB;EAAwB;;AACxB;EAAwB;;AAExB;EACE;;AAGF;EACE;EACA;EACA;;AAIA;EAAmB,ODrDd;;ACsDL;EAAmB,OD5DpB;;AC8DC;EACE;;AAMF;EAAkB,ODrEnB;;ACsEC;EAAkB,ODhEb;;ACkEL;EACE;;;AAOV;AACA;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA,kBDpGM;;ACuGR;EACE;EACA;EACA,kBD1GM;;AC6GR;EACE;EACA,ODvGC;;AC0GH;EACE,OD3GC;EC4GD;EACA;EACA;;AAGF;EAA6B,OD3GpB;;AC4GT;EAA6B,ODlH1B;;ACmHH;EAA6B,ODnH1B;;ACoHH;EAA6B,OD9GpB;;;ACkHb;AAEE;EAAuB;;AACvB;EAAuB;;AACvB;EAAuB;;AACvB;EAAuB;;AAKrB;AAAA;AAAA;AAAA;EAEE;EACA;;;AAKN;EACE;EACA,QCrJmB;EDsJnB;EACA,YCzJe;ED0Jf,YCzJe;ED0Jf;;;AAGF;AAEE;EACE;EACA;EACA,kBDhKQ;ECiKR;;AAEA;EACE;EACA;EACA;EACA,kBDvKM;ECwKN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;;AAEA;EACE;EACA,kBDpLK;ECqLL;;AAEA;EACE,ODtME;;AC2MR;EACE;;AAEA;EACE;EACA,kBDxMD;ECyMC;;AAEA;EACE,ODpNE;;;AC2NZ;AAEE;EACE;;AAGE;EACE;EACA;;AAEA;EACE;EACA;;AAKN;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAKN;EACE;EACA;EACA,kBD5QQ;EC6QR;;AAEA;EACE;EACA;EACA;EACA,kBDnRM;ECoRN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;;AAEA;EACE;EACA,kBDhSK;ECiSL;;AAEA;EACE,ODlTE;;ACuTR;EACE;;AAEA;EACE;EACA,kBDpTD;ECqTC;;AAEA;EACE,ODhUE;;;ACuUZ;AACA;EACE;EACA;EACA;EACA,kBD5UU;EC6UV;EACA,OChVe;EDiVf;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAIJ;EAAiB;;AACjB;EAAiB;;AAEjB;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE,ODlWS;ECmWT;EACA,kBDnWW;;ACqWX;EACE,ODlWU;;ACsWZ;EACE,ODlXC;ECmXD;EACA,kBD5XM;;AC8XN;EACE,OD3XI;;AC8XN;EACE,ODhXQ","file":"game.css"}
\ No newline at end of file
+{"version":3,"sourceRoot":"","sources":["../scss/base.scss","../scss/colours.scss","../scss/game.scss","../scss/spacing.scss"],"names":[],"mappings":"AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE,kBCRO;EDSP,OCSc;EDRd;;;AEZF;AACA;EACE;EACA;;AAEA;EACE;EACA;;;AAIJ;AAEE;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;;AAIJ;AACA;EACE;EACA;;AAEA;EACE,ODnBS;;ACsBX;EACE;EACA;;AAEA;EACE;;AACA;EAAwB;;AAExB;EAAwB;;AACxB;EAAwB;;AAExB;EACE;;AAGF;EACE;EACA;EACA;;AAIA;EAAmB,OD5Cd;;AC6CL;EAAmB,ODnDpB;;ACqDC;EACE;;AAMF;EAAkB,OD5DnB;;AC6DC;EAAkB,ODvDb;;ACyDL;EACE;;;AAOV;AACA;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA,kBD3FM;;AC8FR;EACE;EACA;EACA,kBDjGM;;ACoGR;EACE;EACA,OD9FC;;ACiGH;EACE,ODlGC;ECmGD;EACA;EACA;;AAGF;EAA6B,ODlGpB;;ACmGT;EAA6B,ODzG1B;;AC0GH;EAA6B,OD1G1B;;AC2GH;EAA6B,ODrGpB;;;ACyGb;AAEE;EAAuB;;AACvB;EAAuB;;AACvB;EAAuB;;AACvB;EAAuB;;AAKrB;AAAA;AAAA;AAAA;EAEE;EACA;;;AAKN;EACE;EACA,QC5ImB;ED6InB;EACA,YChJe;EDiJf,YChJe;EDiJf;;;AAGF;AAEE;EACE;EACA;EACA,kBDvJQ;ECwJR;;AAEA;EACE;EACA;EACA;EACA,kBD9JM;EC+JN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;;AAEA;EACE;EACA,kBD3KK;EC4KL;;AAEA;EACE,OD7LE;;ACkMR;EACE;;AAEA;EACE;EACA,kBD/LD;ECgMC;;AAEA;EACE,OD3ME;;;ACkNZ;AAEE;EACE;;AAGE;EACE;EACA;;AAEA;EACE;EACA;;AAKN;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;;AAIJ;EACE;EACA;EACA,kBDvQQ;ECwQR;;AAEA;EACE;EACA;EACA;EACA,kBD9QM;EC+QN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;;AAEA;EACE;EACA,kBD3RK;EC4RL;;AAEA;EACE,OD7SE;;ACkTR;EACE;;AAEA;EACE;EACA,kBD/SD;ECgTC;;AAEA;EACE,OD3TE;;;ACkUZ;AACA;EACE;EACA;EACA;EACA,kBDvUU;ECwUV;EACA,OC3Ue;ED4Uf;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAIJ;EAAiB;;AACjB;EAAiB;;AAEjB;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE,OD7VS;EC8VT;EACA,kBD9VW;;ACgWX;EACE,OD7VU;;ACiWZ;EACE,OD7WC;EC8WD;EACA,kBDvXM;;ACyXN;EACE,ODtXI;;ACyXN;EACE,OD3WQ","file":"game.css"}
\ No newline at end of file
diff --git a/src/resources/static/styles/scss/game.scss b/src/resources/static/styles/scss/game.scss
index 07ce67b..85cf28a 100644
--- a/src/resources/static/styles/scss/game.scss
+++ b/src/resources/static/styles/scss/game.scss
@@ -9,15 +9,6 @@ header {
height: 2.25rem;
margin: .5rem;
}
-
- h1 {
- margin: .5rem;
- text-transform: uppercase;
- letter-spacing: .25rem;
- font-weight: 200;
- font-size: 1.5rem;
- line-height: 2.25rem;
- }
}
/** Tooltip */
@@ -264,6 +255,10 @@ header {
cursor: default !important;
}
}
+
+ &.draw .shadow-square.inner {
+ opacity: .1;
+ }
}
.shadow-square.inner {
diff --git a/src/resources/templates/game.html b/src/resources/templates/game.html
index 96a7505..65308f3 100644
--- a/src/resources/templates/game.html
+++ b/src/resources/templates/game.html
@@ -20,9 +20,10 @@