UNPKG

playship_ludo_pseudo_quick

Version:

Server side neutrino plugin code for ludo game

258 lines (234 loc) 9.69 kB
const enums = require('../utils/enums'); const logger = require('../utils/playshipUtils').getLogger(); const gameLogic = require('./logic'); const events = enums.NEW_EVENTS const eventObjs = require('../utils/newGameEvent') const { _getGameProp, _setGameProp, _getMeta, _setPlayerProp, _getPlayerProp,_gameOver, _remainingTurnToEndGame,_aggregatePlayerTurnTime, _offExtraTimeIfEnabled,_isPauseEnabled,_isGamePaused, _getPlayerRemExtraTime } = require('../utils/utils'); const {ALL_PLAYERS_EXHAUSTED_MOVED} = require('../utils/enums'); const PLAYER_PROPS = enums.PLAYER_PROPS; const GAME_PROPS = enums.GAME_PROPS; const step = function(game) { const gk = {key: game.getId()}; if (game.getState() >= 30) return logger.debug(gk, 'Game has ended, nothing to do'); let gameOverTs = _getGameProp(game, GAME_PROPS.GAME_OVER_TS); if (!isNaN(gameOverTs)) { if (Date.now() > gameOverTs) _gameOver(game,_getGameProp(game, GAME_PROPS.GAME_OVER_REASON)) //game.endGame(_getGameProp(game, GAME_PROPS.GAME_OVER_REASON)); return; } let gameTimerEndTs = _getGameProp(game, GAME_PROPS.GAME_TIMER_END_TS); let timeLeft = gameTimerEndTs - Date.now() if(isNaN(timeLeft)) return; if (timeLeft < 0 && !_getGameProp(game,GAME_PROPS.IS_FINAL_TURNS) && !_isGamePaused(game)){ _setGameProp(game, GAME_PROPS.IS_FINAL_TURNS, true); let remPlayer = _remainingTurnToEndGame(game) _setGameProp(game,GAME_PROPS.FINAL_REM_PLAYERS,remPlayer) game.syncGameStateServVars(); } checkAndSkipTurn(game); checkAndHandleTurnExpiry(game); checkMoveTurnAndEndGame(game); checkTurnSkip(game) checkForTip(game); }; function checkForTip(game) { const gk = {key: game.getId()}; const meta = _getMeta(game); let lastTipTs = game.getTransient(GAME_PROPS.LAST_TIP_TS); if (lastTipTs + meta.genericTipsCheckInterval > Date.now()) return; let random = Math.random(); if (random > meta.probabilityOfTip) return; let tipIdToSend = meta.genericTipIds[Math.floor( Math.random() * meta.genericTipIds.length)]; logger.debug(gk, 'genric tip probability cleared, sending tip tipId', tipIdToSend); game.addTransient(GAME_PROPS.LAST_TIP_TS, Date.now()); game.sendTip(game.getAllPlayerIds()[0], tipIdToSend); } function checkMoveTurnAndEndGame(game) { const gk = {key: game.getId()}; let nextTurnTs = _getGameProp(game, GAME_PROPS.NEXT_TURN_TS); logger.trace(gk, 'Next turn move ts is', nextTurnTs); if (Date.now() >= nextTurnTs) { _setGameProp(game, GAME_PROPS.NEXT_TURN_TS, null); let isTurnContinue = _getGameProp(game, GAME_PROPS.IS_CONTINUE); _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED_SERVER, false); _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED, false); _setGameProp(game, GAME_PROPS.IS_TURN_COMPLETED, false); game.addTransient(GAME_PROPS.IS_SKIP_CHECKED, false); game.syncGameStateServVars(); gameLogic.destroyForfeitPlayerPawns(game).catch(e => { logger.error(gk, 'forfeit players failed with exception', e); }); if (isTurnContinue) game.continueTurn(); else { if (checkAndEndGame(game)) return; // if game ends nothing to do game.nextTurn(); } gameLogic.issueTurnStartSavePoint(game); } } function checkAndEndGame(game) { const gk = {key: game.getId()}; let isGameTimerEnded = _getGameProp(game, GAME_PROPS.IS_FINAL_TURNS); if (!isGameTimerEnded) return false; let prevMoveCount; for (let p of game.getAllPlayerIds()) { logger.debug(gk,"player %s state count %s",p,game.getPlayerState(p)) if (parseInt(game.getPlayerState(p)) < 20) { let moveCount = _getPlayerProp(game, p, enums.PLAYER_PROPS.TURN_COUNT); logger.debug(gk,"player %s move count %s",p,moveCount) if (!prevMoveCount) prevMoveCount = moveCount; if (prevMoveCount !== moveCount) return false; } } _gameOver(game,ALL_PLAYERS_EXHAUSTED_MOVED) //game.endGame(ALL_PLAYERS_EXHAUSTED_MOVED); return true; } function checkAndSkipTurn(game) { const gk = {key: game.getId()}; if (_getGameProp(game, GAME_PROPS.IS_TURN_PROCESSED_SERVER)) return; const meta = _getMeta(game); let turnExpiry = game.getCurrentTurnExpiry(); let isTurnSkipChecked = game.getTransient(GAME_PROPS.IS_SKIP_CHECKED); let TURN_COOL_OFF_SKIP = meta.turnSkipCoolOffDur || 1000 if (turnExpiry > -1 && (turnExpiry + TURN_COOL_OFF_SKIP> Date.now() || _isGamePaused(game)) && !isTurnSkipChecked) { let playerId = game.getCurrentTurnPlayerId(); if(parseInt(game.getPlayerState(playerId)) === 30) return; if(gameLogic.isTurnSkip(game, playerId)) { if(_isGamePaused(game)) _offExtraTimeIfEnabled(game, playerId); game.addTransient(GAME_PROPS.IS_SKIP_CHECKED, true); game.addTransient(GAME_PROPS.IS_TURN_SKIPPED, true); logger.info(gk, 'Skipping turn due to no possible moves for', playerId); _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED, true); _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED_SERVER, true); game.syncGameStateServVars(); gameLogic.turnEndHandler(game, playerId, null, null,true, null,meta.addOnTimeForSkip || 500); } } } function checkAndHandleTurnExpiry(game) { const gk = {key: game.getId()}; if (_getGameProp(game, GAME_PROPS.IS_TURN_PROCESSED_SERVER)) return; let turnExpiry = game.getCurrentTurnExpiry(); logger.trace('Current turn expiry is', turnExpiry); const meta = _getMeta(game); let TURN_COOL_OFF = 0 if (turnExpiry > -1 && turnExpiry + TURN_COOL_OFF < Date.now()) { let playerId = game.getCurrentTurnPlayerId(); if(_isPauseEnabled(game)){ if(!_isGamePaused(game) ){ if(_getPlayerRemExtraTime(game,playerId) > 0) return pauseAndStartExtraTime(game,playerId); } else { if(canGameBePaused(game,playerId)) return; } } let missMoveEventObj = new eventObjs.missMoveEvent() if(parseInt(game.getPlayerState(playerId)) === 30) return; let curMissMoves = _getPlayerProp(game, playerId, PLAYER_PROPS.MISS_MOVES) + 1; _aggregatePlayerTurnTime(game,playerId) logger.info(gk, 'Miss move, switching turn for player', playerId, 'curMissMoves', curMissMoves); game.incrPluginStats('ludo.movemissed.count'); let isPlayerConnected = false let connectedPlayers = game.getConnectedPlayers() for(let i = 0 ; i < connectedPlayers.length;i++){ if(connectedPlayers[i] === playerId){ isPlayerConnected = true break; } } missMoveEventObj.class = isPlayerConnected ? 1 : 0 let curTurnCount = _getPlayerProp(game, playerId, PLAYER_PROPS.TURN_COUNT); missMoveEventObj.kingdom = curTurnCount + 1 game.publishNewGameEvent(playerId,missMoveEventObj) game.publishHHGameEvent(playerId,"miss_move",{ turn_id : game.getCurrentTurnId(), update_time : Date.now() }) game.publishExternalGameEvent('BE_GAME_MISSED_MOVE',playerId,{ turn_id : game.getCurrentTurnId(), connected : isPlayerConnected ? 1 : 0, missed_move_count : curMissMoves, update_time : Date.now() }) _setPlayerProp(game, playerId, PLAYER_PROPS.MISS_MOVES, curMissMoves); if (curMissMoves === 1) game.sendTip(playerId, 8); else if (curMissMoves === 2) game.sendTip(playerId, 9); if (curMissMoves >= meta.maxMissMoves) { game.syncPlayerServVars(playerId); logger.debug(gk, 'Max miss moves reached', curMissMoves, 'by', playerId); _setGameProp(game,GAME_PROPS.ABSOLUTE_WIN_TYPE,1) game.forfeitGameForPlayer(playerId, enums.MAX_MISS_MOVES); game.publishGameEvent(1609, [playerId]); game.incrPluginStats('ludo.moves.allmiss'); return; } _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED, true); _setGameProp(game, GAME_PROPS.IS_TURN_PROCESSED_SERVER, true); if(_isPauseEnabled(game)){_offExtraTimeIfEnabled(game,playerId)} game.syncGameStateServVars(); gameLogic.turnEndHandler(game, playerId,null,null,true, null); game.publishNewGameEvent(playerId,missMoveEventObj) checkMoveTurnAndEndGame(game) } } const canGameBePaused = function(game,playerId){ const gk = {key: game.getId()}; let remainingExtraTime = getRemainingExtraTime(game,playerId) logger.debug(gk,"is game paused %s remaining time", remainingExtraTime); if(remainingExtraTime > 0) return true; return false; } const getRemainingExtraTime = function(game,playerId){ let extraTimeCheckTime = _getGameProp(game,GAME_PROPS.EXTRA_TIME_CHECK_TIME); let playerRemExtraTime = game.getPlayerRemainingExtraTime(playerId) let now = Date.now() return playerRemExtraTime + extraTimeCheckTime - now } const pauseAndStartExtraTime= function(game,playerId){ _setGameProp(game,GAME_PROPS.IS_GAME_PAUSED,true); let now = Date.now(); let gameTimerEndTs = _getGameProp(game, enums.GAME_PROPS.GAME_TIMER_END_TS); let timeLeft = gameTimerEndTs - now _setGameProp(game, GAME_PROPS.GAME_TIMER_REMAINING, timeLeft >= 0 ? timeLeft : 0); _setGameProp(game,GAME_PROPS.EXTRA_TIME_START_TIME,now); _setGameProp(game,GAME_PROPS.EXTRA_TIME_CHECK_TIME,now) game.incrPluginStats('ludo.extratime.used'); game.syncGameStateServVars(); } const checkTurnSkip = function (game) { const gk = {key: game.getId()}; if (game.getTransient(GAME_PROPS.IS_TURN_SKIPPED) && Date.now() >= _getGameProp(game, GAME_PROPS.NEXT_TURN_TS)) { logger.info(gk, 'Proceeding Skipping turn'); game.incrPluginStats('ludo.moveskip.count'); game.addTransient(GAME_PROPS.IS_TURN_SKIPPED, false); checkMoveTurnAndEndGame(game) } } module.exports = step;