added moving pawn when player miss a turn

This commit is contained in:
Wenszel 2023-11-11 18:48:35 +01:00
parent 6114d370e9
commit d0b12137b5
7 changed files with 162 additions and 105 deletions

View File

@ -1,109 +1,88 @@
const RoomModel = require('../schemas/room'); const Room = require('../schemas/room');
const { getPawnPositionAfterMove } = require('../utils/functions'); const { getPawnPositionAfterMove } = require('../utils/functions');
module.exports = (io, socket) => { module.exports = (io, socket) => {
const req = socket.request; const req = socket.request;
const getRoom = async () => { const handleMovePawn = async pawnId => {
return await RoomModel.findOne({ _id: req.session.roomId }).exec(); const room = await getRoom();
const pawn = room.getPawn(pawnId);
if (isMoveValid(pawn, room)) {
const newPositionOfMovedPawn = getPawnPositionAfterMove(room.rolledNumber, pawn);
room.changePositionOfPawn(pawn, newPositionOfMovedPawn);
room.beatPawns(newPositionOfMovedPawn, req.session.color);
handleChangeOfPlayer(room);
}
}; };
const updateRoom = async room => { const handleRollDice = async () => {
return await RoomModel.findOneAndUpdate({ _id: req.session.roomId }, room).exec(); const rolledNumber = rollDice();
const room = await updateRoom({ rolledNumber: rolledNumber });
if (!canPlayerMove(room, rolledNumber)) {
handleChangeOfPlayer(room);
}
}; };
const sendToPlayersRolledNumber = rolledNumber => { const rollDice = () => {
io.to(req.session.roomId.toString()).emit('game:roll', rolledNumber);
};
const sendToPlayersData = room => {
io.to(req.session.roomId.toString()).emit('room:data', JSON.stringify(room));
};
const rollDice = async () => {
const rolledNumber = Math.ceil(Math.random() * 6); const rolledNumber = Math.ceil(Math.random() * 6);
sendToPlayersRolledNumber(rolledNumber); sendToPlayersRolledNumber(rolledNumber);
let room = await updateRoom({ rolledNumber: rolledNumber }); return rolledNumber;
if (!canPlayerMove(room, rolledNumber)) {
room = changeMovingPlayer(room);
await updateRoom(room);
sendToPlayersData(room);
}
}; };
const canPlayerMove = (room, rolledNumber) => { const canPlayerMove = (room, rolledNumber) => {
let isMovePossible = false; const playerPawns = room.getPlayerPawns(req.session.color);
const playerPawns = room.pawns.filter(pawn => pawn.color === req.session.color);
for (const pawn of playerPawns) { for (const pawn of playerPawns) {
// (if player's pawn is in base) if the rolled number is 1,6 if (pawn.canMove(rolledNumber)) return true;
if (pawn.position === pawn.basePos && (rolledNumber === 6 || rolledNumber === 1)) {
isMovePossible = true;
} }
// (if player's pawn is near finish line) if the move does not go beyond the win line return false;
if (pawn.position !== getPawnPositionAfterMove(rolledNumber, pawn) && pawn.position !== pawn.basePos) {
isMovePossible = true;
}
}
return isMovePossible;
}; };
const isMoveValid = async (pawn, room) => { const isMoveValid = (pawn, room) => {
if (req.session.color !== pawn.color) { if (req.session.color !== pawn.color) {
return false; return false;
} }
currentlyMovingPlayer = room.players.filter(player => player.nowMoving === true); if (req.session.playerId !== room.getCurrentlyMovingPlayer()._id.toString()) {
if (req.session.playerId !== currentlyMovingPlayer._id) {
return false; return false;
} }
return true; return true;
}; };
const skipPlayerTurn = async () => { const handleChangeOfPlayer = async room => {
let room = await getRoom(); room.changeMovingPlayer();
room = changeMovingPlayer(room); room.timeoutID = setTimeout(makeRandomMove, 15000, room);
await updateRoom(room); await updateRoom(room);
sendToPlayersData(room);
}; };
const movePawn = async ({ pawnId }) => { const makeRandomMove = async room => {
let room = await getRoom(); if (room.rolledNumber === null) room.rolledNumber = rollDice();
const indexOfPawn = room.pawns.findIndex(pawn => pawn._id == pawnId); const pawnsThatCanMove = room.getPawnsThatCanMove()
if (!isMoveValid(room.pawns[indexOfPawn], room)) return; if (pawnsThatCanMove.length > 0) {
const newPositionOfMovedPawn = getPawnPositionAfterMove(room.rolledNumber, room.pawns[indexOfPawn]); const randomPawn = pawnsThatCanMove[Math.floor(Math.random() * pawnsThatCanMove.length)];
room.pawns[indexOfPawn].position = newPositionOfMovedPawn; room.movePawn(randomPawn);
room = beatPawns(newPositionOfMovedPawn, room);
room = changeMovingPlayer(room);
await updateRoom(room);
sendToPlayersData(room);
};
const beatPawns = (position, room) => {
const pawnsInTheSamePosition = room.pawns.filter(pawn => pawn.position === position);
pawnsInTheSamePosition.forEach(pawn => {
if (pawn.color !== req.session.color) {
const index = room.pawns.findIndex(i => i._id === pawn._id);
room.pawns[index].position = room.pawns[index].basePos;
} }
await handleChangeOfPlayer(room);
};
Room.watch().on('change', async () => {
sendToPlayersData(await getRoom());
}); });
return room;
const getRoom = async () => {
return await Room.findOne({ _id: req.session.roomId }).exec();
}; };
const changeMovingPlayer = room => { const updateRoom = async room => {
if (room.timeoutID) clearTimeout(room.timeoutID); return await Room.findOneAndUpdate({ _id: req.session.roomId }, room).exec();
const playerIndex = room.players.findIndex(player => player.nowMoving === true);
room.players[playerIndex].nowMoving = false;
if (playerIndex + 1 === room.players.length) {
room.players[0].nowMoving = true;
} else {
room.players[playerIndex + 1].nowMoving = true;
}
room.nextMoveTime = Date.now() + 15000;
room.rolledNumber = null;
room.timeoutID = setTimeout(skipPlayerTurn, 15000);
return room;
}; };
socket.on('game:roll', rollDice); const sendToPlayersRolledNumber = rolledNumber => {
socket.on('game:move', movePawn); io.to(req.session.roomId).emit('game:roll', rolledNumber);
socket.on('game:skip', skipPlayerTurn); };
const sendToPlayersData = room => {
io.to(req.session.roomId).emit('room:data', JSON.stringify(room));
};
socket.on('game:roll', handleRollDice);
socket.on('game:move', handleMovePawn);
}; };

View File

@ -70,8 +70,8 @@ module.exports = (io, socket) => {
req.session.reload(err => { req.session.reload(err => {
if (err) return socket.disconnect(); if (err) return socket.disconnect();
// Saving session data // Saving session data
req.session.roomId = room._id; req.session.roomId = room._id.toString();
req.session.playerId = room.players[0]._id; req.session.playerId = room.players[0]._id.toString();
req.session.color = room.players[0].color; req.session.color = room.players[0].color;
req.session.save(); req.session.save();
// Sending data to the user, after which player will be redirected to the game // Sending data to the user, after which player will be redirected to the game
@ -108,8 +108,8 @@ module.exports = (io, socket) => {
req.session.reload(err => { req.session.reload(err => {
if (err) return socket.disconnect(); if (err) return socket.disconnect();
// Saving session data // Saving session data
req.session.roomId = room._id; req.session.roomId = room._id.toString();
req.session.playerId = updatedRoom.players[updatedRoom.players.length - 1]._id; req.session.playerId = updatedRoom.players[updatedRoom.players.length - 1]._id.toString();
req.session.color = colors[updatedRoom.players.length - 1]; req.session.color = colors[updatedRoom.players.length - 1];
req.session.save(); req.session.save();
socket.join(room._id.toString()); socket.join(room._id.toString());

View File

@ -28,7 +28,7 @@ module.exports = (io, socket) => {
} }
room.nextMoveTime = Date.now() + 15000; room.nextMoveTime = Date.now() + 15000;
RoomModel.findOneAndUpdate({ _id: req.session.roomId }, room, function (err, updatedRoom) { RoomModel.findOneAndUpdate({ _id: req.session.roomId }, room, function (err, updatedRoom) {
io.to(req.session.roomId.toString()).emit('room:data', JSON.stringify(updatedRoom)); io.to(req.session.roomId).emit('room:data', JSON.stringify(updatedRoom));
}); });
}); });
} }

24
backend/schemas/pawn.js Normal file
View File

@ -0,0 +1,24 @@
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const { getPawnPositionAfterMove } = require('../utils/functions');
const PawnSchema = new Schema({
color: String,
basePos: Number,
position: Number,
});
PawnSchema.methods.canMove = function (rolledNumber) {
if (this.position === this.basePos && (rolledNumber === 6 || rolledNumber === 1)) {
return true;
}
// (if player's pawn is near finish line) if the move does not go beyond the win line
if (this.position !== getPawnPositionAfterMove(rolledNumber, this) && this.position !== this.basePos) {
return true;
}
return false;
};
module.exports = PawnSchema;

12
backend/schemas/player.js Normal file
View File

@ -0,0 +1,12 @@
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PlayerSchema = new Schema({
name: String,
color: String,
ready: { type: Boolean, default: false },
nowMoving: { type: Boolean, default: false },
});
module.exports = PlayerSchema;

View File

@ -1,31 +1,76 @@
var mongoose = require('mongoose'); const mongoose = require('mongoose');
const { getPawnPositionAfterMove } = require('../utils/functions');
const Schema = mongoose.Schema;
const PawnSchema = require('./pawn');
const PlayerSchema = require('./player');
var Schema = mongoose.Schema; const RoomSchema = new Schema({
var RoomSchema = new Schema({
createDate: Date, createDate: Date,
started: { type: Boolean, default: false }, started: { type: Boolean, default: false },
full: { type: Boolean, default: false }, full: { type: Boolean, default: false },
nextMoveTime: Number, nextMoveTime: Number,
timeoutID: Number, timeoutID: Number,
rolledNumber: Number, rolledNumber: Number,
players: [ players: [PlayerSchema],
{ pawns: [PawnSchema],
name: String,
color: String,
ready: { type: Boolean, default: false },
nowMoving: { type: Boolean, default: false },
},
],
pawns: [
{
color: String,
basePos: Number,
position: Number,
},
],
}); });
var RoomModel = mongoose.model('RoomModel', RoomSchema); RoomSchema.methods.beatPawns = function (position, attackingPawnColor) {
const pawnsOnPosition = this.pawns.filter(pawn => pawn.position === position);
pawnsOnPosition.forEach(pawn => {
if (pawn.color !== attackingPawnColor) {
const index = this.getPawnIndex(pawn._id);
this.pawns[index].position = this.pawns[index].basePos;
}
});
};
RoomSchema.methods.changeMovingPlayer = function () {
const playerIndex = this.players.findIndex(player => player.nowMoving === true);
this.players[playerIndex].nowMoving = false;
if (playerIndex + 1 === this.players.length) {
this.players[0].nowMoving = true;
} else {
this.players[playerIndex + 1].nowMoving = true;
}
this.nextMoveTime = Date.now() + 15000;
this.rolledNumber = null;
if (this.timeoutID) clearTimeout(this.timeoutID);
};
RoomSchema.methods.movePawn = function (pawn) {
const newPositionOfMovedPawn = getPawnPositionAfterMove(this.rolledNumber, pawn);
this.changePositionOfPawn(pawn, newPositionOfMovedPawn);
this.beatPawns(newPositionOfMovedPawn, pawn.color);
};
RoomSchema.methods.getPawnsThatCanMove = function () {
const movingPlayer = this.getCurrentlyMovingPlayer();
const playerPawns = this.getPlayerPawns(movingPlayer.color);
return playerPawns.filter(pawn => pawn.canMove(this.rolledNumber));
}
RoomSchema.methods.changePositionOfPawn = function (pawn, newPosition) {
const pawnIndex = this.getPawnIndex(pawn._id);
this.pawns[pawnIndex].position = newPosition;
};
RoomSchema.methods.getPawnIndex = function (pawnId) {
return this.pawns.findIndex(pawn => pawn._id.toString() === pawnId.toString());
};
RoomSchema.methods.getPawn = function (pawnId) {
return this.pawns.find(pawn => pawn._id.toString() === pawnId.toString());
};
RoomSchema.methods.getPlayerPawns = function (color) {
return this.pawns.filter(pawn => pawn.color === color);
};
RoomSchema.methods.getCurrentlyMovingPlayer = function () {
return this.players.find(player => player.nowMoving === true);
};
const RoomModel = mongoose.model('Room', RoomSchema);
module.exports = RoomModel; module.exports = RoomModel;

View File

@ -78,7 +78,7 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
y = event.clientY - rect.top; y = event.clientY - rect.top;
for (const pawn of pawns) { for (const pawn of pawns) {
if (ctx.isPointInPath(pawn.circle, x, y)) { if (ctx.isPointInPath(pawn.circle, x, y)) {
socket.emit('game:move', { pawnId: pawn._id }); socket.emit('game:move', pawn._id);
} }
} }
setHintPawn(null); setHintPawn(null);
@ -212,9 +212,6 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
socket.on('game:move', () => { socket.on('game:move', () => {
setHintPawn(null); setHintPawn(null);
}); });
socket.on('game:skip', () => {
setHintPawn(null);
});
socket.on('game:roll', () => { socket.on('game:roll', () => {
setHintPawn(null); setHintPawn(null);
}); });