Major changes

- Minor improvements
- Added random ship depletion. When prep phase ends, remaining ships are automatically placed in random valid positions
This commit is contained in:
MaciejkaG 2024-04-06 00:05:11 +02:00
parent 282c713ead
commit acdbad41cd
4 changed files with 176 additions and 33 deletions

View File

@ -230,7 +230,7 @@ app.post('/api/login', (req, res) => {
helpers: { helpers: {
error: "Niepoprawny adres e-mail", error: "Niepoprawny adres e-mail",
fallback: "/login", fallback: "/login",
t: (key) => { return locale.t(key) }
} }
}); });
} }
@ -277,7 +277,13 @@ app.post('/api/nickname', (req, res) => {
res.redirect('/'); res.redirect('/');
}); });
} else { } else {
res.sendStatus(400); res.render("error", {
helpers: {
error: "Nazwa nie spełnia wymogów: Od 3 do 16 znaków, nie może być pusta",
fallback: "/nickname",
t: (key) => { return locale.t(key) }
}
});
} }
}); });
@ -482,12 +488,19 @@ io.on('connection', async (socket) => {
let UTCTs = Math.floor((new Date()).getTime() / 1000 + 90); let UTCTs = Math.floor((new Date()).getTime() / 1000 + 90);
io.to(playerGame.id).emit('turn update', { turn: 0, phase: "preparation", timerToUTC: UTCTs }); io.to(playerGame.id).emit('turn update', { turn: 0, phase: "preparation", timerToUTC: UTCTs });
GInfo.timer(playerGame.id, 90, async () => { GInfo.timer(playerGame.id, 90, async () => {
const playerGame = await GInfo.getPlayerGameData(socket); const members = [...roomMemberIterator(playerGame.id)];
for (let i = 0; i < playerGame.data.boards.length; i++) { for (let i = 0; i < members.length; i++) {
const ships = playerGame.data.boards[i].ships; const sid = members[i][0];
if (!ships.length) { const socket = io.sockets.sockets.get(sid);
AFKEnd(playerGame.id);
return; let placedShips = await GInfo.depleteShips(socket);
placedShips.forEach(shipData => {
socket.emit("placed ship", shipData)
});
if (placedShips.length > 0) {
const locale = new Lang(session.langs);
socket.emit("toast", locale.t("board.Your remaining ships have been randomly placed"))
} }
} }

View File

@ -112,6 +112,7 @@
"You cannot place a ship like this": "You cannot place a ship like this", "You cannot place a ship like this": "You cannot place a ship like this",
"You have ran out of ships of that type": "You have ran out of ships of that type", "You have ran out of ships of that type": "You have ran out of ships of that type",
"You have already shot at this field": "You have already shot at this field", "You have already shot at this field": "You have already shot at this field",
"Your remaining ships have been randomly placed": "Your remaining ships have been automatically placed",
"Victory": "Victory", "Victory": "Victory",
"Defeat": "Defeat" "Defeat": "Defeat"

View File

@ -114,6 +114,7 @@
"You cannot place a ship like this": "Nie możesz tak postawić statku", "You cannot place a ship like this": "Nie możesz tak postawić statku",
"You have ran out of ships of that type": "Skończyły ci się statki tego typu", "You have ran out of ships of that type": "Skończyły ci się statki tego typu",
"You have already shot at this field": "Już strzelałeś w to pole", "You have already shot at this field": "Już strzelałeś w to pole",
"Your remaining ships have been randomly placed": "Twoje pozostałe statki zostały automatycznie rozstawione",
"Victory": "Zwycięstwo", "Victory": "Zwycięstwo",
"Defeat": "Porażka" "Defeat": "Porażka"

View File

@ -46,7 +46,6 @@ export class GameInfo {
const boards = await this.redis.json.get(`game:${socket.session.activeGame}`, { path: ".boards" }); const boards = await this.redis.json.get(`game:${socket.session.activeGame}`, { path: ".boards" });
let stats = []; let stats = [];
console.log(boards);
boards.forEach(board => { boards.forEach(board => {
stats.push(board.stats); stats.push(board.stats);
}); });
@ -100,6 +99,113 @@ export class GameInfo {
await this.redis.json.arrAppend(key, `.boards[${playerIdx}].ships`, shipData); await this.redis.json.arrAppend(key, `.boards[${playerIdx}].ships`, shipData);
} }
async depleteShips(socket) {
const gameId = socket.session.activeGame;
const key = `game:${gameId}`;
const hostId = (await this.redis.json.get(key, { path: '.hostId' }));
const playerIdx = socket.request.session.id === hostId ? 0 : 1;
var playerShips = (await this.redis.json.get(key, { path: `.boards[${playerIdx}].ships` }));
const availableShips = getShipsAvailable(playerShips);
const boardRender = [];
const subtrahents = [[0, 0], [0, 1], [1, 0], [0, -1], [-1, 0], [1, 1], [-1, -1], [1, -1], [-1, 1]];
for (let i = 0; i < 10; i++) {
var array = [];
for (let i = 0; i < 10; i++) {
array.push(false);
}
boardRender.push(array);
}
playerShips.forEach(ship => {
let multips;
switch (ship.rot) {
case 0:
multips = [1, 0];
break;
case 1:
multips = [0, 1];
break;
case 2:
multips = [-1, 0];
break;
case 3:
multips = [0, -1];
break;
}
for (let i = 0; i <= ship.type; i++) {
for (let l = 0; l < subtrahents.length; l++) {
const idxX = ship.posX - subtrahents[l][0] + multips[0] * i;
const idxY = ship.posY - subtrahents[l][1] + multips[1] * i;
if (!(idxX < 0 || idxX > 9 || idxY < 0 || idxY > 9)) {
boardRender[idxX][idxY] = true;
}
}
}
});
const placedShips = [];
for (let i = 0; i < availableShips.length; i++) {
let availableShipsOfType = availableShips[i];
for (let j = 0; j < availableShipsOfType; j++) {
playerShips = (await this.redis.json.get(key, { path: `.boards[${playerIdx}].ships` }));
for (let y = 0; y < 10; y++) {
let row = "";
for (let x = 0; x < 10; x++) {
row += `${boardRender[x][y] ? "\x1b[31m" : "\x1b[32m"}${boardRender[x][y]}\x1b[0m\t`;
}
}
const search = findEmptyFields(boardRender, i+1);
const rPos = search[Math.floor(Math.random() * search.length)];
placedShips.push({ type: i, posX: rPos.posX, posY: rPos.posY, rot: rPos.rot });
await this.redis.json.arrAppend(key, `.boards[${playerIdx}].ships`, { type: i, posX: rPos.posX, posY: rPos.posY, rot: rPos.rot, hits: Array.from(new Array(i + 1), () => false) });
let multips;
switch (rPos.rot) {
case 0:
multips = [1, 0];
break;
case 1:
multips = [0, 1];
break;
case 2:
multips = [-1, 0];
break;
case 3:
multips = [0, -1];
break;
}
for (let k = 0; k <= i; k++) {
for (let l = 0; l < subtrahents.length; l++) {
const idxX = rPos.posX - subtrahents[l][0] + multips[0] * k;
const idxY = rPos.posY - subtrahents[l][1] + multips[1] * k;
if (!(idxX < 0 || idxX > 9 || idxY < 0 || idxY > 9)) {
boardRender[idxX][idxY] = true;
}
}
}
}
}
return placedShips;
}
async removeShip(socket, posX, posY) { async removeShip(socket, posX, posY) {
const gameId = socket.session.activeGame; const gameId = socket.session.activeGame;
const key = `game:${gameId}`; const key = `game:${gameId}`;
@ -175,30 +281,6 @@ export function isPlayerInRoom(socket) {
return !socket.rooms.size === 1; return !socket.rooms.size === 1;
} }
var lastTimeChange = new Date().getTime();
// export function getShipsLeft(data, playerIdx) {
// let shipsLeft = [4, 3, 2, 1];
// const playerShips = shipsLeft.boards[playerIdx].ships;
// playerShips.forEach(ship => {
// var isSunk = true;
// ship.hits.every(isHit => {
// isSunk = isHit;
// return isHit;
// });
// switch (ship.type) {
// case 0:
// shipsLeft[0]--;
// break;
// default:
// break;
// }
// });
// }
export function getShipsAvailable(ships) { export function getShipsAvailable(ships) {
let shipsLeft = [4, 3, 2, 1]; let shipsLeft = [4, 3, 2, 1];
@ -340,6 +422,52 @@ export function checkTurn(data, playerId) {
} }
} }
function findEmptyFields(grid, len) {
const rowPlacements = [];
// Helper function to check if a row can be placed horizontally at a given position
function canPlaceHorizontally(x, y) {
if (x + len >= grid[0].length) {
return false; // Ship exceeds board boundaries
}
for (let i = x; i <= x + len; i++) {
if (grid[i][y]) {
return false; // One of ship's fields is already occupied
}
}
return true;
}
// Helper function to check if a row can be placed vertically at a given position
function canPlaceVertically(x, y) {
if (y + len >= grid.length) {
return false; // Ship exceeds board boundaries
}
for (let i = y; i <= y + len; i++) {
if (grid[x][i]) {
return false; // One of ship's fields is already occupied
}
}
return true;
}
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[j][i] === false) {
if (canPlaceHorizontally(j, i)) {
rowPlacements.push({ posX: j, posY: i, rot: 0 });
}
if (canPlaceVertically(j, i)) {
rowPlacements.push({ posX: j, posY: i, rot: 1 });
}
}
}
}
return rowPlacements;
}
function clamp(n, min, max) { function clamp(n, min, max) {
return Math.min(Math.max(n, min), max); return Math.min(Math.max(n, min), max);
} }