UNPKG

playship_ludo_pseudo_quick

Version:

Server side neutrino plugin code for ludo game

557 lines (544 loc) 18.2 kB
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 };