diff --git a/README.md b/README.md
index 968014a..e61abdd 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,8 @@ Zie [voorbeeld in video-formaat](sample/chess-gui.webm).
- [x] Gebruikt AJAX (in JSON) voor elke valide zet(paar).
- [x] Sessies voor onderbreking.
- [x] Status messages.
-- [ ] Duidelijke (en mooie) layout.
-- [ ] In-game opties (die men op elk moment kan wijzigen).
+- [x] Duidelijke (en mooie) layout.
+- [x] In-game opties (die men op elk moment kan wijzigen).
- [ ] Animatie van pionnen wanneer je ze sleept over het veld.
- [ ] Modulariteit (met Roy/chess).
- [ ] Veld voor weggewerkte pionnen.
diff --git a/chess_gui/lib/chess_gui.pm b/chess_gui/lib/chess_gui.pm
index 521eb96..62218be 100644
--- a/chess_gui/lib/chess_gui.pm
+++ b/chess_gui/lib/chess_gui.pm
@@ -718,7 +718,9 @@ my ($pval, $called_player, $reason, $session) = @_; # Arguments: (Value of all p
}
sub PROGRAM {
+if (!defined($user_mode{$_[2]})) { # Default user mode.
$user_mode{$_[2]} = 0;
+}
# if (!defined($user_mode)) {
# print 'Please input your side:', "\n";
# foreach (@player) {
@@ -742,7 +744,7 @@ $user_mode{$_[2]} = 0;
# }
# MATCH: while (1) {
- my %diff;
+ my (%diff, $onlykingcanmove);
$player_turn{$_[2]}++;
# $player = ($player_turn+1) % 2;
@@ -823,21 +825,25 @@ $user_mode{$_[2]} = 0;
if ($matches == 0) {
$counter{$_[2]}++;
if ($counter{$_[2]} >= 2 && $player_turn{$_[2]} > 24) { # End the game if the same applies to the opponent (only the king can move), and $player_turn have passed.
+ $onlykingcanmove = 0;
# @{$diff{'msg'}{'gstatus'}}[$player] = 'Only the kings can act. Stalemate...';
push @{$diff{$pplayer[$player]}{'status'}}, 4;
- &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ if ($player == 1) { # Undefine once, for the last player.
+ &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ }
# return;
}
}
- if ($player_turn{$_[2]} >= $action_limit) { # TODO: Is this needed when we have @pseudoinfinite_loop_check?
+ if (!(defined($onlykingcanmove)) && $player_turn{$_[2]} >= $action_limit) { # TODO: Is this needed when we have @pseudoinfinite_loop_check?
# @{$diff{'msg'}{'gstatus'}}[$player] = 'Total turn limit ' . ($player_turn*2) . ' reached: Stalemate...';
push @{$diff{$pplayer[$player]}{'status'}}, 3;
- &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ if ($player == 1) { # Undefine once, for the last player.
+ &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ }
# return;
}
-
- if (($player_turn{$_[2]}*2+$player) % ($loop_limit+1) == 0) { # When player 0 is iterating through all chess possibilities in training mode, stop & do the usual decrement when both players have been doing the same four-turn loop at least three times successively. If we don't stop the program here but do stop the four-turn loop, player 1 might prioritize creating loops when breaking the loop would be a final blow for player 0. TODO: Alternatively, we might revert back here to some previous state...
+ elsif (($player_turn{$_[2]}*2+$player) % ($loop_limit+1) == 0) { # When player 0 is iterating through all chess possibilities in training mode, stop & do the usual decrement when both players have been doing the same four-turn loop at least three times successively. If we don't stop the program here but do stop the four-turn loop, player 1 might prioritize creating loops when breaking the loop would be a final blow for player 0. TODO: Alternatively, we might revert back here to some previous state...
my ($evenval1, $unevenval1, $evenval2, $unevenval2);
for (my $counter3 = 0; $#{$pseudoinfinite_loop_check{$_[2]}} >= $counter3; $counter3++) {
if ($counter3 > 1) {
@@ -873,7 +879,9 @@ $user_mode{$_[2]} = 0;
}
# @{$diff{'status'}}[$player] = 'Loop limit ' . $loop_limit . ' reached: Stalemate...';
push @{$diff{$pplayer[$player]}{'status'}}, 2;
- &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ if ($player == 1) { # Undefine once, for the last player.
+ &POSTCHESS_CALC(&PRETTY_CALC(0, $player), 0, $_[2]);
+ }
# return;
}
undef @{$pseudoinfinite_loop_check{$_[2]}};
@@ -943,11 +951,22 @@ get '/board/init' => sub {
encode_json(\%default_iboard);
};
-get '/move/:src/:dst/:stt' => sub {
+get '/move/:src/:dst/:stt' => sub { # Logic.
+#print route_parameters->get('src'), "\n";
my %diff = &PROGRAM(route_parameters->get('src'), route_parameters->get('dst'), route_parameters->get('stt')); # Includes player input.
encode_json(\%diff);
};
+get '/board/set/:setting/:stt' => sub { # Settings.
+if (route_parameters->get('setting') eq 'Spectator') {
+ $user_mode{route_parameters->get('stt')} = -1;
+} elsif (route_parameters->get('setting') eq 'White') {
+ $user_mode{route_parameters->get('stt')} = 0;
+} elsif (route_parameters->get('setting') eq 'Black') {
+ $user_mode{route_parameters->get('stt')} = 1;
+}
+};
+
get '/' => sub {
send_file '/index.html';
};
diff --git a/chess_gui/public/css/index.css b/chess_gui/public/css/index.css
index cbe268e..82cb43d 100644
--- a/chess_gui/public/css/index.css
+++ b/chess_gui/public/css/index.css
@@ -4,12 +4,44 @@
border-style: solid;
overflow-x: scroll;
scrollbar-width: none;
+ background: linear-gradient(to right,transparent 90%,#000),repeating-linear-gradient(90deg,#000 1px,transparent 9px);
}
#main {
display: grid;
}
+html {
+ background: url(../i/bg.png);
+}
+
+#notice, #warning {
+ position: absolute;
+ right: 2vmin;
+ top: 14vmin;
+ background-color: #e66d;
+/* padding: 4px;*/
+ text-align: center;
+ border-radius: 25%;
+ border-left-style: solid;
+ border-right-style: solid;
+ min-width: 178px;
+ box-shadow: inset 4px 4px 4px #bbbbbb;
+}
+
+#warning {
+ right: 0;
+ top: 25%;
+ border-radius: 0;
+ width: 100%;
+ font-size: larger;
+ padding: 5px;
+}
+
+h1 {
+ text-decoration-line: underline;
+}
+
/* Chess board START */
#board a {
@@ -20,19 +52,24 @@
display: flex;
flex-flow: column-reverse; /* Order depends on player side #1/3 */
padding-left: 24px;
- max-inline-size: 75vh; /* TODO: We don't use SVG for the chess pieces, so it might look pixelated on high-res. Wouldn't it be better to have a resizeable board? */
+ max-inline-size: 356px; /* TODO: We don't use SVG for the chess pieces, so it might look pixelated on high-res. Wouldn't it be better to have a resizeable board? */
min-width: 178px; /* From this point onward the item list font size will be too large */
+ /* From this point onward the pieces will seem pixelated */
+ background-color: peru;
+ /*! margin-left: 24px; */
+ box-shadow: 10px 10px 20px 10px;
}
.x-row {
display: flex;
flex-flow: row nowrap; /* Order depends on player side #2/3 */
- padding-left: 32px;
+ padding-left: 0;
/*! min-width: 140px; */
}
#y-co > li {
flex: 1;
+ border-left-style: ridge;
}
#y-co > li:nth-child(2n) > .x-row > li:nth-child(2n) {
@@ -56,21 +93,25 @@
/*}*/
#y-co:not(.x-row) {
- border-style: solid;
+ border-style: groove;
+ border-width: thick;
+ border-color: tan;
}
#x-co {
display: flex;
- padding-top: 1em;
+ /*! padding-top: 1em; */
flex-flow: row nowrap;
list-style-position: inside;
list-style-type: upper-alpha;
- padding-left: 32px;
+ padding-left: 0px;
+ height: 24px;
+ border-top-style: ridge;
}
#x-co > li {
flex: 1 1 32px;
- padding-top: 1em;
+ padding-top: 0.4em;
}
img {
@@ -111,6 +152,7 @@ figure {
display: flex;
flex-flow: row;
margin: 0 5px 0 5px;
+ border-radius: 5%;
}
figure img {
@@ -145,16 +187,19 @@ dd.noimg { /* Display text of
and
at the same height when there's no i
}
.features > li {
- padding: 10px;
- flex: 0 1 auto;
+ flex: 1 1 89px;
+ border-left-style: solid;
+ border-color: white;
}
.features {
display: flex;
flex-flow: row wrap;
- background-color: #5583;
+ background-color: #123;
font-weight: bold;
font-family: sans-serif;
+ text-align: center;
+ box-shadow: inset 10px 20px 10px #345;
}
.keys {
@@ -191,6 +236,8 @@ ul.features > li:hover > ul > li {
ul a {
text-decoration: none;
display: block;
+ height: inherit;
+ color: #dd6600;
}
.key > ul > li:nth-last-child(n+2) a {
@@ -216,7 +263,13 @@ ul a {
}
a:hover {
- color: green;
+ color: #ff22ff;
+ text-decoration: underline;
+}
+
+.values > li > a:hover, .keys > li > a:hover {
+ background-color: #123;
+ box-shadow: inset 2px 4px 2px #345;
}
.option {
@@ -226,4 +279,24 @@ a:hover {
padding: 5px;
}
+.features > li > a {
+ padding: 8px;
+}
+
/* Chess control panel END */
+
+/* Status messages animation START */
+
+@keyframes fadeOut {
+to {
+opacity: 0;
+}
+}
+
+@keyframes fadeIn {
+to {
+opacity: 1;
+}
+}
+
+/* Status messages animation END */
diff --git a/chess_gui/public/i/bg.png b/chess_gui/public/i/bg.png
new file mode 100644
index 0000000..5ca25f1
Binary files /dev/null and b/chess_gui/public/i/bg.png differ
diff --git a/chess_gui/public/js/dand.js b/chess_gui/public/js/dand.js
index afa7231..1e384f2 100644
--- a/chess_gui/public/js/dand.js
+++ b/chess_gui/public/js/dand.js
@@ -13,6 +13,7 @@ var pp = ['White','Black'];
var statusm = ['Your turn','Opponent\'s turn','Suggestion','You failed in deceiving your opponent.','You won','You lost','Stalemate','Confirmation','Notice','Connection lost','You resigned','Opponent resigned','Server maintenance'];
var nrsuffix = ['st', 'nd', 'rd'];
var defsuffix = 'th';
+var auto;
//x = 25;
//console.log(x.toString(36));
@@ -56,16 +57,35 @@ xhr.open('GET', 'move/' + drag + '/' + drop + '/' + localStorage.state, true);
xhr.send(null);
var h1TN = statusm[1];
+h1.innerHTML = h1TN;
+I('notice').appendChild(h1);
var h2TN = statusm[2];
h2.innerHTML = h2TN;
-I('main').insertBefore(h2, I('board'));
-h1.innerHTML = h1TN;
-I('main').insertBefore(h1, h2);
+//I('main').insertBefore(h2, I('board'));
+I('notice').appendChild(h2);
+//I('notice').removeAttribute('style');
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.opacity = 1;
+I('notice').setAttribute('style', 'animation: fadeIn 0s ease-in-out 0s normal both;');
+//I('notice').setAttribute('style', 'animation: fadeOut 3s ease-in-out 0s normal both;');
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').animate({opacity: 0}, 3000, function() {console.log('lalalalala');});
+//console.log('lalalalala');
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = '';
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0 1 normal forwards';
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0s 1 normal forwards';
+//I('main').insertBefore(h1, h2);
+//I('notice').appendChild(h1, h2);
xhr.onload = function () {
if (xhr.status === 200) {
responseObject = JSON.parse(xhr.responseText);
-if (responseObject.White.status[1] === 0 && responseObject.Black.status[1] === 0) { // Legal move(s)?
+if (responseObject.White != null && responseObject.Black != null && responseObject.White.status[1] === 0 && responseObject.Black.status[1] === 0) { // Legal move(s)?
count = 1;
if (responseObject.White.status.length === 6) {
if (responseObject.White.status[5] === 4) {
@@ -80,15 +100,29 @@ var h2TN = 'Loop limit exceeded.';
} else if (responseObject.White.status[5] === 1) {
var h1TN = statusm[4];
var h2TN = 'White took your king.';
+} else {
+var rcodew = 0;
}
} else {
var h1TN = statusm[0];
var h2TN = statusm[2];
+var rcodew = 0;
}
-h2.innerHTML = h2TN;
-I('main').insertBefore(h2, I('board'));
h1.innerHTML = h1TN;
-I('main').insertBefore(h1, h2);
+I('notice').appendChild(h1);
+h2.innerHTML = h2TN;
+//I('main').insertBefore(h2, I('board'));
+I('notice').appendChild(h2);
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = '';
+I('notice').setAttribute('style', 'animation: fadeOut 3s ease-in-out 0s normal both;');
+//I('notice').animate({opacity: 0}, 3000, {opacity: 0});
+//I('notice').style.animation = '';
+//I('notice').style.animation = 'fadeOut 3s ease-in-out';
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0s 1 normal forwards';
+//I('main').insertBefore(h1, h2);
if (responseObject.Black.status.length === 6) {
if (responseObject.Black.status[5] === 4) {
@@ -103,11 +137,26 @@ var h2TN = 'Loop limit exceeded.';
} else if (responseObject.Black.status[5] === 1) {
var h1TN = statusm[5];
var h2TN = 'Black took your king.';
+} else {
+var rcodeb = 0;
}
-h2.innerHTML = h2TN;
-I('main').insertBefore(h2, I('board'));
h1.innerHTML = h1TN;
-I('main').insertBefore(h1, h2);
+I('notice').appendChild(h1);
+h2.innerHTML = h2TN;
+//I('main').insertBefore(h2, I('board'));
+I('notice').appendChild(h2);
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = '';
+I('notice').setAttribute('style', 'animation: fadeOut 3s ease-in-out 0s normal both;');
+//I('notice').animate({opacity: 0}, 3000, {opacity: 0});
+//I('notice').style.animation = '';
+//I('notice').style.animation = 'fadeOut 3s ease-in-out';
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0s 1 normal forwards';
+//I('main').insertBefore(h1, h2);
+} else {
+var rcodeb = 0;
}
// else {
//var h1TN = statusm[1];
@@ -249,7 +298,8 @@ d.appendChild(li);
} else {
var h1TN = statusm[0];
h1.innerHTML = h1TN;
-I('main').insertBefore(h1, h2);
+//I('main').insertBefore(h1, h2);
+I('notice').appendChild(h1);
var h2TN = statusm[3];
if (count > 1) {
if (count > 3) {
@@ -261,7 +311,17 @@ h2.innerHTML = h2TN + ' for the ' + count + '' + suffix + '' + ' time
} else {
h2.innerHTML = h2TN;
}
-I('main').insertBefore(h2, I('board'));
+//I('main').insertBefore(h2, I('board'));
+I('notice').appendChild(h2);
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = '';
+I('notice').setAttribute('style', 'animation: fadeOut 3s ease-in-out 0s normal both;');
+//I('notice').animate({opacity: 0}, 3000, {opacity: 0});
+//I('notice').style.animation = '';
+//I('notice').style.animation = 'fadeOut 3s ease-in-out';
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0s 1 normal forwards';
count++;
}
// TODO: Display status and/or sleep.
@@ -272,11 +332,25 @@ count++;
//I('description').innerHTML = responseObject.Black.status[1];
} else {
var h1TN = statusm[8];
+h1.innerHTML = h1TN;
+I('notice').appendChild(h1);
var h2TN = statusm[9];
h2.innerHTML = h2TN;
-I('main').insertBefore(h2, I('board'));
-h1.innerHTML = h1TN;
-I('main').insertBefore(h1, h2);
+//I('main').insertBefore(h2, I('board'));
+I('notice').appendChild(h2);
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = '';
+I('notice').setAttribute('style', 'animation: fadeOut 3s ease-in-out 0s normal both;');
+//I('notice').animate({opacity: 0}, 3000, {opacity: 0});
+//I('notice').style.animation = '';
+//I('notice').style.animation = 'fadeOut 3s ease-in-out';
+//I('notice').style.opacity = 1; // Cancel out previous animation.
+//I('notice').style.animation = ''; // Cancel out previous animation.
+//I('notice').style.animation = 'fadeOut 3s ease-in-out 0s 1 normal forwards';
+//I('main').insertBefore(h1, h2);
+}
+if (auto === true && rcodeb === 0 && rcodew === 0) {
+dragAndDrop(null, null, auto);
}
}
}
@@ -292,3 +366,46 @@ I('main').insertBefore(h1, h2);
//drag = this.id;
//}}
//}
+
+for (var i=0; C('values').length > i; i++) { // Add event listeners for all options of the chess control panel (1/2).
+for (var j=0; C('values')[i].children.length > j; j++) {
+C('values')[i].children[j].onclick = function () {
+xhr.open('GET', 'board/set/' + this.innerText + '/' + localStorage.state, true);
+xhr.send(null);
+var selection = this.innerText;
+xhr.onload = function () {
+if (xhr.status === 200) {
+if (selection === 'Spectator') {
+auto = true;
+dragAndDrop(null, null, auto);
+} else {
+auto = false;
+}
+}
+}
+}
+}
+}
+for (var k=0; C('features')[0].children.length > k; k++) { // Add event listeners for the main navigation of the chess control panel (2/2).
+C('features')[0].children[k].onclick = function () {
+if (this.textContent === 'New game') { // Reset storage to default, regenerate chessboard, remove log, and generate a new chess game ID.
+localStorage.state = S();
+I('y-co').innerHTML = '';
+I('log').parentNode.removeChild(I('log'));
+var ol;
+var javascript = localStorage.init.split(','); // TODO: There should be a cleaner way to store/retrieve multidimensional data structures in localStorage.
+for (var i=j=0; javascript.length > j; j += 2) {
+//if (!localStorage.getItem(javascript[j+1])) {
+if (localStorage.getItem(javascript[j]) === null && !localStorage.getItem(javascript[j+1]) && (javascript[j+1] === '' || I(javascript[j+1]) === null)) {
+G(i, javascript[j], javascript[j+1]);
+} else {
+//console.log(javascript[j], localStorage.getItem(javascript[j]));
+localStorage.removeItem(javascript[j]);
+G(i, javascript[j], javascript[j+1]);
+}
+//}
+i++;
+}
+}
+}
+}
diff --git a/chess_gui/public/js/head.js b/chess_gui/public/js/head.js
index 344da9c..d1048bd 100644
--- a/chess_gui/public/js/head.js
+++ b/chess_gui/public/js/head.js
@@ -12,7 +12,7 @@ function T(a) {
return document.getElementsByTagName(a);
}
-function S() {
+function S() { // Generate a chess game ID.
var r = (Math.random()*36).toString(36).substring(2);
var f = Math.random().toString().replace(/^0\./, '');
//f = f*10**(f.toString().length-2);
@@ -78,7 +78,7 @@ li.innerHTML = srci; // Add.
postG();
}
-function postG () {
+function postG () { // Add event listeners for the generated chessboard.
var drag;
var drop;
for (var b=0; C('coord').length > b; b++) {
diff --git a/chess_gui/public/lllll b/chess_gui/public/lllll
deleted file mode 100644
index 220c60c..0000000
--- a/chess_gui/public/lllll
+++ /dev/null
@@ -1,10 +0,0 @@
-use warnings;
-use strict;
-my @pages;
-@pages = { url => 'http://foo.org',
- title => 'The Foo Organisation'
- },
- { url => 'http://bar.org',
- title => 'The Bar Organisation'
- };
-print $pages[0]{'url'};
diff --git a/chess_gui/views/index.html b/chess_gui/views/index.html
index f7d7b2d..28e5514 100644
--- a/chess_gui/views/index.html
+++ b/chess_gui/views/index.html
@@ -11,6 +11,8 @@
+