wildcard and serverside scoring
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,4 +3,4 @@ client/node_modules/
|
||||
server/node_modules/
|
||||
*.log
|
||||
*.env
|
||||
.turns-debug.json
|
||||
turns-debug.json
|
||||
|
||||
@@ -34,12 +34,17 @@ or just use environment variables
|
||||
|
||||
### Bugs and Issues
|
||||
|
||||
Prettymuch all of the bugs i'm aware of occur when a user reconnects to a game that's taking place. ESPECIALLY if that user is the host of the game
|
||||
|
||||
### Contributing
|
||||
|
||||
To contribute a translation
|
||||
To contribute a translation there's a few scripts that need to be run
|
||||
|
||||
To see what needs to be completed code-wise, take a look at `TODO`, there you will find tasks that need to be completed as well as known bugs. There's also a lot of TODOs in the code :)
|
||||
|
||||
### Acknowledgements
|
||||
|
||||
Express.js - HTTP Routing and Management
|
||||
Socket.io - Socket Routing and Management
|
||||
|
||||
Inês Filipa Baiõa Antunes - Tranlations (Portuguese, Spanish)
|
||||
|
||||
24
TODO
24
TODO
@@ -15,8 +15,8 @@
|
||||
→ Update with new locales
|
||||
✔ Spanish (Ines) @done(21-04-11 01:03)
|
||||
→ Update with new locales
|
||||
→ French (Alexendro)
|
||||
→ Czech (Mikdore)
|
||||
✘ French (Alexendro) @cancelled(21-05-10 18:22)
|
||||
✘ Czech (Mikdore) @cancelled(21-05-10 18:22)
|
||||
→ Go through code again once finished and pick out locales
|
||||
|
||||
☐ Lobbying logic
|
||||
@@ -28,14 +28,14 @@
|
||||
→ Find appropriate scrabble dictionary for
|
||||
✔ Portuagese @done(21-04-19 02:10)
|
||||
✔ Spanish @done(21-04-19 02:10)
|
||||
✔ French @done(21-04-19 02:10)
|
||||
→ Czech
|
||||
✔ French @done(21-05-10 18:22)
|
||||
✘ Czech @cancelled(21-05-10 18:22)
|
||||
→ Optimise! n-ary tree
|
||||
|
||||
☐ Game networking
|
||||
→ Figure out game reconnection procedure
|
||||
→ Perhaps players skip a turn if they disconnect on their turn
|
||||
→ Game should go on until 1 person remains
|
||||
✔ Figure out game reconnection procedure @done(21-05-10 18:22)
|
||||
✘ Perhaps players skip a turn if they disconnect on their turn @cancelled(21-05-10 18:22)
|
||||
✘ Game should go on until 1 person remains @cancelled(21-05-10 18:22)
|
||||
→ Game chat
|
||||
|
||||
☐ Game logic
|
||||
@@ -52,13 +52,13 @@
|
||||
✔ Update dynamically @done(21-05-09 22:44)
|
||||
|
||||
☐ Code
|
||||
→ Refactor to code portsoc eslint
|
||||
→ Refactor game client
|
||||
✘ Refactor to code portsoc eslint @cancelled(21-05-10 18:22)
|
||||
✘ Refactor game client @cancelled(21-05-10 18:22)
|
||||
→ WHY THE HELL ARE THEY CALLED USERS IN SOME PLACES AND PLAYERS IN OTHERS
|
||||
→ Why in some places is it user.name and others user.username
|
||||
→ Should lobbies persist once game starts?
|
||||
|
||||
☐ Bugfixes
|
||||
→ If a user leaves their current game then makes a new one, it's corrupted
|
||||
✔ If a user leaves their current game then makes a new one, it's corrupted @done(21-05-10 17:56)
|
||||
→ If a user disconnects during a game, the game is irrevokably corrupted
|
||||
|
||||
|
||||
→ Usually, if a player leaves, it's fine, but if the host leaves. The lobbby is destructed and the logic creates a new game on the spot and they're the only player
|
||||
|
||||
@@ -162,10 +162,10 @@ socket.on('lobby-create-error', obj => {
|
||||
|
||||
const errorDiv = document.createElement('div');
|
||||
errorDiv.id = 'lobby-error';
|
||||
errorDiv.innerHTML = localeString('error-bold') + ' ' + localeString('error-creating-lobby') + ' ' + JSON.stringify(args);
|
||||
errorDiv.innerHTML = localeString('error-bold') + ' ' + localeString('error-creating-lobby') + ' ' + JSON.stringify(obj);
|
||||
errorDiv.classList.add('red');
|
||||
CreateLobbyBlock.appendChild(errorDiv);
|
||||
pageLog(localeString('error-bold') + ' ' + localeString('error-creating-lobby') + ' ' + JSON.stringify(args));
|
||||
pageLog(localeString('error-bold') + ' ' + localeString('error-creating-lobby') + ' ' + JSON.stringify(obj));
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ NOTES
|
||||
let Users = [];
|
||||
// just shorthand, so long as i remember to keep it updated lmao
|
||||
let MyTurn = false;
|
||||
let TileSet = [];
|
||||
|
||||
let pastTurns = [];
|
||||
|
||||
@@ -27,6 +28,8 @@ function initGame(boardstates, tileset, myplayer, players)
|
||||
{
|
||||
pastTurns.push(...boardstates);
|
||||
|
||||
TileSet = tileset;
|
||||
|
||||
// construct piece array
|
||||
// structure [{letter: '', score: int}]
|
||||
let drawerStructure = [];
|
||||
|
||||
@@ -341,12 +341,12 @@
|
||||
|
||||
|
||||
<script src="index.js"></script>
|
||||
<script src="network.js"></script>
|
||||
<script src="ui.js"></script>
|
||||
<script src="dragable.js"></script>
|
||||
<script src="board.js"></script>
|
||||
<script src="pieces.js"></script>
|
||||
<script src="game.js"></script>
|
||||
<script src="events.js"></script>
|
||||
<script src="network.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -129,6 +129,16 @@ function onIdentifyError(socket, args)
|
||||
ConnectionState.forEach(e => {
|
||||
e.innerHTML = JSON.stringify(args);
|
||||
});
|
||||
removePiecesFromDrawer('*');
|
||||
addPiecesToDrawer([
|
||||
{letter: 'H', score: 1},
|
||||
{letter: 'E', score: 2},
|
||||
{letter: 'L', score: 3},
|
||||
{letter: 'L', score: 4},
|
||||
{letter: 'O', score: 5},
|
||||
{letter: 'O', score: 6},
|
||||
{letter: 'O', score: 7}
|
||||
]);
|
||||
onDisconnect();
|
||||
}
|
||||
|
||||
@@ -299,6 +309,15 @@ if (isSingleplayer)
|
||||
e.innerHTML = localeString('no-connection-singleplayer');
|
||||
});
|
||||
alert('Singleplayer is not implemented yet! a practice board will be set up to demonstrate tech and tile stuff');
|
||||
addPiecesToDrawer([
|
||||
{letter: 'H', score: 1},
|
||||
{letter: 'E', score: 2},
|
||||
{letter: 'L', score: 3},
|
||||
{letter: 'L', score: 4},
|
||||
{letter: 'O', score: 5},
|
||||
{letter: 'O', score: 6},
|
||||
{letter: 'O', score: 7}
|
||||
]);
|
||||
} else
|
||||
{
|
||||
initMultiplayer();
|
||||
|
||||
@@ -52,6 +52,11 @@ function addPiecesToDrawer(pieces)
|
||||
// Removes regardless of vadility
|
||||
function removePiecesFromDrawer(pieces)
|
||||
{
|
||||
if (pieces === '*')
|
||||
{
|
||||
Drawer.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
for (const piece of pieces)
|
||||
{
|
||||
piece.remove();
|
||||
@@ -221,6 +226,43 @@ function piecePlaced(piece)
|
||||
piece.classList.add('staged-piece');
|
||||
piece.dataset.coords = JSON.stringify(coords);
|
||||
|
||||
// Wildcard! (done clientside because of laziness)
|
||||
let letter = piece.dataset.letter;
|
||||
if (letter === '_')
|
||||
{
|
||||
// TODO: this would be a pretty good function for elsewhere..
|
||||
const tilesetincludes = (l) => {
|
||||
for (const range of TileSet)
|
||||
if (range.letters.includes(l)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
letter = prompt('You placed a wildcard! what would you like the letter to be?').toUpperCase();
|
||||
if (letter === null || !tilesetincludes(letter))
|
||||
{
|
||||
DrawerSounds[Math.floor(Math.random() * 3)].play();
|
||||
|
||||
piece.classList.remove('staged-piece');
|
||||
piece.classList.remove('small-piece');
|
||||
piece.classList.add('unplayed-piece');
|
||||
delete piece.dataset.coords;
|
||||
|
||||
setupPieces();
|
||||
return;
|
||||
}
|
||||
|
||||
piece.dataset.letter = letter;
|
||||
// no way to work this out here
|
||||
|
||||
let score = -1;
|
||||
for (const range in TileSet)
|
||||
if (TileSet[range].letters.includes(letter))
|
||||
score = TileSet[range].points;
|
||||
|
||||
piece.dataset.score = score;
|
||||
piece.innerHTML = `${piece.dataset.letter}<score>${piece.dataset.score}</score>`;
|
||||
}
|
||||
|
||||
setupPieces();
|
||||
} else
|
||||
{
|
||||
|
||||
@@ -149,6 +149,15 @@ function GetGameByUserUID(useruid)
|
||||
return false;
|
||||
}
|
||||
|
||||
function GetGameUserByUserUID(useruid)
|
||||
{
|
||||
for (const game in ActiveGames)
|
||||
for (const player of ActiveGames[game].players)
|
||||
if (player.uid === useruid) return player;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function GetTurnUser(gameuid)
|
||||
{
|
||||
if (!ActiveGames[gameuid]) return false;
|
||||
@@ -277,14 +286,32 @@ function PlayTurn(gameuid, playeruid, turn)
|
||||
}
|
||||
|
||||
// process outcome
|
||||
const temptiles = turn.oldboardtiles.concat(turn.boardtiles)
|
||||
|
||||
// check if user is allowed to make that move
|
||||
const gameplayer = GetGameUserByUserUID(playeruid);
|
||||
console.log(gameplayer);
|
||||
|
||||
// process turn and allocate scores
|
||||
|
||||
// give user new tiles
|
||||
|
||||
turn.boardtiles = turn.oldboardtiles.append(turn.boardtiles);
|
||||
// update tiles with scores
|
||||
turn.boardtiles = turn.oldboardtiles.concat(turn.boardtiles);
|
||||
for (const tile in turn.boardtiles)
|
||||
{
|
||||
let score = 0;
|
||||
for (const pointband of Dist.GetDist(game.locale).dist)
|
||||
{
|
||||
if (pointband.letters.includes(turn.boardtiles[tile].letter))
|
||||
{
|
||||
score = pointband.points;
|
||||
break;
|
||||
}
|
||||
}
|
||||
turn.boardtiles[tile].score = score;
|
||||
}
|
||||
|
||||
ActiveGames[gameuid].gamestates.push(turn);
|
||||
ActiveGames[gameuid].turn = turninfo.newTurn;
|
||||
ActiveGames[gameuid].turntotal = turninfo.newTotalTurn;
|
||||
@@ -327,9 +354,9 @@ function gameNextTurn(gameuid)
|
||||
}
|
||||
|
||||
// same as how the
|
||||
function EndGame()
|
||||
function EndGame(gameuid)
|
||||
{
|
||||
|
||||
delete ActiveGames[gameuid];
|
||||
}
|
||||
|
||||
|
||||
@@ -359,6 +386,7 @@ module.exports = {
|
||||
|
||||
// Get game exports
|
||||
GetGameByUserUID: GetGameByUserUID,
|
||||
GetGameUserByUserUID: GetGameUserByUserUID,
|
||||
GetTurnUser: GetTurnUser,
|
||||
|
||||
// Change game state exports
|
||||
|
||||
@@ -458,9 +458,16 @@ function HandleDisconnect(socket, args)
|
||||
// if user is in a game, notify the game logic
|
||||
// if the user is the last user in a game - delete it
|
||||
// if the user is leaving, change their status so reconnect is allowed
|
||||
|
||||
// TODO: VERY IMPORTANTTTT THAT^^^
|
||||
|
||||
// quick fix, prevents game destruction
|
||||
// if (user.intent === 'GAME')
|
||||
// {
|
||||
// Game.Registrar.UserDisconnect(user.uid);
|
||||
// Logger.info(`SOCKET ${socket.id} DISCONNECTED FROM GAME`);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if user is in a lobby, leave and if user own's a lobby, destruct
|
||||
// leave lobby before user is disconnected
|
||||
if (user.intent !== 'GAMETRANSITION')
|
||||
@@ -526,6 +533,8 @@ function EmitGameBegin(game)
|
||||
const userturnstartconnection = Game.Registrar.GetConnectionByUser(userturnstart);
|
||||
|
||||
io.to(userturnstartconnection).emit('game-your-turn');
|
||||
|
||||
Logger.debug(JSON.stringify(game.players, null, 2));
|
||||
}
|
||||
|
||||
function EmitGameReconnect(user, game)
|
||||
@@ -543,12 +552,17 @@ function EmitGameReconnect(user, game)
|
||||
// NOTE it shouldn't ever be their turn on a reconnect
|
||||
// as the game logic should pass control to next player
|
||||
// as the game order is changed
|
||||
if (!Game.Logic.GetTurnUser(game.uid)) return;
|
||||
const userturnstart = Game.Logic.GetTurnUser(game.uid).uid;
|
||||
if (userturnstart === user.uid)
|
||||
{
|
||||
const userturnstartconnection = Game.Registrar.GetConnectionByUser(userturnstart);
|
||||
|
||||
io.to(userturnstartconnection).emit('game-your-turn');
|
||||
}
|
||||
io.to(gameuserconnection).emit('game-your-turn');
|
||||
} else
|
||||
{
|
||||
// TODO: this needs to send game heuristics
|
||||
io.to(gameuserconnection).emit('game-turn-start');
|
||||
}
|
||||
|
||||
Logger.debug(JSON.stringify(game.players, null, 2));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user