Add UI improvements. You can now change sides during a game (but not yet difficulty).

main
Roy 1 year ago
parent 4ffd43ae86
commit 1c255cc9aa
  1. 4
      README.md
  2. 29
      chess_gui/lib/chess_gui.pm
  3. 93
      chess_gui/public/css/index.css
  4. BIN
      chess_gui/public/i/bg.png
  5. 147
      chess_gui/public/js/dand.js
  6. 4
      chess_gui/public/js/head.js
  7. 10
      chess_gui/public/lllll
  8. 3
      chess_gui/views/index.html

@ -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.

@ -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;
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;
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;
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';
};

@ -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 <dd> and <dt> 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 */

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

@ -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 + '<sup>' + suffix + '</sup>' + ' 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 = '<ol id="x-co"><li></li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ol>';
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++;
}
}
}
}

@ -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++) {

@ -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'};

@ -11,6 +11,8 @@
</head>
<body>
<section id="main">
<div id="notice">
</div>
<section id="board">
<section id="panel">
<ul class="features">
@ -54,5 +56,6 @@
</section>
</section>
<script type="text/javascript" src="js/dand.js"></script>
<noscript><p id="warning"><strong>As you can see, this frontend requires JavaScript to display correctly.</strong></p></noscript>
</body>
</html>

Loading…
Cancel
Save