Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#115-AddPlayerPanel-styling
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianBabinski1 committed Feb 15, 2021
2 parents 20704dd + 5687055 commit 9f1666c
Show file tree
Hide file tree
Showing 50 changed files with 837 additions and 380 deletions.
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles/App.scss" />
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@700&display=swap" rel="stylesheet">
<link rel="icon" type="image/png" href="./static/images/ui/favicon.png" />
</head>
<body>
Expand Down
37 changes: 37 additions & 0 deletions src/Animals/Predator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { AnimalRoles } from '../Enums/AnimalRolesEnum';
import { AttackHerdInterface } from '../Interfaces/AttackHerdInterface';
import { Animal } from './Animal';

export class Predator extends Animal implements AttackHerdInterface {
protected _kills: AnimalNames[];
protected _isChasedAwayBy: AnimalNames;
protected _exclamation: string;
constructor(
name: AnimalNames,
imagePath: string,
roles: AnimalRoles = AnimalRoles.PREDATOR,
kills: AnimalNames[],
isChasedAwayBy: AnimalNames,
exclamation: string,
) {
super(name, imagePath, undefined, roles);
this._kills = kills;
this._isChasedAwayBy = isChasedAwayBy;
this._exclamation = exclamation;
}

get kills(): AnimalNames[] {
return this._kills;
}
get isChasedAwayBy(): AnimalNames {
return this._isChasedAwayBy;
}
get exclamation(): string {
return this._exclamation;
}

attackHerd(): string {
return this._exclamation;
}
}
37 changes: 37 additions & 0 deletions src/Animals/Protector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { AnimalRoles } from '../Enums/AnimalRolesEnum';
import { ProtectHerdInterface } from '../Interfaces/ProtectHerdInterface';
import { Animal, Value } from './Animal';

export class Protector
extends Animal
implements ProtectHerdInterface {
protected _chasesAway: AnimalNames;
protected _exclamation: string;
constructor(
name: AnimalNames,
imagePath: string,
role: AnimalRoles = AnimalRoles.PREDATOR,
value: Value,
chasesAway: AnimalNames,
exclamation: string,
) {
super(name, imagePath, value, role);
this._chasesAway = chasesAway;
this._exclamation = exclamation;
}

get chasesAway(): AnimalNames {
if (!this._chasesAway) throw new Error('nothing to chase away');
return this._chasesAway;
}
get exclamation(): string {
if (!this._exclamation) return '';
return this._exclamation;
}

protectHerd(): string {
if (!this._exclamation) return '';
return this._exclamation;
}
}
2 changes: 1 addition & 1 deletion src/Interfaces/AttackHerdInterface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface AttackHerdInterface {
// TODO: tweak when herd is ready
// TODO: DEFINE THE ACTION FOR ATTACK
attackHerd(): string;
}
3 changes: 2 additions & 1 deletion src/Interfaces/GameConfigInterface.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { GameModes } from '../Enums/GameModeEnums';
import { LivestockConfigInterface } from './LivestockConfigInterface';
import { PlayerDTO } from './PlayerDTOInterface';
import { PredatorsConfigInterface } from './PredatorsConfigInterface';
import { ProtectorsConfigInterface } from './ProtectorsConfigInterface';

export interface GameConfigInterface {
mode: GameModes;
roundTimeInSeconds: number;
totalGameTimeInSeconds?: number;
playersConfig: { name: string; path: string; color: string }[];
playersConfig: PlayerDTO[];
livestockConfig: LivestockConfigInterface[];
protectorsConfig: ProtectorsConfigInterface[];
predatorsConfig: PredatorsConfigInterface[];
Expand Down
1 change: 1 addition & 0 deletions src/Interfaces/HerdConfigInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export interface HerdConfigInterface {
path: string;
inStock: number;
chasesAway?: AnimalNames;
exclamation?: string;
}
5 changes: 4 additions & 1 deletion src/Interfaces/PredatorsConfigInterface.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { AnimalRoles } from '../Enums/AnimalRolesEnum';
import { AnimalNames } from '../Enums/AnimalNamesEnum';

export interface PredatorsConfigInterface {
name: AnimalNames;
path: string;
roles: AnimalRoles;
kills: AnimalNames[];
isChasedAwayBy: AnimalNames[];
isChasedAwayBy: AnimalNames;
exclamation: string;
dice?: { diceNumber: number; probability: number }[];
}
1 change: 1 addition & 0 deletions src/Interfaces/ProtectorsConfigInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import { LivestockConfigInterface } from './LivestockConfigInterface';
export interface ProtectorsConfigInterface
extends LivestockConfigInterface {
chasesAway: AnimalNames;
exclamation: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AnimalNames } from '../Enums/AnimalNamesEnum';

export interface GetRandomValue {
export interface RandomAnimalInterface {
getRandomValue(): AnimalNames;
}
6 changes: 3 additions & 3 deletions src/Player.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defaultPlayerHerdConfig } from './app/logic/defaultHerdConfig';
import { Herd } from './app/logic/Herd';
import { mockHerdConfig } from './app/logic/mockHerdConfig';
// import { mockHerdConfig } from './app/logic/defaultHerdConfig';
import { HerdConfigInterface } from './Interfaces/HerdConfigInterface';

export class Player {
Expand All @@ -8,12 +9,11 @@ export class Player {
protected herd: Herd;
protected color: string;

// TODO: set path to default avatar when it's available
constructor(
name: string,
avatar = 'path to default avatar',
color = 'green',
herdConfig: HerdConfigInterface[] = mockHerdConfig,
herdConfig: HerdConfigInterface[] = defaultPlayerHerdConfig,
) {
this.name = name;
this.herd = new Herd(herdConfig);
Expand Down
156 changes: 92 additions & 64 deletions src/app/BreedProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,83 @@
import { GetRandomValue } from '../Interfaces/DiceInterface';
import { FirstDice } from './FirstDice';
import { SecondDice } from './SecondDice';
import { RandomAnimalInterface } from '../Interfaces/RandomAnimalInterface';
import { Player } from '../Player';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { Fox } from '../Animals/Fox';
import { Wolf } from '../Animals/Wolf';
import { Herd } from './logic/Herd';
import { add, divide, floor, min } from 'lodash';
import { AnimalRoles } from '../Enums/AnimalRolesEnum';
import { add, divide, floor, min, remove } from 'lodash';
import { Bank } from './logic/Bank';
import { ConvertAnimalName } from './utils/ConvertAnimalName';
import { PredatorsConfigInterface } from '../Interfaces/PredatorsConfigInterface';
import { GameModes } from '../Enums/GameModeEnums';
import { Predator } from '../../src/Animals/Predator';

export type RollResult = {
rollResult: AnimalNames[];
gain: [AnimalNames, number][];
};

export class BreedProcessor {
randomResultInterfaceWolf: GetRandomValue;
randomResultInterfaceFox: GetRandomValue;
predators: Predator[];

constructor(private bank: Bank) {
this.randomResultInterfaceWolf = new SecondDice();
this.randomResultInterfaceFox = new FirstDice();
constructor(
private bank: Bank,
private firstDice: RandomAnimalInterface,
private secondDice: RandomAnimalInterface,
predatorConfig: PredatorsConfigInterface[],
private mode: GameModes,
) {
this.predators = predatorConfig.map(
({ name, path, roles, kills, isChasedAwayBy, exclamation }) => {
return new Predator(
name,
path,
roles,
kills,
isChasedAwayBy,
exclamation,
);
},
);
}

getPredatorByName(predatorName: AnimalNames): Predator {
const attackingPredator = this.predators.find(
(predator) => predator.theName === predatorName,
);
if (!attackingPredator) throw new Error('No such predator');
return attackingPredator;
}

processBreedPhase({ theHerd }: Player): RollResult {
const wolfDiceResult = this.randomResultInterfaceWolf.getRandomValue();
const foxDiceResult = this.randomResultInterfaceFox.getRandomValue();
const equalResult = foxDiceResult === wolfDiceResult;
const roll = [wolfDiceResult, foxDiceResult];
if (equalResult) {
const count = this.breedAnimals(foxDiceResult, theHerd, true);
return { rollResult: roll, gain: [[foxDiceResult, count]] };
const roll = [
this.firstDice.getRandomValue(),
this.secondDice.getRandomValue(),
];
const [firstDice, secondDice] = roll;
if (firstDice === secondDice) {
const count = this.breedAnimals(firstDice, theHerd, true);
return {
rollResult: roll,
gain: count ? [[firstDice, count]] : [],
};
}
const gain: [AnimalNames, number][] = [];
if (foxDiceResult === AnimalNames.FOX) {
const fox: Fox = ConvertAnimalName.toAnimalObject(
foxDiceResult,
) as Fox;
this.returnToBank(fox, theHerd);
theHerd.cullAnimals(fox);
} else {
gain.push([
foxDiceResult,
this.breedAnimals(foxDiceResult, theHerd),
]);
}
if (wolfDiceResult === AnimalNames.WOLF) {
const wolf = ConvertAnimalName.toAnimalObject(
wolfDiceResult,
) as Wolf;
this.returnToBank(wolf, theHerd);
theHerd.cullAnimals(wolf);
} else {
gain.push([
wolfDiceResult,
this.breedAnimals(wolfDiceResult, theHerd),
]);
}
roll
.filter((animal) => !this.isPredator(animal))
.forEach((animal) => {
const grow = this.breedAnimals(animal, theHerd);
if (grow) {
gain.push([animal, grow]);
}
});
roll
.filter((animal) => this.isPredator(animal))
.forEach((animal) => {
const predator = this.getPredatorByName(animal);
const isHerdCulled = this.returnToBank(predator, theHerd);
if (isHerdCulled && gain.length > 0) {
this.reduceGain(predator, gain);
}
predator.attackHerd();
theHerd.cullAnimals(predator, this.mode);
});
return { rollResult: roll, gain: gain };
}

Expand All @@ -83,35 +102,35 @@ export class BreedProcessor {
return herdGrow;
}

private returnToBank(predator: Wolf | Fox, herd: Herd): void {
if (predator instanceof Fox) {
if (herd.getAnimalNumber(AnimalNames.SMALL_DOG) > 0) {
this.bank.theHerd.addAnimalsToHerd(AnimalNames.SMALL_DOG, 1);
return;
}
const quantity = herd.getAnimalNumber(AnimalNames.RABBIT);
this.bank.theHerd.addAnimalsToHerd(
AnimalNames.RABBIT,
quantity,
);
return;
}
if (herd.getAnimalNumber(AnimalNames.BIG_DOG) > 0) {
this.bank.theHerd.addAnimalsToHerd(AnimalNames.BIG_DOG, 1);
return;
private isPredator(animal: AnimalNames): boolean {
return this.predators.some(({ theName }) => theName === animal);
}

private returnToBank(predator: Predator, herd: Herd): boolean {
const animalsToCull = predator.kills;
const protector = predator.isChasedAwayBy;
const hasProtector = herd.getAnimalNumber(protector);
const isDynamicMode = this.mode === GameModes.DYNAMIC;
const killsRabbits = animalsToCull.includes(AnimalNames.RABBIT);
if (hasProtector) {
this.bank.theHerd.addAnimalsToHerd(protector, 1);
return false;
}

herd.theAnimals
.filter(
([animal]) =>
animal.hasRole(AnimalRoles.LIVESTOCK) &&
animal.theName !== AnimalNames.HORSE,
.filter(([animal]) =>
animalsToCull.includes(animal.theName as AnimalNames),
)
.forEach(([animal, count]) =>
this.bank.theHerd.addAnimalsToHerd(
animal.theName as AnimalNames,
count,
),
);
if (isDynamicMode && killsRabbits) {
this.bank.theHerd.removeAnimalsFromHerd(AnimalNames.RABBIT, 1);
}
return true;
}

private calculateHerdGrow(
Expand All @@ -130,4 +149,13 @@ export class BreedProcessor {
);
return min([herdMaxGrow, bankContains]) as number;
}

private reduceGain(
predator: Predator,
animalsGain: [AnimalNames, number][],
): void {
remove(animalsGain, ([animal]) => {
return predator.kills.includes(animal);
});
}
}
28 changes: 23 additions & 5 deletions src/app/Dice.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import { GetRandomValue } from '../Interfaces/DiceInterface';
import { RandomAnimalInterface } from '../Interfaces/RandomAnimalInterface';
import { AnimalNames } from '../Enums/AnimalNamesEnum';
import { sample } from 'lodash';
import { sample, shuffle } from 'lodash';

export class Dice implements GetRandomValue {
constructor(private diceSides: AnimalNames[]) {}
export class Dice implements RandomAnimalInterface {
private dice: AnimalNames[] = [];

/**
* adds animals names to dice sides in quantity of probability
* @param animal accepts AnimalNames with desired animal on side
* @param probability accepts number with number of sides with this animal
*/
addSide(animal: AnimalNames, probability: number): void {
if (probability === 0) {
return;
}
this.dice.push(animal);
this.addSide(animal, probability - 1);
}

/**
* Returns random animal
*/
getRandomValue(): AnimalNames {
return sample(this.diceSides) as AnimalNames;
this.dice = shuffle(this.dice);
return sample(this.dice) as AnimalNames;
}
}
Loading

0 comments on commit 9f1666c

Please sign in to comment.