aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
authorYaroslav De La Peña Smirnov <yaros.rus_89@live.com.mx>2017-11-29 11:44:34 +0300
committerYaroslav De La Peña Smirnov <yaros.rus_89@live.com.mx>2017-11-29 11:44:34 +0300
commit67fdec20726e48ba3a934cb25bb30d47ec4a4f29 (patch)
tree37fd9f4f0b0c20103e1646fc83021e4765de3680 /client
downloadspanish-checkers-67fdec20726e48ba3a934cb25bb30d47ec4a4f29.tar.gz
spanish-checkers-67fdec20726e48ba3a934cb25bb30d47ec4a4f29.zip
Initial commit, version 0.5.3
Diffstat (limited to 'client')
-rw-r--r--client/css/style.css122
-rw-r--r--client/fonts/shashki.eotbin0 -> 1856 bytes
-rw-r--r--client/fonts/shashki.svg14
-rw-r--r--client/fonts/shashki.ttfbin0 -> 1692 bytes
-rw-r--r--client/fonts/shashki.woffbin0 -> 1132 bytes
-rw-r--r--client/index.html52
-rw-r--r--client/js/index.js540
-rw-r--r--client/no-js.html30
8 files changed, 758 insertions, 0 deletions
diff --git a/client/css/style.css b/client/css/style.css
new file mode 100644
index 0000000..610dc30
--- /dev/null
+++ b/client/css/style.css
@@ -0,0 +1,122 @@
+@font-face {
+ font-family: "shashki";
+ src:url("/static/fonts/shashki.eot");
+ src:url("/static/fonts/shashki.eot?#iefix") format("embedded-opentype"),
+ url("/static/fonts/shashki.woff") format("woff"),
+ url("/static/fonts/shashki.ttf") format("truetype"),
+ url("/static/fonts/shashki.svg#shashki") format("svg");
+ font-weight: normal;
+ font-style: normal;
+
+}
+
+.navbar, .nav-container{
+ border-radius: 0 !important;
+}
+
+.btn{
+ margin-top: 10px;
+}
+
+.alert .btn, .panel-heading .btn{
+ margin: 0;
+}
+
+.panel-heading{
+ font-weight: 700;
+}
+
+.player-name.active{
+ font-weight: 700;
+ color: rgb(0, 158, 0);
+}
+
+#board{
+ table-layout: fixed;
+ width: 416px;
+ height: 416px;
+ margin: 0 auto;
+ border: 3px solid #000;
+ background:#FFECCA;
+}
+
+#board .square{
+ width: 52px !important;
+ height: 52px !important;
+ font-size: 42px;
+ line-height: 45px;
+ text-align: center;
+ vertical-align: middle;
+ overflow: hidden;
+}
+
+#b1, #d1, #f1, #h1, #a2, #c2, #e2, #g2, #b3, #d3, #f3, #h3, #a4, #c4, #e4, #g4,
+#b5, #d5, #f5, #h5, #a6, #c6, #e6, #g6, #b7, #d7, #f7, #h7, #a8, #c8, #e8, #g8 {
+ background:#FFECCA;
+}
+
+#a1, #c1, #e1, #g1, #b2, #d2, #f2, #h2, #a3, #c3, #e3, #g3, #b4, #d4, #f4, #h4,
+#a5, #c5, #e5, #g5, #b6, #d6, #f6, #h6, #a7, #c7, #e7, #g7, #b8, #d8, #f8, #h8 {
+ background:#684B33;
+}
+
+.piece:before{
+ font-family: "shashki" !important;
+ font-style: normal !important;
+ font-weight: normal !important;
+ font-variant: normal !important;
+ text-transform: none !important;
+ speak: none;
+ font-size: 42px;
+ line-height: 45px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-align: center;
+ vertical-align: middle;
+}
+
+
+.piece.white{
+ color: #992E2E;
+}
+
+.piece.black{
+ color: #000;
+}
+
+.white.pawn:before {
+ content: "\63";
+}
+
+.white.dame:before {
+ content: "\64";
+}
+
+.black.pawn:before {
+ content: "\63";
+}
+
+.black.dame:before {
+ content: "\64";
+}
+
+@keyframes move-anim{
+ 0% {background-color: #FFECCA;}
+ 50% {background-color: #adffad;}
+ 100% {background-color: #FFECCA;}
+}
+
+.square.selected{
+ background-color: #adffad !important;
+}
+
+.square.move{
+ animation-name: move-anim;
+ animation-duration: 1s;
+ animation-iteration-count: infinite;
+}
+
+.square.last-move{
+ box-sizing: border-box;
+ border: 3px solid #00cc00;
+} \ No newline at end of file
diff --git a/client/fonts/shashki.eot b/client/fonts/shashki.eot
new file mode 100644
index 0000000..748fcac
--- /dev/null
+++ b/client/fonts/shashki.eot
Binary files differ
diff --git a/client/fonts/shashki.svg b/client/fonts/shashki.svg
new file mode 100644
index 0000000..8dd32dd
--- /dev/null
+++ b/client/fonts/shashki.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Generated by Fontastic.me</metadata>
+<defs>
+<font id="shashki" horiz-adv-x="512">
+<font-face font-family="shashki" units-per-em="512" ascent="480" descent="-32"/>
+<missing-glyph horiz-adv-x="512" />
+
+<glyph glyph-name="dameb" unicode="&#100;" d="M256 469c-118 0-213-95-213-213 0-118 95-213 213-213 118 0 213 95 213 213 0 118-95 213-213 213z m-1-137c3-15 2-64 29-64 26 1 93 42 80 33-42-29-46-96-46-96l-126 0c0 0-3 67-45 96-13 9 53-32 80-33 26 0 26 49 28 64z"/>
+<glyph glyph-name="damew" unicode="&#98;" d="M256 469c-118 0-213-95-213-213 0-118 95-213 213-213 118 0 213 95 213 213 0 118-95 213-213 213z m0-25c104 0 188-84 188-188 0-104-84-188-188-188-104 0-188 84-188 188 0 104 84 188 188 188z m-29-176c-27 1-93 42-80 33 42-29 45-96 45-96l126 0c0 0 4 67 46 96 13 9-54-32-80-33-27 0-26 49-29 64-2-15-2-64-28-64z"/>
+<glyph glyph-name="pawnb" unicode="&#99;" d="M469 256c0-118-95-213-213-213-118 0-213 95-213 213 0 118 95 213 213 213 118 0 213-95 213-213z"/>
+<glyph glyph-name="pawnw" unicode="&#97;" d="M256 469c-118 0-213-95-213-213 0-118 95-213 213-213 118 0 213 95 213 213 0 118-95 213-213 213z m0-25c104 0 188-84 188-188 0-104-84-188-188-188-104 0-188 84-188 188 0 104 84 188 188 188z"/>
+</font></defs></svg>
diff --git a/client/fonts/shashki.ttf b/client/fonts/shashki.ttf
new file mode 100644
index 0000000..4b67cba
--- /dev/null
+++ b/client/fonts/shashki.ttf
Binary files differ
diff --git a/client/fonts/shashki.woff b/client/fonts/shashki.woff
new file mode 100644
index 0000000..5c19112
--- /dev/null
+++ b/client/fonts/shashki.woff
Binary files differ
diff --git a/client/index.html b/client/index.html
new file mode 100644
index 0000000..5c5b954
--- /dev/null
+++ b/client/index.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=480px, initial-scale=1">
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+ <link rel="stylesheet" href="/static/css/style.css">
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
+ <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+ <script src="/static/js/index.js"></script>
+ <title>Spanish Checkers by Yaroslav de la Peña Smirnov</title>
+ </head>
+ <body>
+ <nav class="navbar navbar-inverse">
+ <div class="container nav-container">
+ <div class="navbar-header">
+ <p class="navbar-brand">Spanish Checkers v0.5.3</span></p>
+ </div>
+ </div>
+ </nav>
+ <div id="start-container" class="container">
+ <div id="#message-box"></div>
+ <div class="row">
+ <div class="col-sm-6">
+ <h2>Start a new game</h2>
+ <form id="newgame" method="post" action="/start">
+ <label for="playername">Name</label>
+ <input id="playername" class="form-control" name="playername" type="text" placeholder="Player 1" required>
+ <button class="btn btn-primary" type="submit" value="Submit">New game</button>
+ </form>
+ </div>
+ <div class="col-sm-6">
+ <h2>Join a game</h2>
+ <form id="joingame" method="post" action="/join">
+ <label for="gameid">Game ID</label>
+ <input id="gameid" class="form-control" name="gameid" tpye="text" required>
+ <label for="player2name">Name</label>
+ <input id="player2name" class="form-control" name="player2name" type="text" placeholder="Player 2" required>
+ <button class="btn btn-primary" type="submit">Join game</button>
+ </form>
+ </div>
+ </div>
+ </div>
+ <br>
+ <hr>
+ <div class="text-center">
+ <p>Yaroslav de la Peña Smirnov - 2017</p>
+ <p>Сделано для предмета "Прикладная Информатика", Лабораторная Работа №4, Вариант 5. Университет ИТМО, группа K3200.</p>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/client/js/index.js b/client/js/index.js
new file mode 100644
index 0000000..8e96fd6
--- /dev/null
+++ b/client/js/index.js
@@ -0,0 +1,540 @@
+/*
+Created by Yaroslav de la Peña Smirnov
+This software is provided under the 3-Clause BSD License
+
+Copyright 2017 Yaroslav de la Peña Smirnov
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*Game logic*/
+var playerName = "";
+var opponentName = "";
+var playerColor = "white";
+var isTurn = false;
+var ongoingGame = false;
+var defaultSquareIDs = [
+ 'a8', 'b8', 'c8', 'd8', 'e8', 'f8', 'g8', 'h8',
+ 'a7', 'b7', 'c7', 'd7', 'e7', 'f7', 'g7', 'h7',
+ 'a6', 'b6', 'c6', 'd6', 'e6', 'f6', 'g6', 'h6',
+ 'a5', 'b5', 'c5', 'd5', 'e5', 'f5', 'g5', 'h5',
+ 'a4', 'b4', 'c4', 'd4', 'e4', 'f4', 'g4', 'h4',
+ 'a3', 'b3', 'c3', 'd3', 'e3', 'f3', 'g3', 'h3',
+ 'a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2',
+ 'a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1'
+];
+var squareIDs;
+var upperPieces = "piece black pawn";
+var lowerPieces = "piece white pawn";
+function initBoard(player){
+ if (player == 1){
+ squareIDs = defaultSquareIDs;
+ playerColor = "white";
+ upperPieces = "piece black pawn";
+ lowerPieces = "piece white pawn";
+ }
+ else {
+ playerColor = "black";
+ squareIDs = [];
+ for (i = defaultSquareIDs.length - 1; i >= 0; i--){
+ squareIDs.push(defaultSquareIDs[i]);
+ }
+ upperPieces = "piece white pawn";
+ lowerPieces = "piece black pawn";
+ }
+ $("#board-container").html("<table id='board'></table>")
+ var i = 0, j = 0, k = 0;
+ var bc = "<tbody>";
+ for (i = 0; i < 8; i++){
+ bc += "<tr>";
+ for(j = 0; j < 8; j++){
+ bc += "<td id='"+squareIDs[k]+"' class='square ";
+ if(((i+1) % 2 == 0 && (j+1) % 2 == 0) || ((i+1) % 2 != 0 && (j+1) % 2 != 0)){
+ if(i < 3){
+ bc += upperPieces;
+ }
+ else if(i > 4){
+ bc += lowerPieces;
+ }
+ }
+ bc += "'></td>\n";
+ k++;
+ }
+ bc += "</tr>\n";
+ }
+ bc += "</tbody>\n";
+ $("#board").html(bc);
+ ongoingGame = true;
+}
+
+function getMoves(event){
+ if (!isTurn){ return; }
+ var piece = event.target;
+ $(".square").removeClass("selected kill");
+ $(".square").removeClass("move");
+ $(event.target).addClass("selected");
+ var pieceColor = "white";
+ var pieceType = "pawn";
+ if ($(piece).hasClass("black")){ pieceColor = "black"; }
+ if ($(piece).hasClass("dame")){ pieceType = "dame"; }
+ var pieceID = $(piece).attr("id");
+ var pX = pieceID.charCodeAt(0)-96;
+ var pY = parseInt(pieceID.charAt(1));
+ if(pieceType == "dame"){
+ var opponent = "black";
+ if ($(piece).hasClass("black")){ opponent = "white"; }
+ var mY = pY+1;
+ var mRX = pX+1;
+ var mLX = pX-1;
+ while(mY < 9 && (mRX < 9 || mLX > 0)){
+ if(mRX < 9){
+ var moveRID = "#"+String.fromCharCode(mRX+96)+mY;
+ if(!$(moveRID).hasClass("piece")){
+ $(moveRID).addClass("move");
+ mRX++;
+ }
+ else{
+ if(mY<8 && mRX<8 && $(moveRID).hasClass(opponent)){
+ var victimID = moveRID;
+ var nmY = mY+1;
+ mRX++;
+ moveRID = "#"+String.fromCharCode(mRX+96)+nmY;
+ if(!$(moveRID).hasClass("piece") && mRX < 9){
+ $(moveRID).addClass("move kill");
+ $(moveRID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mRX, nmY);
+ }
+ }
+ mRX = 9;
+ }
+ }
+ if(mLX > 0){
+ var moveLID = "#"+String.fromCharCode(mLX+96)+mY;
+ if(!$(moveLID).hasClass("piece") && mLX > 0){
+ $(moveLID).addClass("move");
+ mLX--;
+ }
+ else{
+ if(mY<8 && mLX>1 && $(moveLID).hasClass(opponent)){
+ var victimID = moveLID;
+ var nmY = mY+1;
+ mLX--;
+ moveLID = "#"+String.fromCharCode(mLX+96)+nmY;
+ if(!$(moveLID).hasClass("piece")){
+ $(moveLID).addClass("move kill");
+ $(moveLID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mLX, nmY);
+ }
+ }
+ mLX = 0;
+ }
+ }
+ mY++;
+ }
+ mY = pY-1;
+ mRX = pX+1;
+ mLX = pX-1;
+ while(mY > 0 && (mRX < 9 || mLX > 0)){
+ if(mRX < 9){
+ var moveRID = "#"+String.fromCharCode(mRX+96)+mY;
+ if(!$(moveRID).hasClass("piece")){
+ $(moveRID).addClass("move");
+ mRX++;
+ }
+ else{
+ if(mY>1 && mRX<8 && $(moveRID).hasClass(opponent)){
+ var victimID = moveRID;
+ var nmY = mY-1;
+ mRX++;
+ moveRID = "#"+String.fromCharCode(mRX+96)+nmY;
+ if(!$(moveRID).hasClass("piece")){
+ $(moveRID).addClass("move kill");
+ $(moveRID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mRX, nmY);
+ }
+ }
+ mRX = 9;
+ }
+ }
+ if(mLX > 0){
+ var moveLID = "#"+String.fromCharCode(mLX+96)+mY;
+ if(!$(moveLID).hasClass("piece")){
+ $(moveLID).addClass("move");
+ mLX--;
+ }
+ else{
+ if(mY>1 && mLX>1 && $(moveLID).hasClass(opponent)){
+ var victimID = moveLID;
+ var nmY = mY-1;
+ mLX--;
+ moveLID = "#"+String.fromCharCode(mLX+96)+nmY;
+ if(!$(moveLID).hasClass("piece")){
+ $(moveLID).addClass("move kill");
+ $(moveLID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mLX, nmY);
+ }
+ }
+ mLX = 0;
+ }
+ }
+ mY--;
+ }
+ }
+ else if (pieceColor == "white"){
+ if(pY < 8){
+ if(pX < 8){
+ var mY = pY+1;
+ var mX = pX+1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move");
+ }
+ else if(pX < 7 && pY < 7 && $(moveID).hasClass("black")){
+ var victimID = moveID;
+ mX++;
+ mY++;
+ moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move kill");
+ $(moveID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mX, mY);
+ }
+ }
+ }
+ if(pX > 1){
+ var mY = pY+1;
+ var mX = pX-1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move");
+ }
+ else if(pX > 2 && pY < 7 && $(moveID).hasClass("black")){
+ var victimID = moveID;
+ mX--;
+ mY++;
+ moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move kill");
+ $(moveID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mX, mY);
+ }
+ }
+ }
+ }
+ }
+ else{
+ if(pY > 1){
+ if(pX < 8){
+ var mY = pY-1;
+ var mX = pX+1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move");
+ }
+ else if(pX < 7 && pY > 2 && $(moveID).hasClass("white")){
+ var victimID = moveID;
+ mX++;
+ mY--;
+ moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move kill");
+ $(moveID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mX, mY);
+ }
+ }
+ }
+ if(pX > 1){
+ var mY = pY-1;
+ var mX = pX-1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move");
+ }
+ else if(pX > 2 && pY > 2 && $(moveID).hasClass("white")){
+ var victimID = moveID;
+ mX--;
+ mY--;
+ moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece")){
+ $(moveID).addClass("move kill");
+ $(moveID).attr("victim", victimID);
+ findMoreMoves(pieceColor, pieceType, victimID, mX, mY);
+ }
+ }
+ }
+ }
+ }
+}
+
+function findMoreMoves(pieceColor, pieceType, victimIDs, pX, pY){
+ if(pieceType == "dame"){
+ console.log("findmore dame start");
+ }
+ if(pY < 7 && (pieceColor == "white" || pieceType == "dame")){
+ var vY = pY+1;
+ if (pX < 7){
+ console.log("up right start");
+ var vX = pX+1;
+ var victimID = "#"+String.fromCharCode(vX+96)+vY;
+ if($(victimID).hasClass("piece") && ((pieceColor == "white" && $(victimID).hasClass("black")) || (pieceColor == "black" && $(victimID).hasClass("white")))){
+ console.log("up right victim");
+ var mY = vY+1;
+ var mX = vX+1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece") && victimIDs.indexOf(victimID) < 0){
+ console.log("up right move");
+ $(moveID).addClass("move kill");
+ var nvictimIDs = victimIDs+","+victimID;
+ $(moveID).attr("victim", nvictimIDs);
+ findMoreMoves(pieceColor, pieceType, nvictimIDs, mX, mY);
+ }
+ }
+ }
+ if (pX > 2){
+ console.log("up left start");
+ var vX = pX-1;
+ var victimID = "#"+String.fromCharCode(vX+96)+vY;
+ if($(victimID).hasClass("piece") && ((pieceColor == "white" && $(victimID).hasClass("black")) || (pieceColor == "black" && $(victimID).hasClass("white")))){
+ console.log("up left victim");
+ var mY = vY+1;
+ var mX = vX-1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece") && victimIDs.indexOf(victimID) < 0){
+ console.log("up left move");
+ $(moveID).addClass("move kill");
+ var nvictimIDs = victimIDs+","+victimID;
+ $(moveID).attr("victim", nvictimIDs);
+ findMoreMoves(pieceColor, pieceType, nvictimIDs, mX, mY);
+ }
+ }
+ }
+ }
+ if(pY > 2 && (pieceColor == "black" || pieceType == "dame")){
+ var vY = pY-1;
+ if (pX < 7){
+ console.log("down right start");
+ var vX = pX+1;
+ var victimID = "#"+String.fromCharCode(vX+96)+vY;
+ if($(victimID).hasClass("piece") && ((pieceColor == "white" && $(victimID).hasClass("black")) || (pieceColor == "black" && $(victimID).hasClass("white")))){
+ console.log("down right victim");
+ var mY = vY-1;
+ var mX = vX+1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece") && victimIDs.indexOf(victimID) < 0){
+ console.log("down right move");
+ $(moveID).addClass("move kill");
+ var nvictimIDs = victimIDs+","+victimID;
+ $(moveID).attr("victim", nvictimIDs);
+ findMoreMoves(pieceColor, pieceType, nvictimIDs, mX, mY);
+ }
+ }
+ }
+ if (pX > 2){
+ console.log("down left start");
+ var vX = pX-1;
+ var victimID = "#"+String.fromCharCode(vX+96)+vY;
+ if($(victimID).hasClass("piece") && ((pieceColor == "white" && $(victimID).hasClass("black")) || (pieceColor == "black" && $(victimID).hasClass("white")))){
+ console.log("down left victim");
+ var mY = vY-1;
+ var mX = vX-1;
+ var moveID = "#"+String.fromCharCode(mX+96)+mY;
+ if(!$(moveID).hasClass("piece") && victimIDs.indexOf(victimID) < 0){
+ console.log("down left move");
+ $(moveID).addClass("move kill");
+ var nvictimIDs = victimIDs+","+victimID;
+ $(moveID).attr("victim", nvictimIDs);
+ findMoreMoves(pieceColor, pieceType, nvictimIDs, mX, mY);
+ }
+ }
+ }
+ }
+}
+
+function movePiece(event){
+ if (!isTurn){ return; }
+ var mSquare = event.target;
+ var pieceColor = "white";
+ var pieceType = "pawn";
+ if($(".selected").first().hasClass("black")){ pieceColor = "black"; }
+ if($(".selected").first().hasClass("dame")){ pieceType = "dame"; }
+ if ((pieceColor == "white" && $(mSquare).attr("id").charAt(1) == "8") || (pieceColor == "black" && $(mSquare).attr("id").charAt(1) == "1")){
+ pieceType = "dame";
+ }
+ var origin = $(".selected").first().attr("id");
+ var target = $(mSquare).attr("id");
+ $(".selected").removeClass("piece black white pawn dame");
+ $(mSquare).addClass("piece "+pieceColor+" "+pieceType);
+ $(".square").removeClass("selected move");
+ socket.emit("piece moved", origin, target);
+ if($(mSquare).hasClass("kill")){
+ var victims = $(mSquare).attr("victim").split(",");
+ victims.forEach(function(victim){
+ var victimColor = "black";
+ if($(victim).hasClass("white")){ victimColor = "white"; }
+ $(victim).removeClass("piece white black pawn dame");
+ var pieceRemoved = victim.slice(1);
+ $(mSquare).attr("victim", "");
+ socket.emit("piece removed", pieceRemoved, victimColor);
+ });
+ }
+ $(".square").removeClass("kill last-move");
+ $("#"+origin).addClass("last-move");
+ $("#"+target).addClass("last-move");
+}
+
+$(document).on("click", ".square.piece", function(event){
+ if(isTurn && $(event.target).hasClass(playerColor)){
+ getMoves(event);
+ }
+});
+
+$(document).on("click", ".square.move", function(event){
+ if(isTurn){
+ movePiece(event);
+ }
+});
+
+$(document).on("click", "#btn-truce", function(event){
+ socket.emit("request truce");
+});
+
+$(document).on("click", "#btn-truce-accept", function(event){
+ socket.emit("accept truce");
+ $("#message-box").html("<div class='alert alert-info'>You have accepted "+opponentName+"'s truce offer. The game is a tie. <a class='btn btn-info btn-sm' href='/'>New game</a>");
+ ongoingGame = false;
+ isTurn = false;
+});
+
+$(document).on("click", "#btn-truce-decline", function(event){
+ socket.emit("reject truce");
+ $("#message-box").html("<div class='alert alert-info alert-dismissable'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a>You have declined "+opponentName+"'s truce offer.");
+});
+
+window.onbeforeunload = function(){
+ if (ongoingGame){
+ return "By closing this page you will be disconnected from the match and lose. Are you sure you want to leave?";
+ }
+ return undefined;
+}
+
+/*Socket handling*/
+var socket;
+function initializeEvents(){
+ socket.on("invalid game", function(){
+ $("#start-container").html("<div class='alert alert-danger'>Invalid game ID <a class='btn btn-danger btn-sm' href='/'>Go back</a></div>");
+ socket.disconnect();
+ socket = null;
+ });
+ socket.on("full game", function(){
+ $("#start-container").html("<div class='alert alert-danger'>U wot m8? U trying to join a full game m8. Try joining a new game or start a new one yourself. <a class='btn btn-danger btn-sm' href='/'>Go back</a></div>");
+ socket.disconnect();
+ socket = null;
+ });
+ socket.on("game started", function(gameID){
+ $("#start-container").html("<div class='panel panel-default'><div class='panel-heading'>Game ID: "+gameID.toString()+" <a id='btn-truce' class='btn btn-default' style='display:none'>Request tie</a></div></div><div id='message-box'></div><hr><div class='text-center'><h4 id='opponent-name' class='player-name'>Waiting for player...</h4><div id='board-container'></div><h4 id='local-name' class='player-name'>"+playerName+"</h4></div>");
+ initBoard(1);
+ });
+ socket.on("game joined", function(gameID, opponent){
+ $("#start-container").html("<div class='panel panel-default'><div class='panel-heading'>Game ID: "+gameID.toString()+" <a id='btn-truce' class='btn btn-default'>Request tie</a></div></div><div id='message-box'></div><hr><div class='text-center'><h4 id='opponent-name' class='player-name active'>"+opponent+"</h4><div id='board-container'></div><h4 id='local-name' class='player-name'>"+playerName+"</h4></div>");
+ initBoard(2);
+ opponentName = opponent;
+ $("#btn-truce").css("display", "inline-block");
+ });
+ socket.on("player joined", function(player){
+ $("#opponent-name").html(player);
+ isTurn = true;
+ $("#local-name").addClass("active");
+ opponentName = player;
+ $("#btn-truce").css("display", "inline-block");
+ });
+ socket.on("turn start", function(){
+ isTurn = true;
+ $("#local-name").addClass("active");
+ $("#opponent-name").removeClass("active");
+ });
+ socket.on("turn end", function(){
+ isTurn = false;
+ $("#local-name").removeClass("active");
+ $("#opponent-name").addClass("active");
+ });
+ socket.on("move piece", function(origin, target){
+ var pieceColor = "black";
+ if(playerColor == "black") { pieceColor = "white"; }
+ var pieceType = "pawn";
+ if($("#"+origin).hasClass("dame")){ pieceType = "dame"; }
+ $(".square").removeClass("last-move");
+ $("#"+origin).removeClass("piece white black pawn dame");
+ $("#"+origin).addClass("last-move");
+ if((pieceColor == "black" && target.charAt(1) == "1") || (pieceColor == "white" && target.charAt(1) == "8")){ pieceType = "dame"; }
+ $("#"+target).addClass("piece "+pieceColor+" "+pieceType+" last-move");
+ });
+ socket.on("remove piece", function(pieceRemoved){
+ $("#"+pieceRemoved).removeClass("piece white black pawn dame");
+ });
+ socket.on("truce requested", function(){
+ $("#message-box").html("<div class='alert alert-info'>"+opponentName+" wants to declare the game a tie. Do you accept their offer? <a id='btn-truce-accept' class='btn btn-info btn-sm'>Accept</a> <a id='btn-truce-decline' class='btn btn-info btn-sm'>Decline</a></div>");
+ });
+ socket.on("truce accepted", function(){
+ $("#message-box").html("<div class='alert alert-info'>"+opponentName+" has accepted your truce offer. The game is a tie. <a class='btn btn-info btn-sm' href='/'>New game</a>");
+ ongoingGame = false;
+ isTurn = false;
+ });
+ socket.on("truce rejected", function(){
+ $("#message-box").html("<div class='alert alert-warning alert-dismissable'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a>"+opponentName+" has declined your truce offer.");
+ });
+ socket.on("you won", function(){
+ $("#message-box").html("<div class='alert alert-success'>Way to go! You've won! <a class='btn btn-success btn-sm' href='/'>New game</a>");
+ ongoingGame = false;
+ isTurn = false;
+ });
+ socket.on("you lost", function(){
+ $("#message-box").html("<div class='alert alert-danger'>You've lost, victory goes to "+opponentName+". Better luck next time! <a class='btn btn-danger btn-sm' href='/'>New game</a>");
+ ongoingGame = false;
+ isTurn = false;
+ });
+ socket.on("game message", function(data){
+ $("#message-box").html("<p>"+data+"<p>");
+ });
+ socket.on("game disconnect", function(player){
+ if(ongoingGame)
+ $("#message-box").html("<div class='alert alert-warning'>Player <strong>"+player+"</strong> disconnected <a class='btn btn-warning btn-sm' href='/'>New game</a></div>");
+ ongoingGame = false;
+ isTurn = false;
+ });
+}
+$(function(){
+ $("#newgame").submit(function(event){
+ socket = io();
+ var form_data = $(this).serializeArray().reduce(function(obj, item) {
+ obj[item.name] = item.value;
+ return obj;
+ }, {});
+ playerName = form_data.playername;
+ initializeEvents();
+ socket.emit("start game", form_data);
+ $("#start-container").addClass("text-center");
+ $("#start-container").html("<h2>Starting game...</h2><div id='message-box'></div>");
+ return false;
+ });
+ $("#joingame").submit(function(event){
+ socket = io();
+ var form_data = $(this).serializeArray().reduce(function(obj, item) {
+ obj[item.name] = item.value;
+ return obj;
+ }, {});
+ playerName = form_data.player2name;
+ initializeEvents();
+ socket.emit("join game", form_data);
+ $("#start-container").addClass("text-center");
+ $("#start-container").html("<h2>Joining game...</h2><div id='message-box'></div>");
+ return false;
+ });
+}) \ No newline at end of file
diff --git a/client/no-js.html b/client/no-js.html
new file mode 100644
index 0000000..608c5a5
--- /dev/null
+++ b/client/no-js.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+ <link rel="stylesheet" href="/static/css/style.css">
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
+ <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+ <script src="/static/js/index.js"></script>
+ <title>Spanish Checkers by Yaroslav de la Peña Smirnov</title>
+ </head>
+ <body>
+ <<nav class="navbar navbar-inverse">
+ <div class="container nav-container">
+ <div class="navbar-header">
+ <p class="navbar-brand">Spanish Checkers v0.5.1</span></p>
+ </div>
+ </div>
+ </nav>
+ <div class="container text-center">
+ <h1>Give me the javascript, and I shall give you the game.</h1>
+ </div>
+ <div class="text-center">
+ <p>Yaroslav de la Peña Smirnov - 2017</p>
+ <p>Сделано для предмета "Прикладная Информатика", Лабораторная Работа №4, Вариант 5. Университет ИТМО, группа K3200.</p>
+ </div>>
+ </body>
+</html> \ No newline at end of file