playship_ludo_pseudo_quick
Version:
Server side neutrino plugin code for ludo game
557 lines (544 loc) • 18.2 kB
JavaScript
const enums = require('../utils/enums');
const {GAME_PROPS} = require("./enums");
const eventObjs = require("./newGameEvent");
const propertyCheckOrderForAbsw = [
enums.PLAYER_PROPS.MISS_MOVES,
enums.PLAYER_PROPS.ASCEND_COUNT,
enums.PLAYER_PROPS.KILLS,
enums.PLAYER_PROPS.GOT_KILLED,
enums.PLAYER_PROPS.TOTAL_TIME_PLAYED
]
const propMultipliers = {
[enums.PLAYER_PROPS.MISS_MOVES.name] : {
x : 1,
y : -1,
enumScoreWin : 3,
enumScoreLost : 3
},
[enums.PLAYER_PROPS.ASCEND_COUNT.name] :{
x : -1,
y : 1,
enumScoreWin : 4,
enumScoreLost : 4
},
[enums.PLAYER_PROPS.KILLS.name] : {
x : -1,
y : 1,
enumScoreWin : 5,
enumScoreLost : 5
},
[enums.PLAYER_PROPS.GOT_KILLED.name] : {
x : 1,
y : -1,
enumScoreWin : 6,
enumScoreLost : 6
},
[enums.PLAYER_PROPS.TOTAL_TIME_PLAYED.name] : {
x : 1,
y : -1,
enumScoreWin : 7,
enumScoreLost : 7
}
}
const scores = {
[enums.PLAYER_PROPS.MISS_MOVES.name] : {
"1" : 2,
"2" : 2,
"3" : 2,
"4" : 2,
},
[enums.PLAYER_PROPS.ASCEND_COUNT.name] : {
"1" : 13,
"2" : 14,
"3" : 2,
"4" : 4,
},
[enums.PLAYER_PROPS.KILLS.name] : {
"1" : 22,
"2" : 22,
"3" : 3,
"4" : 4,
},
[enums.PLAYER_PROPS.GOT_KILLED.name] : {
"1" : 32,
"2" : 31,
"3" : 3,
"4" : 4,
},
[enums.PLAYER_PROPS.TOTAL_TIME_PLAYED.name] : {
"1" : 42,
"2" : 42,
"3" : 3,
"4" : 4,
}
}
const parseBool = function(str, defValue) {
if (!str) return defValue || false;
return JSON.parse(str);
};
const logger = require('./playshipUtils').getLogger();
const gameObjById = function(game, id) {
let obj = game.getTransient('ludo_' + id);
if (obj) return obj;
obj = game.gameObjectByIds(id)[id];
obj._set = function(key, val) {
if (typeof key === 'string') return this.setProp(key, val);
switch (key.type) {
case 'object':
if (val) return this.setProp(key.name, JSON.stringify(val));
else return this.setProp(key.name, val);
default:
return this.setProp(key.name, val);
}
};
obj._get = function(key) {
if (typeof key === 'string') return this.getProp(key);
let val = this.getProp(key.name);
switch (key.type) {
case 'boolean':
return parseBool(val);
case 'number':
return parseFloat(val);
case 'object':
return JSON.parse(val || null);
case 'csv':
if (val) return val.split(',');
return val;
default:
return val;
}
};
game.addTransient('ludo_' + id, obj);
return obj;
};
const getPlayerProp = function(game, playerId, key) {
if (typeof key === 'string')
return game.getPlayerProp(playerId, key);
let val = game.getPlayerProp(playerId, key.name);
switch (key.type) {
case 'boolean':
return parseBool(val);
case 'number':
return parseFloat(val);
case 'object':
return JSON.parse(val || null);
case 'objectSync':
let o = JSON.parse(val || null);
if (o) return o[key.name];
else return o;
case 'csv':
if (val) return val.split(',');
return val;
default:
return val;
}
};
const setPlayerProp = function(game, playerId, key, value) {
if (typeof key === 'string')
return game.setPlayerProp(playerId, key, value);
switch (key.type) {
case 'object':
if (value)
return game.setPlayerProp(playerId, key.name, JSON.stringify(value));
else
return game.setPlayerProp(playerId, key.name, value);
case 'objectSync':
if (value)
return game.setPlayerProp(playerId, key.name,
JSON.stringify({[key.name]: value}));
else
return game.setPlayerProp(playerId, key.name, value);
default:
return game.setPlayerProp(playerId, key.name, value);
}
};
const getGameProp = function(game, key) {
if (typeof key === 'string')
return game.getGameProp(key);
let val = game.getGameProp(key.name);
switch (key.type) {
case 'boolean':
return parseBool(val);
case 'number':
return parseFloat(val);
case 'object':
return JSON.parse(val || null);
default:
return val;
}
};
const setGameProp = function(game, key, value) {
if (typeof key === 'string')
return game.setGameProp(key, value);
switch (key.type) {
case 'object':
if (value)
return game.setGameProp(key.name, JSON.stringify(value));
else
return game.setGameProp(key.name, value);
default:
return game.setGameProp(key.name, value);
}
};
const getMeta = function(game) {
let meta = game.getTransient('_meta');
if (!meta) {
meta = game.getGameMeta();
game.addTransient('_meta', meta);
}
return meta;
};
const getAllPlayerOwnedObjectIds = function(game, playerId) {
let objKey = 'ludo_player_' + playerId;
let objIds = game.getTransient(objKey);
if (objIds) return objIds;
let allObjIds = game.getAllObjIds();
objIds = [];
for (let oid of allObjIds) if (game.getOwner(oid) === playerId)
objIds.push(oid);
game.addTransient(objKey, objIds);
return objIds;
};
const getNextTurnPlayerId = function(game,playerId){
const gk = {key: game.getId()};
let playerSeating = game.getPlayerSeating()
for(let i = 0 ; i <playerSeating.length;i++ ) {
logger.debug(gk,"player seating and playerId ," , playerSeating , playerId)
if (playerSeating[i] === playerId) {
if (i === playerSeating.length - i) return playerSeating[0]
return playerSeating[i + 1]
}
}
}
const handleRoll = function(game,playerId,rollInfo,diceRollEvent){
const gk = {key: game.getId()};
if(!rollInfo) return;
let isAutoRollEnabled = JSON.parse(rollInfo).isAutoRollEnabled
if(isAutoRollEnabled){
diceRollEvent.genus = "AUTO_ROLL"
let autoRollCount = getPlayerProp(game,playerId,enums.PLAYER_PROPS.AUTO_ROLL_COUNT)
setPlayerProp(game,playerId,enums.PLAYER_PROPS.AUTO_ROLL_COUNT,autoRollCount+1)
}else {
diceRollEvent.genus = "MANUAL_ROLL"
let playerROllCount = getPlayerProp(game,playerId,enums.PLAYER_PROPS.PLAYER_ROLL_COUNT)
setPlayerProp(game,playerId,enums.PLAYER_PROPS.PLAYER_ROLL_COUNT,playerROllCount + 1)
}
let turnExpiry = game.getCurrentTurnExpiry();
let now = Date.now();
const meta = getMeta(game);
let duration = meta.turnDuration;
let timeTakenToPlay = duration - turnExpiry + now;
diceRollEvent.time_stats = timeTakenToPlay;
game.publishNewGameEvent(playerId,diceRollEvent);
}
const isHighestScore = function(game,playerId){
let hScore = game.getPlayerScore(playerId)
let pScore = game.getPlayerScore(playerId)
for (let p of game.getPlayerSeating()){
if(p === playerId) continue;
let playerScore = game.getPlayerScore(p)
if(playerScore > hScore)
hScore = playerScore
}
if(hScore > pScore) return false
return true
}
const isForfeitTurnCountBreached = function(game,playerId){
let curTurnCount = getPlayerProp(game, playerId, enums.PLAYER_PROPS.TURN_COUNT);
let gameTurnCounter =game.getCurrentTurnIndex()
let numPlayers = game.getNumberOfPlayers();
if(numPlayers === 2){
if(gameTurnCounter > 22 || curTurnCount > 11) return true
}else if(numPlayers === 4){
if(gameTurnCounter > 30 || curTurnCount > 7) return true
}
return false;
}
const gameOver = function(game,endGameReason){
const gk = {key: game.getId()};
try {
for (let p of game.getPlayerSeating()) {
let autoRollCount = getPlayerProp(game, p,
enums.PLAYER_PROPS.AUTO_ROLL_COUNT)
let playerRollCount = getPlayerProp(game, p,
enums.PLAYER_PROPS.PLAYER_ROLL_COUNT)
let curAscendCount = getPlayerProp(game, p,
enums.PLAYER_PROPS.ASCEND_COUNT) || 0;
game.publishGameEvent(1614, [p], autoRollCount);
game.publishGameEvent(1615, [p], playerRollCount);
if(curAscendCount >=4) {
if(!isHighestScore(game,p)) {
game.publishGameEvent(1616, [p]);
}
}
}
let forfeitWinnerFraud = isForfeitWinnerFraud(game)
logger.debug(gk,"forfeit fraud check ",forfeitWinnerFraud)
if(forfeitWinnerFraud.isFraud){
let fraudForfeitWinnerEvent = new eventObjs.fraudForfeitWinner()
fraudForfeitWinnerEvent.userId2 = game.getUserIdByPlayerId(forfeitWinnerFraud.player);
game.publishGameFraudEvent(forfeitWinnerFraud.fraudPlayer,fraudForfeitWinnerEvent)
}
game.endGame(endGameReason)
}catch (e){
game.endGame(endGameReason)
}
}
const isForfeitWinnerFraud = function(game){
const gk = {key: game.getId()};
logger.debug(gk,"is a forfeit in game " + getGameProp(game,GAME_PROPS.IS_FORFEIT_FRAUD_BY_ANY_PLAYER))
if(!getGameProp(game,GAME_PROPS.IS_FORFEIT_FRAUD_BY_ANY_PLAYER)) return {
isFraud: false
}
let hScore = getGameProp(game,GAME_PROPS.FORFEIT_HIGHEST_PLAYER_SCORE);
logger.debug(gk,"highest score, ", hScore)
let meta = getMeta(game)
let localHighestScore = 0;
let player = null;
for (let p of game.getPlayerSeating()){
let playerScore = game.getPlayerScore(p)
logger.debug(gk,"player score,%s and playerId %s", playerScore,p)
if(playerScore > localHighestScore) {
localHighestScore = playerScore
player = p;
}
}
let scoreLimit = meta.forfeitWinnerScoreDiff || 2
let isFraud = (hScore - localHighestScore) > scoreLimit
return {
isFraud : isFraud,
player : player,
fraudPlayer : getGameProp(game,GAME_PROPS.FORFEIT_HIGHEST_PLAYER_ID)
}
}
const remainingTurnToEndGame = function(game){
let playerFound = false
let playerId = game.getCurrentTurnPlayerId()
let players = []
for (let p of game.getPlayerSeating()){
if(p === playerId) {
playerFound = true;
players.push(p)
continue
};
if(playerFound) players.push(p)
}
return players
}
const aggregatePlayerTurnTime = function(game,playerId){
const gk = {key: game.getId()};
let playerTotalPlayTime = getPlayerProp(game,playerId,
enums.PLAYER_PROPS.TOTAL_TIME_PLAYED)
let now = Date.now();
let turnExpiry = game.getCurrentTurnExpiry();
let turnDuration = getMeta(game).turnDuration;
logger.debug(gk,"playerTotalPlayTime",playerTotalPlayTime)
logger.debug(gk,"variables",turnDuration,turnExpiry)
let remainingTime = turnDuration + turnExpiry - now
playerTotalPlayTime = playerTotalPlayTime + remainingTime
setPlayerProp(game,playerId,enums.PLAYER_PROPS.TOTAL_TIME_PLAYED,playerTotalPlayTime)
}
const playersScoreByPlayerProp = function(game, playerList,playerProp){
let propScore = []
if(typeof game !== 'object'){
for (let i = 0 ; i < playerList.length ; i++){
let playerId = playerList[i]
propScore.push({playerId : playerId , score :
scores[playerProp.name][playerId]})
}
}else {
for (let i = 0; i < playerList.length; i++) {
let playerId = playerList[i]
propScore.push({
playerId: playerId, score:
getPlayerProp(game, playerId, playerProp)
})
}
}
let multiplier = propMultipliers[playerProp.name]
propScore.sort((a,b)=> (multiplier.y * b.score) +
(multiplier.x * a.score))
return propScore;
}
const getNextPropForCheck = function(property){
switch (property){
case enums.PLAYER_PROPS.MISS_MOVES:
return enums.PLAYER_PROPS.ASCEND_COUNT;
case enums.PLAYER_PROPS.ASCEND_COUNT :
return enums.PLAYER_PROPS.KILLS;
case enums.PLAYER_PROPS.KILLS :
return enums.PLAYER_PROPS.GOT_KILLED;
case enums.PLAYER_PROPS.GOT_KILLED :
return enums.PLAYER_PROPS.TOTAL_TIME_PLAYED;
case enums.PLAYER_PROPS.TOTAL_TIME_PLAYED:
return "NOTHING"
}
}
function shuffle(array) {
let currentIndex = array.length, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
const findAbsoluteWinnerForPlayerProp = function(game,playerList,playerProp,finalList){
const gk = {key: game.getId()};
logger.info(gk,"finding score,",playerProp)
if(playerProp === "NOTHING"){
let newList = shuffle(playerList);
for(let i = 0 ; i < newList.length ; i++){
finalList.push(newList[i])
}
return;
}
let playersScores = playersScoreByPlayerProp(game,playerList,
playerProp)
logger.info(gk,"player score by prop %s",playerProp,playersScores)
for (let i = 0 ; i < playersScores.length ; i++) {
let playerId = playersScores[i].playerId
let score = playersScores[i].score
let totalMatches = 0
for(let j = i + 1 ; j < playersScores.length ; j++){
if(score !== playersScores[j].score){
setGameProp(game,enums.GAME_PROPS.ABSOLUTE_WIN_TYPE,
propMultipliers[playerProp.name].enumScoreWin)
break;
}else {
totalMatches++
}
}
if(totalMatches === 0 ) {
finalList.push(playerId)
}else {
let tiePlayers = []
for(let z = 0 ; z <= totalMatches ; z++){
tiePlayers.push(playersScores[i+z].playerId)
}
findAbsoluteWinnerForPlayerProp(game,tiePlayers,
getNextPropForCheck(playerProp),finalList)
i += (totalMatches)
}
}
}
const findAbsoluteWinners = function(game, playerList){
let finalList = []
findAbsoluteWinnerForPlayerProp(game,playerList,
propertyCheckOrderForAbsw[0],finalList)
return finalList;
}
function offExtraTimeIfEnabledAndExtGameTime (game, playerId, turnEvent){
const gk = {key: game.getId()};
let isGamePaused = getGameProp(game,enums.GAME_PROPS.IS_GAME_PAUSED);
if(!isGamePaused) return;
let extraTimeStart = getGameProp(game,enums.GAME_PROPS.EXTRA_TIME_START_TIME);
let extraTimeCheckTime = getGameProp(game,enums.GAME_PROPS.EXTRA_TIME_CHECK_TIME);
let now = Date.now();
let gameTimerEndTs = getGameProp(game, enums.GAME_PROPS.GAME_TIMER_END_TS);
gameTimerEndTs = gameTimerEndTs + now - extraTimeStart;
logger.debug(gk , 'game timer increased by %s', now - extraTimeCheckTime)
setGameProp(game,enums.GAME_PROPS.GAME_TIMER_END_TS,gameTimerEndTs);
let playerRemExtraTime = getPlayerRemExtraTime(game,playerId);
let remExtraTime = playerRemExtraTime - now + extraTimeCheckTime;
logger.debug(gk,"start time %s , now %s and remaining time %s",
extraTimeCheckTime,now,remExtraTime)
game.setPlayerRemainingExtraTime(playerId,remExtraTime)
if(turnEvent) turnEvent.extra_time = now - extraTimeStart;
setGameProp(game,enums.GAME_PROPS.IS_GAME_PAUSED,false);
setGameProp(game,enums.GAME_PROPS.EXTRA_TIME_START_TIME,-1);
setGameProp(game,enums.GAME_PROPS.EXTRA_TIME_CHECK_TIME,-1)
}
getGameTimeLeft = function(game,playerId){
let gameTimerEndTs = getGameProp(game, enums.GAME_PROPS.GAME_TIMER_END_TS);
const meta = getMeta(game);
let now = Date.now()
if(!meta.isGamePauseEnabled ||
(game.getBattleType() === enums.BATTLE_TYPES.TOURNAMENT) )
return { gameTime : gameTimerEndTs - now, isExtraTimeEnabled : false};
let isGamePaused = getGameProp(game,enums.GAME_PROPS.IS_GAME_PAUSED);
if(!isGamePaused) return { gameTime : gameTimerEndTs - now,
isExtraTimeEnabled : true};
let extraTimeStart = getGameProp(game,enums.GAME_PROPS.EXTRA_TIME_START_TIME);
let extraTimeCheckTime = getGameProp(game,enums.GAME_PROPS.EXTRA_TIME_CHECK_TIME);
let playerRemExtraTime = getPlayerRemExtraTime(game,playerId)
return { gameTime : gameTimerEndTs - extraTimeStart,
extraTime: playerRemExtraTime - now + extraTimeCheckTime,isExtraTimeEnabled : true }
}
const isPauseEnabled = function(game){
const meta = getMeta(game);
if(!meta.isGamePauseEnabled) return false;
if(game.getBattleType() === enums.BATTLE_TYPES.TOURNAMENT) return false;
return true;
}
const isGamePaused = function(game){
let isGamePaused = getGameProp(game,enums.GAME_PROPS.IS_GAME_PAUSED);
return isGamePaused
}
const getPlayerRemExtraTime = function(game,playerId){
let playerRemExtraTime = parseInt(game.getPlayerRemainingExtraTime(playerId))
return playerRemExtraTime
}
const publishGameDiceRollsInfo = function(game){
const gk = {key: game.getId()};
const publishData = [];
let position = 1;
for (let p of game.getPlayerSeating()){
const player = game.getUserByPlayerId(p);
let userDiceRollsInfo = getUserDiceRollsInfo(game,p);
if(!userDiceRollsInfo) {
return logger.error(gk,"error fetching user Dice rolls info , hence stopping the publish")
}
publishData.push({
userId : player.userId,
userName : player.name,
position :position,
gameKey : game.getId(),
diceSummary : userDiceRollsInfo.bag
})
position++;
}
game.publishGameInfoEvent("ENCRYPT_DICE_ROLL",publishData);
}
const getUserDiceRollsInfo = function(game,playerId){
let transKey = '_shuffler_' + playerId;
return game.getTransient(transKey);
}
const setPLayerInitGameScore = function(game,playerId){
const pieceType = getPlayerProp(game, playerId, enums.PLAYER_PROPS.COLOR);
let objIds = game.getAllObjIds();
let initScore = 0
for (let objId of objIds) {
let obj = gameObjById(game, objId)
if(pieceType === obj.type) {
initScore += obj._get(enums.OBJECT_PROPS.SCORE);
}
}
game.awardScore(playerId,initScore);
}
module.exports = {
_parseBool: parseBool,
_gameObjById: gameObjById,
_getPlayerProp: getPlayerProp,
_setPlayerProp: setPlayerProp,
_setGameProp: setGameProp,
_getGameProp: getGameProp,
_getMeta: getMeta,
_gameOver : gameOver,
_handleRoll : handleRoll,
_getAllPlayerOwnedObjectIds: getAllPlayerOwnedObjectIds,
_getNextTurnPlayerId : getNextTurnPlayerId,
_remainingTurnToEndGame : remainingTurnToEndGame,
_aggregatePlayerTurnTime : aggregatePlayerTurnTime,
_findAbsoluteWinner : findAbsoluteWinners,
_isHighestScore: isHighestScore,
_offExtraTimeIfEnabled : offExtraTimeIfEnabledAndExtGameTime,
_getGameTimeLeft : getGameTimeLeft,
_isPauseEnabled : isPauseEnabled,
_isGamePaused: isGamePaused,
_getPlayerRemExtraTime : getPlayerRemExtraTime,
_isForfeitTurnCountBreached : isForfeitTurnCountBreached,
_publishGameDiceRollsInfo : publishGameDiceRollsInfo,
_setPLayerInitGameScore : setPLayerInitGameScore
};