Skip to content

Commit

Permalink
feat(interactable-players): interactable players with interactions fo…
Browse files Browse the repository at this point in the history
…r current game play (#631)
  • Loading branch information
antoinezanardi committed Nov 15, 2023
1 parent b4b530e commit e230b3a
Show file tree
Hide file tree
Showing 61 changed files with 65,642 additions and 55,051 deletions.
19 changes: 19 additions & 0 deletions src/modules/game/enums/player.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,27 @@ enum PlayerDeathCauses {
DISEASE = "disease",
}

enum PlayerInteractionTypes {
EAT = "eat",
LOOK = "look",
CHARM = "charm",
GIVE_LIFE_POTION = "give-life-potion",
GIVE_DEATH_POTION = "give-death-potion",
SHOOT = "shoot",
PROTECT = "protect",
MARK = "mark",
VOTE = "vote",
CHOOSE_AS_MODEL = "choose-as-model",
CHOOSE_AS_SHERIFF = "choose-as-sheriff",
SNIFF = "sniff",
BAN_VOTING = "ban-voting",
TRANSFER_SHERIFF_ROLE = "transfer-sheriff-role",
SENTENCE_TO_DEATH = "sentence-to-death",
}

export {
PlayerGroups,
PlayerAttributeNames,
PlayerDeathCauses,
PlayerInteractionTypes,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { plainToInstance } from "class-transformer";

import { GamePlayEligibleTargetsBoundaries } from "@/modules/game/schemas/game-play/game-play-eligible-targets/game-play-eligible-targets-boundaries/game-play-eligible-targets-boundaries.schema";

import { toJSON } from "@/shared/misc/helpers/object.helper";
import { PLAIN_TO_INSTANCE_DEFAULT_OPTIONS } from "@/shared/validation/constants/validation.constant";

function createGamePlayEligibleTargetsBoundaries(gamePlayEligibleTargetsBoundaries: GamePlayEligibleTargetsBoundaries): GamePlayEligibleTargetsBoundaries {
return plainToInstance(GamePlayEligibleTargetsBoundaries, toJSON(gamePlayEligibleTargetsBoundaries), PLAIN_TO_INSTANCE_DEFAULT_OPTIONS);
}

export { createGamePlayEligibleTargetsBoundaries };
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { plainToInstance } from "class-transformer";

import { GamePlayEligibleTargets } from "@/modules/game/schemas/game-play/game-play-eligible-targets/game-play-eligible-targets.schema";

import { toJSON } from "@/shared/misc/helpers/object.helper";
import { PLAIN_TO_INSTANCE_DEFAULT_OPTIONS } from "@/shared/validation/constants/validation.constant";

function createGamePlayEligibleTargets(gamePlayEligibleTargets: GamePlayEligibleTargets): GamePlayEligibleTargets {
return plainToInstance(GamePlayEligibleTargets, gamePlayEligibleTargets, PLAIN_TO_INSTANCE_DEFAULT_OPTIONS);
return plainToInstance(GamePlayEligibleTargets, toJSON(gamePlayEligibleTargets), PLAIN_TO_INSTANCE_DEFAULT_OPTIONS);
}

export { createGamePlayEligibleTargets };
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { plainToInstance } from "class-transformer";

import { InteractablePlayer } from "@/modules/game/schemas/game-play/game-play-eligible-targets/interactable-player/interactable-player.schema";

import { toJSON } from "@/shared/misc/helpers/object.helper";
import { PLAIN_TO_INSTANCE_DEFAULT_OPTIONS } from "@/shared/validation/constants/validation.constant";

function createInteractablePlayer(interactablePlayer: InteractablePlayer): InteractablePlayer {
return plainToInstance(InteractablePlayer, toJSON(interactablePlayer), PLAIN_TO_INSTANCE_DEFAULT_OPTIONS);
}

export { createInteractablePlayer };
12 changes: 12 additions & 0 deletions src/modules/game/helpers/game-play/game-play.helper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { plainToInstance } from "class-transformer";
import type { Types } from "mongoose";

import type { GameWithCurrentPlay } from "@/modules/game/types/game-with-current-play";
import { GAME_PLAYS_PRIORITY_LIST } from "@/modules/game/constants/game.constant";
import { MakeGamePlayTargetWithRelationsDto } from "@/modules/game/dto/make-game-play/make-game-play-target/make-game-play-target-with-relations.dto";
import { MakeGamePlayVoteWithRelationsDto } from "@/modules/game/dto/make-game-play/make-game-play-vote/make-game-play-vote-with-relations.dto";
import { MakeGamePlayWithRelationsDto } from "@/modules/game/dto/make-game-play/make-game-play-with-relations.dto";
import type { MakeGamePlayDto } from "@/modules/game/dto/make-game-play/make-game-play.dto";
import type { PlayerInteractionTypes } from "@/modules/game/enums/player.enum";
import { PlayerAttributeNames, PlayerGroups } from "@/modules/game/enums/player.enum";
import { getAdditionalCardWithId, getGroupOfPlayers, getPlayerWithId } from "@/modules/game/helpers/game.helper";
import { doesPlayerHaveActiveAttributeWithName } from "@/modules/game/helpers/player/player-attribute/player-attribute.helper";
Expand Down Expand Up @@ -92,6 +95,14 @@ function canSurvivorsVote(game: Game): boolean {
return survivors.some(player => !doesPlayerHaveActiveAttributeWithName(player, PlayerAttributeNames.CANT_VOTE, game));
}

function isPlayerInteractableWithInteractionType(playerId: Types.ObjectId, interactionType: PlayerInteractionTypes, game: GameWithCurrentPlay): boolean {
const { eligibleTargets } = game.currentPlay;
return !!eligibleTargets?.interactablePlayers?.find(({ player, interactions }) => {
const doesPlayerHaveInteraction = interactions.find(({ type }) => type === interactionType);
return player._id.equals(playerId) && doesPlayerHaveInteraction !== undefined;
});
}

export {
getVotesWithRelationsFromMakeGamePlayDto,
getTargetsWithRelationsFromMakeGamePlayDto,
Expand All @@ -100,4 +111,5 @@ export {
findPlayPriorityIndex,
areGamePlaysEqual,
canSurvivorsVote,
isPlayerInteractableWithInteractionType,
};
15 changes: 12 additions & 3 deletions src/modules/game/helpers/game.helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Types } from "mongoose";

import { VOTE_ACTIONS } from "@/modules/game/constants/game-play/game-play.constant";
import type { CreateGamePlayerDto } from "@/modules/game/dto/create-game/create-game-player/create-game-player.dto";
import type { CreateGameDto } from "@/modules/game/dto/create-game/create-game.dto";
import { GamePlayActions } from "@/modules/game/enums/game-play.enum";
Expand Down Expand Up @@ -157,15 +158,14 @@ function getNearestAliveNeighborInSortedPlayers(seekingNeighborPlayer: Player, s
const seekingNeighborPlayerIndex = sortedPlayers.findIndex(({ _id }) => _id.equals(seekingNeighborPlayer._id));
let currentIndex = seekingNeighborPlayerIndex + indexHeading;
let count = 0;
while (count < sortedPlayers.length) {
while (count < sortedPlayers.length - 1) {
if (currentIndex < 0) {
currentIndex = sortedPlayers.length - 1;
} else if (currentIndex >= sortedPlayers.length) {
currentIndex = 0;
}
const checkingNeighbor = sortedPlayers[currentIndex];
if (checkingNeighbor.position !== seekingNeighborPlayer.position && checkingNeighbor.isAlive &&
(options.playerSide === undefined || checkingNeighbor.side.current === options.playerSide)) {
if (checkingNeighbor.isAlive && (options.playerSide === undefined || checkingNeighbor.side.current === options.playerSide)) {
return checkingNeighbor;
}
currentIndex += indexHeading;
Expand All @@ -180,9 +180,14 @@ function getNearestAliveNeighbor(playerId: Types.ObjectId, game: Game, options:
return getNearestAliveNeighborInSortedPlayers(player, sortedPlayers, options);
}

function getAllowedToVotePlayers(game: Game): Player[] {
return game.players.filter(player => player.isAlive && !doesPlayerHaveActiveAttributeWithName(player, PlayerAttributeNames.CANT_VOTE, game));
}

function getExpectedPlayersToPlay(game: Game): Player[] {
const { currentPlay } = game;
const mustIncludeDeadPlayersGamePlayActions = [GamePlayActions.SHOOT, GamePlayActions.BAN_VOTING, GamePlayActions.DELEGATE];
const voteActions: GamePlayActions[] = [...VOTE_ACTIONS];
let expectedPlayersToPlay: Player[] = [];
if (currentPlay === null) {
throw createNoCurrentGamePlayUnexpectedException("getExpectedPlayersToPlay", { gameId: game._id });
Expand All @@ -197,6 +202,9 @@ function getExpectedPlayersToPlay(game: Game): Player[] {
if (!mustIncludeDeadPlayersGamePlayActions.includes(currentPlay.action)) {
expectedPlayersToPlay = expectedPlayersToPlay.filter(player => player.isAlive);
}
if (voteActions.includes(currentPlay.action)) {
expectedPlayersToPlay = expectedPlayersToPlay.filter(player => !doesPlayerHaveActiveAttributeWithName(player, PlayerAttributeNames.CANT_VOTE, game));
}
return expectedPlayersToPlay.map(player => createPlayer(player));
}

Expand Down Expand Up @@ -228,5 +236,6 @@ export {
getNonexistentPlayer,
getFoxSniffedPlayers,
getNearestAliveNeighbor,
getAllowedToVotePlayers,
getExpectedPlayersToPlay,
};

0 comments on commit e230b3a

Please sign in to comment.