Skip to content

Commit

Permalink
Merge pull request #86 from Front-znad-zatoki/feature/#68-implement-p…
Browse files Browse the repository at this point in the history
…rocess-game-2

Feature/#68 implement process game 2
  • Loading branch information
Enessetere authored Feb 4, 2021
2 parents 93ae695 + cc106cd commit ec39929
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 49 deletions.
100 changes: 56 additions & 44 deletions src/app/GameController.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,77 @@
// import { time } from 'console';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { Player } from '../Player';
import { BreedProcessor } from './BreedProcessor';
import { Bank } from './logic/Bank';
import { Timer } from './Timer';
import { GameProcessor } from './logic/GameProcessor';
import { View } from './View';
import { Game } from './logic/Game';
import { defaultGameConfiguration } from './logic/defaultGameConfiguration';

export class GameController {
private currentPlayer: Player | undefined;
private player: Player | undefined;
private timer: Timer;
private breedProcessor: BreedProcessor;
private game: Game;
private gameProcessor: GameProcessor;
constructor(private view: View) {
this.timer = new Timer();
this.breedProcessor = new BreedProcessor(new Bank());
this.game = new Game(defaultGameConfiguration);
this.gameProcessor = new GameProcessor(this.game);
}

get theCurrentPlayer(): Player {
return this.currentPlayer as Player;
get theGame(): Game {
return this.game;
}

get theTimer(): Timer {
return this.timer;
/**
* Starts the turn for the current player.
* Displays alert when the time is over.
* Updates the remaining time on the View.
*/
startTurn(): void {
this.gameProcessor.startTurn(
(currentPlayer) => {
this.view.displayAlert(currentPlayer?.theName as string);
},
(remainingTime) => {
this.view.updateRemainingTime(remainingTime);
},
);
}

startTurn(): void {
this.timer.countdown();
const turnTimer = setInterval(() => {
if (!this.timer.running) {
clearInterval(turnTimer);
if (Math.ceil(this.timer.theTurnTimeLeft) === 0) {
this.view.displayAlert(
this.currentPlayer?.theName as string,
);
this.nextPlayer();
this.startTurn();
}
}
this.view.updateRemainingTime(
Math.round(this.timer.theTurnTimeLeft),
);
}, 10);
stopTurn(): void {
this.gameProcessor.stopTurn();
}

breed(): [AnimalNames, AnimalNames] | undefined {
if (this.timer.theTurnTimeLeft === 0) {
return;
/**
* Executes trade proposed by the player and checks win condition.
* If player wins the game after the trade, stops the timer and tells the View to display the WinModal.
* @param offer made by the player
* @param target desired by the player
* @returns true if the trade was sucessful, false otherwise
*/
trade(
offer: [AnimalNames, number],
target: [AnimalNames, number],
): boolean {
const tradeResult = this.gameProcessor.trade(offer, target);
if (this.gameProcessor.checkWin()) {
this.gameProcessor.stopTurn();
this.view.displayWinModal(this.game.theCurrentPlayer);
}
const rollResult = this.breedProcessor.processBreedPhase(
this.currentPlayer as Player,
);
return rollResult;
return tradeResult;
}

stopTurn(): void {
this.timer.resetTurn();
/**
* Rolls the dice for the player and updates their Herd.
* If player wins the game after the breed, stops the timer and tells the View to display the WinModal.
*/
breed(): [AnimalNames, AnimalNames] | undefined {
const diceResult = this.gameProcessor.breed();
if (this.gameProcessor.checkWin()) {
this.gameProcessor.stopTurn();
this.view.displayWinModal(this.game.theCurrentPlayer);
}
return diceResult;
}

/**
* Sets the current player to the next player in order.
*/
nextPlayer(): void {
//TODO multiplayer logic
this.currentPlayer = this.player;
this.timer.resetTurn();
this.gameProcessor.nextPlayer();
}
}
15 changes: 10 additions & 5 deletions src/app/View.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Render } from './utils/Render';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { GameController } from './GameController';
import { Game } from './logic/Game';
import { defaultGameConfiguration } from './logic/defaultGameConfiguration';
import { Player } from '../Player';
import { WinModal } from './components/WinModal';

export class View {
renderMenuView(): void {
Expand Down Expand Up @@ -60,8 +60,6 @@ export class View {
: playersChosenAvatarPath;

Render.removeAllChildren('#sf-app');
new Game(defaultGameConfiguration);

this.renderGameView(inputValue, playersChosenAvatarPath);
};
startGameButton.addEventListener('click', handleClick);
Expand Down Expand Up @@ -116,7 +114,7 @@ export class View {
rollADiceButton.addEventListener('click', () => {
const rollResult = gameController.breed();
herdView.innerText = JSON.stringify(
gameController.theCurrentPlayer.theHerd.theAnimals.map(
gameController.theGame.theCurrentPlayer.theHerd.theAnimals.map(
([animal, count]) => [animal.theName, count],
),
);
Expand Down Expand Up @@ -161,6 +159,13 @@ export class View {
alert(`${name}'s turn has passed!`);
}

displayWinModal(player: Player): void {
const modal = new WinModal();
modal.create(player);
modal.addButton();
Render.render('#sf-app', modal.modal);
}

handleTrade(): void {
console.log('handle trade');
}
Expand Down
11 changes: 11 additions & 0 deletions src/app/logic/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class Game {
timer: Timer;
breedProcessor: BreedProcessor;
trade: Trade;
private currentPlayerNumber: number;
constructor({
mode,
roundTimeInSeconds,
Expand Down Expand Up @@ -57,6 +58,7 @@ export class Game {
this.playersHerdConfig,
),
);
this.currentPlayerNumber = 0;
this.bank = new Bank(this.banksHerdConfig);
// TODO: GET DICE DATA FROM CONFIG AFTER/ IF DICE REFACTOR
// TODO: CHECK IF NEEDED SINCE THEY ARE CALLED IN BREEDPROCESSOR
Expand All @@ -67,6 +69,11 @@ export class Game {
this.trade = new Trade(this.bank);
}

nextPlayer(): void {
this.currentPlayerNumber =
(this.currentPlayerNumber + 1) % this.players.length;
}

get theMode(): GameModes {
return this.mode;
}
Expand All @@ -75,6 +82,10 @@ export class Game {
return this.players;
}

get theCurrentPlayer(): Player {
return this.players[this.currentPlayerNumber];
}

get theBank(): Bank {
return this.bank;
}
Expand Down
114 changes: 114 additions & 0 deletions src/app/logic/GameProcessor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { AnimalNames } from '~src/Enums/AnimalNamesEnum';
import { Player } from '~src/Player';
import { Game } from './Game';

export class GameProcessor {
constructor(private game: Game) {}

/**
* Starts the timer for current players turn.
* When the time is over, resets the timer, sets current player to the next player and starts the timer.
* @param turnTimeOverCallback to be executed when the time is over
* @param updateRemainingTimeCallback to be executed when the remaining time changes
*/
startTurn(
turnTimeOverCallback: (currentPlayer: Player) => void,
updateRemainingTimeCallback: (remainingTime: number) => void,
): void {
this.game.theTimer.countdown();
const turnTimer = setInterval(() => {
if (!this.game.theTimer.running) {
clearInterval(turnTimer);
if (Math.ceil(this.game.theTimer.theTurnTimeLeft) === 0) {
turnTimeOverCallback(this.game.theCurrentPlayer);

this.nextPlayer();
this.startTurn(
turnTimeOverCallback,
updateRemainingTimeCallback,
);
}
}
updateRemainingTimeCallback(
Math.round(this.game.theTimer.theTurnTimeLeft),
);
}, 10);
}

/**
* Stops the timer for the current player.
*/
stopTurn(): void {
this.game.theTimer.resetTurn();
}

/**
* Executes trade proposed by the player and checks win condition.
* @param offer made by the player
* @param target desired by the player
* @returns true if the trade was sucessful, false if the trade was not sucessful or the player run out of time
*/
trade(
offer: [AnimalNames, number],
target: [AnimalNames, number],
): boolean {
if (!this.hasTimeLeft()) {
return false;
}
const tradeResult = this.game.theTrade.processOffer(
offer,
this.game.theCurrentPlayer,
target,
);
return tradeResult;
}

/**
* @returns true if current player wins the game, false otherwise
*/
checkWin(): boolean {
const animalsRequiredToWin: AnimalNames[] = [
AnimalNames.RABBIT,
AnimalNames.SHEEP,
AnimalNames.PIG,
AnimalNames.COW,
AnimalNames.HORSE,
];
for (const animal in animalsRequiredToWin) {
if (
this.game.theCurrentPlayer.theHerd.getAnimalNumber(
animal as AnimalNames,
) === 0
) {
return false;
}
}
return true;
}

/**
* Rolls the dice for the player and updates their Herd.
* @returns the result of the current players roll
*/
breed(): [AnimalNames, AnimalNames] | undefined {
if (!this.hasTimeLeft()) {
return;
}
const rollResult = this.game.theBreedProcessor.processBreedPhase(
this.game.theCurrentPlayer,
);
return rollResult;
}

/**
* Sets the current player to the next player in order and resets the timer.
*/
nextPlayer(): void {
this.game.nextPlayer();
this.game.theTimer.resetTurn();
}

private hasTimeLeft(): boolean {
return this.game.theTimer.theTurnTimeLeft === 0;
}
}

0 comments on commit ec39929

Please sign in to comment.