= 8 months ago
parent 3c3dd7a95f
commit a994893492
  1. 8
      client/index.html
  2. 60
      client/javascript/menu.js
  3. 71
      server/communication.js
  4. 401
      server/game-logic.js
  5. 42
      server/schemas/game-schema.js

@ -36,18 +36,18 @@
<div class="box" id="code-entry" > <div class="box" id="code-entry" >
<h2>Připojit se</h2> <h2>Připojit se</h2>
<input type="text" name="code" id="code" placeholder="kód hry"> <input type="text" name="code" id="code" placeholder="kód hry">
<button>potvrdit</button> <button onclick="confirmJoinWithCode()">potvrdit</button>
<button onclick="backToMainMenu()">zpět</button> <button onclick="backToMainMenu()">zpět</button>
</div> </div>
<div class="box" id="alert"> <div class="box" id="alert">
<h2>Chyba!</h2> <h2>Chyba!</h2>
<p id="errorMessage"></p> <p id="errorMessage"></p>
<button>zpět</button> <button onclick="backToMainMenu()">zpět</button>
</div> </div>
<div class="box lobby" id="lobby"> <div class="box lobby" id="lobby">
<h2>Soukromá Hra</h2> <h2>Soukromá Hra</h2>
<p>Zvací kód: <span id="gameId">A5G3D</span></p> <p>Zvací kód: <span id="inviteCode">-</span></p>
<p>Hráč bílý: <span id="whitePlayer">Test</span></p> <p>Hráč bílý: <span id="whitePlayer">-</span></p>
<p>Hráč černý: <span id="blackPlayer">-</span></p> <p>Hráč černý: <span id="blackPlayer">-</span></p>
<button>Prohodit hráče</button> <button>Prohodit hráče</button>
<button disabled>začít hru</button> <button disabled>začít hru</button>

@ -8,6 +8,14 @@ function hide(id){
document.getElementById(id).style.display = "none"; document.getElementById(id).style.display = "none";
} }
function message(text){
alert(text);
}
function getValue(id){
return document.getElementById(id).value;
}
function getUserName(){ function getUserName(){
if (userName == "") { if (userName == "") {
userName = document.getElementById("nickname").value; userName = document.getElementById("nickname").value;
@ -45,6 +53,8 @@ function createGame(){
if(response.status == "success"){ if(response.status == "success"){
hide("loader"); hide("loader");
show("lobby"); show("lobby");
setText("whitePlayer", userName);
setText("inviteCode", response.inviteCode);
}else{ }else{
alert("fck"); alert("fck");
} }
@ -60,11 +70,61 @@ function joinWithCode(){
show("code-entry"); show("code-entry");
} }
function confirmJoinWithCode(){
inviteCode = getValue("code");
if(inviteCode == ""){
message("zadej musíš zadat kód hry");
return;
}
setText("loaderText", "Hledám Hru");
resetMenu();
show("loader");
socket.emit("joinWithCodeRequest", {userName, inviteCode}, (response) =>{
switch(response.status){
case "error":
resetMenu();
setText("errorMessage", response.message);
show("alert");
break;
case "success":
resetMenu();
show("lobby");
const whitePlayerName = (response.playerSwap) ? response.player2_name : response.player1_name;
const blackPlayerName = (response.playerSwap) ? response.player1_name : response.player2_name;
setText("whitePlayer", whitePlayerName);
setText("blackPlayer", blackPlayerName);
setText("inviteCode", response.inviteCode);
show("lobby");
}
})
}
function backToMainMenu(){ function backToMainMenu(){
resetMenu(); resetMenu();
show("main-menu"); show("main-menu");
} }
socket.on('playerJoinGame', ({player1_name, layer1_name, player2_name, playerSwap}) => {
const whitePlayerName = (playerSwap) ? player2_name : player1_name;
const blackPlayerName = (playerSwap) ? player1_name : player2_name;
setText("whitePlayer", whitePlayerName);
setText("blackPlayer", blackPlayerName);
})
show("main-menu"); show("main-menu");
hide("game"); hide("game");

@ -12,6 +12,8 @@ const io = require('socket.io')(server, {
}); });
const Game = require("./schemas/game-schema"); const Game = require("./schemas/game-schema");
const GameLogic = require('./game-logic.js');
const databaseUrl = "mongodb://dama:dama@localhost:27017/dama"; const databaseUrl = "mongodb://dama:dama@localhost:27017/dama";
const chance = new Chance(); const chance = new Chance();
@ -23,7 +25,55 @@ io.on('connection', (socket) => {
socket.on('disconnect', async () => { socket.on('disconnect', async () => {
console.log('user disconnected'); console.log('user disconnected');
await Game.deleteMany({owner}); await Game.deleteMany({owner:socket.id});
})
socket.on('leaveGame', async () => {
await Game.deleteMany({owner:socket.id});
})
socket.on('joinWithCodeRequest', async ({userName, inviteCode}, callback) => {
const game = await Game.findOne({"inviteCode":inviteCode});
if(!game){
callback({status:"error", message:"Nebyly nalezeny žádné hry"});
return;
}
if(game.player1 != null && game.player2 != null){
callback({status:"error", message:"Místnost je plná"})
}
other_player = null;
if(game.player1 == null){
game.player1 = socket.id;
game.player1_name = userName;
other_player = game.player2;
}else{
game.player2 = socket.id;
game.player2_name = userName;
other_player = game.player1;
}
await game.save();
const player1 = game.player1;
const player1_name = game.player1_name;
const player2 = game.player2_name;
const player2_name = game.player2_name;
const playerSwap = game.playerSwap;
callback({status:"success", player1:player1, player1_name:player1_name, player2:player2, player2_name:player2_name, playerSwap:playerSwap})
io.sockets.sockets.get(other_player).emit('playerJoinGame', {player1, player1_name, player2, player2_name, playerSwap});
socket.join(game.roomId);
}) })
socket.on('createGameRequest', ({userName}, callback) => { socket.on('createGameRequest', ({userName}, callback) => {
@ -31,6 +81,10 @@ io.on('connection', (socket) => {
const roomId = chance.guid(); const roomId = chance.guid();
const inviteCode = chance.string({ length: 5, casing: 'upper', alpha: true, numeric: true, symbols: false }); const inviteCode = chance.string({ length: 5, casing: 'upper', alpha: true, numeric: true, symbols: false });
const gameLogic = new GameLogic();
gameLogic.generateDefaultPositions();
const pieceList = gameLogic.pieceList;
socket.join(roomId); socket.join(roomId);
newGame = new Game({ newGame = new Game({
owner: socket.id, owner: socket.id,
@ -39,22 +93,13 @@ io.on('connection', (socket) => {
player2: null, player2: null,
player2_name: null, player2_name: null,
channel: roomId, channel: roomId,
white: 1, playerSwap: false,
black: 2,
public: false, public: false,
started: false, started: false,
inviteCode: inviteCode, inviteCode: inviteCode,
currentPlayer: null, currentPlayer: null,
missedOportunities: [String], missedOportunities: [],
pieces: [ pieces: pieceList
{
id: Integer,
x: Integer,
y: Integer,
player: String,
type: String
}
]
}); });
newGame.save(); newGame.save();

@ -1,306 +1,311 @@
class GameLogic{
constructor(pieceList = [], missedOportunities = [], currentPlayer = "white") {
this.pieceList = pieceList;
this.missedOportunities = missedOportunities;
this.currentPlayer = currentPlayer;
}
const pieceList = new Array(); isMissedOportunity(pieceRecord) {
missedOportunities = new Array(); const id = pieceRecord.id;
currentPlayer = "white"; return this.missedOportunities.includes(id);
}
function isMissedOportunity(pieceRecord) { generateDefaultPositions(){
const id = pieceRecord.id;
return missedOportunities.includes(id);
}
function generateDefaultPositions(){ var id = 0;
var id = 0; for (let i = 0; i < 8; i++) {
for (let j = 0; j < 3; j++) {
if((i+j) % 2 == 0){
const pieceRecord = {id:id, x:i, y:j, player:"white", type:"basic"};
this.pieceList.push(pieceRecord);
id++;
}
for (let i = 0; i < 8; i++) {
for (let j = 0; j < 3; j++) {
if((i+j) % 2 == 0){
pieceRecord = {id:id, x:i, y:j, player:"white", type:"basic"};
pieceList.push(pieceRecord);
id++;
} }
} }
}
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
for (let j = 5; j < 8; j++) { for (let j = 5; j < 8; j++) {
if((i+j) % 2 == 0){ if((i+j) % 2 == 0){
pieceRecord = {id:id, x:i, y:j, player:"black", type:"basic"}; const pieceRecord = {id:id, x:i, y:j, player:"black", type:"basic"};
pieceList.push(pieceRecord); this.pieceList.push(pieceRecord);
id++; id++;
} }
}
} }
} }
}
function getPieceRecord(x,y){ getPieceRecord(x,y){
if (x > 7 || x < 0 || y > 7 || y < 0) { if (x > 7 || x < 0 || y > 7 || y < 0) {
return false; return false;
}
return this.pieceList.find(pieceRecord => pieceRecord.x == x && pieceRecord.y == y);
} }
return pieceList.find(pieceRecord => pieceRecord.x == x && pieceRecord.y == y);
}
function nukePieceRecord(pieceRecord) { nukePieceRecord(pieceRecord) {
const index = pieceList.findIndex(record => record.id == pieceRecord.id); const index = this.pieceList.findIndex(record => record.id == pieceRecord.id);
pieceList.splice(index, 1); this.pieceList.splice(index, 1);
} }
function updatePieceRecord(pieceRecord) { updatePieceRecord(pieceRecord) {
const index = pieceList.findIndex(record => record.id == pieceRecord.id); const index = this.pieceList.findIndex(record => record.id == pieceRecord.id);
pieceList[index] = pieceRecord; this.pieceList[index] = pieceRecord;
} }
function updatePieceRecordPosition(pieceRecord, x, y) { updatePieceRecordPosition(pieceRecord, x, y) {
pieceRecord.x = x; pieceRecord.x = x;
pieceRecord.y = y; pieceRecord.y = y;
updatePieceRecord(pieceRecord); this.updatePieceRecord(pieceRecord);
return pieceRecord; return pieceRecord;
} }
function getCasualties(oldX, oldY, newX, newY) { getCasualties(oldX, oldY, newX, newY) {
const directionX = (newX > oldX) ? 1 : -1; const directionX = (newX > oldX) ? 1 : -1;
const directionY = (newY > oldY) ? 1 : -1; const directionY = (newY > oldY) ? 1 : -1;
const casualties = new Array(); const casualties = new Array();
for (let i = 1; i < (Math.abs(newY - oldY) + 1); i++) { for (let i = 1; i < (Math.abs(newY - oldY) + 1); i++) {
const x = oldX + (i*directionX); const x = oldX + (i*directionX);
const y = oldY + (i*directionY); const y = oldY + (i*directionY);
pieceRecord = getPieceRecord(x,y); pieceRecord = this.getPieceRecord(x,y);
if (pieceRecord) { if (pieceRecord) {
casualties.push(pieceRecord); casualties.push(pieceRecord);
} }
}
return casualties;
} }
return casualties;
}
function getLoser() { getLoser() {
if (!pieceList.find(pieceRecord => pieceRecord.player == "white")) { if (!this.pieceList.find(pieceRecord => pieceRecord.player == "white")) {
return "white"; return "white";
} }
if (!pieceList.find(pieceRecord => pieceRecord.player == "black")) { if (!this.pieceList.find(pieceRecord => pieceRecord.player == "black")) {
return "black"; return "black";
}
return null;
} }
return null;
}
function continuableInDirectionForQueen(directionX, directionY, pieceRecord) { continuableInDirectionForQueen(directionX, directionY, pieceRecord) {
const pieceX = pieceRecord.x; const pieceX = pieceRecord.x;
const pieceY = pieceRecord.y; const pieceY = pieceRecord.y;
const player = pieceRecord.player; const player = pieceRecord.player;
for (let i = 1; i < 8; i++) { for (let i = 1; i < 8; i++) {
const x = pieceX + (i*directionX); const x = pieceX + (i*directionX);
const y = pieceY + (i*directionY); const y = pieceY + (i*directionY);
if(x > 7 || x < 0 || y > 7 || y < 0 || (x+directionX) > 7 || (x+directionX) < 0 || (y+directionY) > 7 || (y+directionY) < 0 ){ if(x > 7 || x < 0 || y > 7 || y < 0 || (x+directionX) > 7 || (x+directionX) < 0 || (y+directionY) > 7 || (y+directionY) < 0 ){
return false; return false;
} }
const record = getPieceRecord(x, y); const record = this.getPieceRecord(x, y);
if (record) { if (record) {
if (record.player == player) { if (record.player == player) {
return false; return false;
} }
const firstBlockRecord = getPieceRecord(x+directionX,y+directionY); const firstBlockRecord = this.getPieceRecord(x+directionX,y+directionY);
const secondBlockRecord = getPieceRecord(x-directionX,y-directionY); const secondBlockRecord = this.getPieceRecord(x-directionX,y-directionY);
return ((!firstBlockRecord || firstBlockRecord.id == pieceRecord.id) && (!secondBlockRecord || secondBlockRecord.id == pieceRecord.id)); return ((!firstBlockRecord || firstBlockRecord.id == pieceRecord.id) && (!secondBlockRecord || secondBlockRecord.id == pieceRecord.id));
} }
}
return false;
} }
return false; continuable(pieceRecord){
} const x = pieceRecord.x;
function continuable(pieceRecord){ const y = pieceRecord.y;
const x = pieceRecord.x; const player = pieceRecord.player;
const y = pieceRecord.y; const type = pieceRecord.type;
const player = pieceRecord.player;
const type = pieceRecord.type;
if(player == "white" && ((getPieceRecord(x+1, y+1) && getPieceRecord(x+1, y+1).player != player && !getPieceRecord(x+2, y+2) && (y+2) < 8 && (x+2) < 8) || ((getPieceRecord(x-1, y+1) && getPieceRecord(x-1, y+1).player != player && !getPieceRecord(x-2, y+2) && (y+2) < 8 && (x-2) > 0)))){ if(player == "white" && ((this.getPieceRecord(x+1, y+1) && this.getPieceRecord(x+1, y+1).player != player && !this.getPieceRecord(x+2, y+2) && (y+2) < 8 && (x+2) < 8) || ((this.getPieceRecord(x-1, y+1) && this.getPieceRecord(x-1, y+1).player != player && !this.getPieceRecord(x-2, y+2) && (y+2) < 8 && (x-2) > 0)))){
return true; return true;
} }
if( player == "black" && ((getPieceRecord(x+1, y-1) && getPieceRecord(x+1, y-1).player != player && !getPieceRecord(x+2, y-2) && (y-2) > 0 && (x+2) < 8) || ((getPieceRecord(x-1, y-1) && getPieceRecord(x-1, y-1).player != player && !getPieceRecord(x-2, y-2) && (y-2) > 0 && (x-2) > 0)))){ if( player == "black" && ((this.getPieceRecord(x+1, y-1) && this.getPieceRecord(x+1, y-1).player != player && !this.getPieceRecord(x+2, y-2) && (y-2) > 0 && (x+2) < 8) || ((this.getPieceRecord(x-1, y-1) && this.getPieceRecord(x-1, y-1).player != player && !this.getPieceRecord(x-2, y-2) && (y-2) > 0 && (x-2) > 0)))){
return true; return true;
} }
if(type == "queen"){
if(type == "queen"){ return (this.continuableInDirectionForQueen(1,1,pieceRecord) || this.continuableInDirectionForQueen(-1,-1,pieceRecord) || this.continuableInDirectionForQueen(-1,1,pieceRecord) || this.continuableInDirectionForQueen(1,-1,pieceRecord));
}
return (continuableInDirectionForQueen(1,1,pieceRecord) || continuableInDirectionForQueen(-1,-1,pieceRecord) || continuableInDirectionForQueen(-1,1,pieceRecord) || continuableInDirectionForQueen(1,-1,pieceRecord)); return false;
} }
return false; getOportunities(pieceRecord){
} const player = pieceRecord.player;
const opportunities = new Array();
function getOportunities(pieceRecord){ this.pieceList.forEach(record => {
const player = pieceRecord.player; if (record.player == player && record != pieceRecord && this.continuable(record)) {
const opportunities = new Array();
pieceList.forEach(record => { opportunities.push(record.id);
if (record.player == player && record != pieceRecord && continuable(record)) { }
});
opportunities.push(record.id); return opportunities;
} }
});
return opportunities; getOportunitiesIncludingSelf(pieceRecord){
} const player = pieceRecord.player;
const opportunities = new Array();
function getOportunitiesIncludingSelf(pieceRecord){ this.pieceList.forEach(record => {
const player = pieceRecord.player; if (record.player == player && this.continuable(record)) {
const opportunities = new Array();
pieceList.forEach(record => { opportunities.push(record.id);
if (record.player == player && continuable(record)) { }
});
opportunities.push(record.id); return opportunities;
} }
});
return opportunities; isMoveValid(pieceRecord, x, y){
}
function isMoveValid(pieceRecord, x, y){
if(0 > y > 7 || 0 > x > 7){
return false;
}
if(0 > y > 7 || 0 > x > 7){ if (this.getPieceRecord(x,y)) {
return false; return false;
} }
if (getPieceRecord(x,y)) { const currentX = pieceRecord.x;
return false; const currentY = pieceRecord.y;
}
if (Math.abs(y - currentY) != Math.abs(x - currentX)) {
return false;
}
const currentX = pieceRecord.x; const player = pieceRecord.player;
const currentY = pieceRecord.y; const type = pieceRecord.type;
if (Math.abs(y - currentY) != Math.abs(x - currentX)) { //Check correct Y direction if piece is basic
return false; if (currentY > y && player == "white" && type == "basic") {
} return false;
}
const player = pieceRecord.player;
const type = pieceRecord.type;
//Check correct Y direction if piece is basic const directionY = (y > currentY) ? 1 : -1;
if (currentY > y && player == "white" && type == "basic") { const directionX = (x > currentX) ? 1 : -1;
return false;
}
space = 0;
piecesInWay = 0;
const directionY = (y > currentY) ? 1 : -1; for (let i = 1; i < (Math.abs(y-currentY)+1); i++) {
const directionX = (x > currentX) ? 1 : -1;
space = 0; const nowX = currentX + (i*directionX);
piecesInWay = 0; const nowY = currentY + (i*directionY);
for (let i = 1; i < (Math.abs(y-currentY)+1); i++) { if (inWayPieceRecord = this.getPieceRecord(nowX, nowY)) {
const nowX = currentX + (i*directionX); if(inWayPieceRecord.player == player){
const nowY = currentY + (i*directionY); return false;
}
if (inWayPieceRecord = getPieceRecord(nowX, nowY)) { space = 0;
piecesInWay++;
}else{
space++;
piecesInWay = 0;
}
if(inWayPieceRecord.player == player){ if(piecesInWay > 1){
return false; return false;
} }
space = 0; if (space > 1 && type == "basic") {
piecesInWay++; return false;
}else{ }
space++;
piecesInWay = 0;
}
if(piecesInWay > 1){
return false;
} }
if (space > 1 && type == "basic") { return true;
return false;
}
} }
swapPlayers() {
this.currentPlayer = (this.currentPlayer == "white") ? "black" : "white";
}
return true; makeMove(pieceRecord, x, y){
const player = pieceRecord.player;
} if (!isMoveValid(pieceRecord, x, y)) {
function swapPlayers() { return 0;
currentPlayer = (currentPlayer == "white") ? "black" : "white"; }
}
function makeMove(pieceRecord, x, y){ const oldX = pieceRecord.x;
const player = pieceRecord.player; const oldY = pieceRecord.y;
const casualties = this.getCasualties(oldX, oldY, x, y);
if (!isMoveValid(pieceRecord, x, y)) {
return 0;
}
const oldX = pieceRecord.x; casualties.forEach(casualty => {
const oldY = pieceRecord.y; this.nukePieceRecord(casualty);
});
const casualties = getCasualties(oldX, oldY, x, y); this.missedOportunities = new Array();
oportunities = this.getOportunitiesIncludingSelf(pieceRecord);
if(casualties.length == 0 && oportunities.length != 0) {
this.missedOportunities = oportunities;
casualties.forEach(casualty => { }
nukePieceRecord(casualty);
});
missedOportunities = new Array(); const original_type = pieceRecord.type;
oportunities = getOportunitiesIncludingSelf(pieceRecord);
if(casualties.length == 0 && oportunities.length != 0) { if ((player == "white" && y == 7) || (player == "black" && y == 0) && pieceRecord.type == "basic") {
missedOportunities = oportunities;
} pieceRecord.type = "queen";
}
const original_type = pieceRecord.type; const updatedPieceRecord = updatePieceRecordPosition(pieceRecord, x, y);
if ((player == "white" && y == 7) || (player == "black" && y == 0) && pieceRecord.type == "basic") { if (this.continuable(updatedPieceRecord) && casualties.length > 0 && pieceRecord.type == original_type) {
return 2;
}
pieceRecord.type = "queen";
return 1;
} }
const updatedPieceRecord = updatePieceRecordPosition(pieceRecord, x, y); nukePieceRecordThatMissedOportunity(pieceRecord) {
if (this.missedOportunities.includes(pieceRecord.id)) {
if (continuable(updatedPieceRecord) && casualties.length > 0 && pieceRecord.type == original_type) { this.missedOportunities = new Array();
return 2; this.nukePieceRecord(pieceRecord);
return true;
}
return false;
} }
return 1;
}
function nukePieceRecordThatMissedOportunity(pieceRecord) {
if (missedOportunities.includes(pieceRecord.id)) {
missedOportunities = new Array();
nukePieceRecord(pieceRecord);
return true;
}
return false;
} }
module.exports = GameLogic;
generateDefaultPositions();

@ -1,29 +1,27 @@
const mongoose = require("mongoose"); const mongoose = require("mongoose");
const pieceSchema = new mongoose.Schema({
id: Number,
x: Number,
y: Number,
player: String,
type: String
});
const gameSchema = new mongoose.Schema({ const gameSchema = new mongoose.Schema({
owner: String, owner: { type: String, required:true, unique:true },
player1: String, player1: { type: String, default: null, unique:true },
player1_name: String, player1_name: { type: String, default: null },
player2: String, player2: { type: String, default: null, unique:true},
player2_name: String, player2_name: { type: String, default: null },
channel: String, channel: { type: String, required:true, unique:true},
white: String, playerSwap: { type: Boolean, default: false },
black: String, public: { type: Boolean, default: false },
public: Boolean, started: { type: Boolean, default: false },
started: Boolean, inviteCode: { type: String, default: null },
inviteCode: String, currentPlayer: { type: Number, default: null },
currentPlayer: String, missedOportunities: {type: [String], default:[]},
missedOportunities: [String], pieces: [pieceSchema]
pieces: [
{
id: Number,
x: Number,
y: Number,
player: String,
type: String
}
]
}); });

Loading…
Cancel
Save