Skip to content

Commit

Permalink
Merge branch 'move-mn-phase'
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbradd authored May 2, 2022
2 parents a131ed6 + 987465b commit dbe582b
Show file tree
Hide file tree
Showing 49 changed files with 4,859 additions and 107 deletions.
635 changes: 619 additions & 16 deletions src/main/java/it/polimi/ingsw/server/model/ActionPhase.java

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion src/main/java/it/polimi/ingsw/server/model/BlockCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
import it.polimi.ingsw.server.model.enums.CharacterType;

/**
* STUB
* Class for representing a Block card.
*
* @author Alexandru Gabriel Bradatan
*/
class BlockCard {
/**
* The {@link CharacterType} of the Character that owns this card
*/
private final CharacterType owner;

/**
* Creates a new card owned by the given {@link CharacterType}
*
* @param owner the {@link CharacterType} of the owner of the card
* @throws IllegalArgumentException if {@code owner} is null
*/
BlockCard(CharacterType owner) {
if (owner == null) throw new IllegalArgumentException("owner shouldn't be null");
this.owner = owner;
}

/**
* Getter for this card's owner's {@link CharacterType}.
*
* @return card's owner's {@link CharacterType}.
*/
public CharacterType getOwner() {
return owner;
}
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/it/polimi/ingsw/server/model/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,15 @@ public Hall getHall() {

// Coins management

/**
* Returns the number of coins on this Board
*
* @return the number of coins on this Board
*/
public int getCoins() {
return coins;
}

/**
* The player spends {@code num_coins} coins. This method then returns a new Board instance with the updated
* internal state
Expand Down
102 changes: 102 additions & 0 deletions src/main/java/it/polimi/ingsw/server/model/CentaurAndKnight.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package it.polimi.ingsw.server.model;

import it.polimi.ingsw.server.model.enums.CharacterType;
import it.polimi.ingsw.server.model.exceptions.InvalidCharacterParameterException;

import java.util.Objects;

/**
* Represents the Centaur character card.
*
* @author Alexandru Gabriel Bradatan
*/
class CentaurAndKnight extends Character {
private final Behaviour behaviour;

/**
* Creates a new CentaurAndKnight card. If {@code behaviour} is {@link Behaviour#CENTAUR} the card will
* act as a Centaur card. Otherwise, it will act a Knight card.
*
* @param behaviour an enum describing what this card will act as
*/
CentaurAndKnight(Behaviour behaviour) {
super(behaviour == Behaviour.CENTAUR ? CharacterType.CENTAUR : CharacterType.KNIGHT);
this.behaviour = behaviour;
}

/**
* Returns a shallow copy of the given card
*
* @param old the Centaur to copy
* @throws IllegalArgumentException if {@code old} is null
*/
private CentaurAndKnight(CentaurAndKnight old) {
super(old);
this.behaviour = old.behaviour;
}

/**
* Abstract method that returns a shallow copy of the current object.
*
* @return returns a shallow copy of the current object.
*/
@Override
Character shallowCopy() {
return new CentaurAndKnight(this);
}

/**
* If acting as Centaur: Ignore the additional influence of towers during influence calculation. This effect requires no steps.
* If acting as Knight: Ignore the additional influence of towers during influence calculation. This effect requires no steps.
*
* @param phase the {@link ActionPhase} the card's effect has been called from
* @param steps an array of {@link CharacterStep} configuring the effect
* @return a Tuple containing the updated ActionPhase and the updated Character
* @throws IllegalArgumentException if {@code phase} or {@code steps} or are null
* @throws InvalidCharacterParameterException if any of the parameters in {@code steps} is formatted incorrectly
*/
@Override
Tuple<ActionPhase, Character> doEffect(ActionPhase phase, CharacterStep[] steps) throws InvalidCharacterParameterException {
return super.doEffect(phase, steps)
.map(t -> {
ActionPhase newPhase = t.getFirst();
Player p = newPhase.getCurrentPlayer();
CentaurAndKnight c = (CentaurAndKnight) t.getSecond();
if (c.behaviour == Behaviour.CENTAUR) {
newPhase = newPhase.setInfluenceCalculator(
new IgnoreTowersInfluenceDecorator(newPhase.getInfluenceCalculator()));
} else {
newPhase = newPhase.setInfluenceCalculator(
new ExtraPointsInfluenceDecorator(newPhase.getInfluenceCalculator(), p, 2));
}
return new Tuple<>(newPhase, c);
});
}

/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
CentaurAndKnight that = (CentaurAndKnight) o;
return behaviour == that.behaviour;
}

/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), behaviour);
}

/**
* Enum for signaling what this card will act as
*/
public enum Behaviour {
CENTAUR, KNIGHT
}
}
176 changes: 166 additions & 10 deletions src/main/java/it/polimi/ingsw/server/model/Character.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,187 @@
package it.polimi.ingsw.server.model;

import it.polimi.ingsw.server.model.enums.CharacterType;
import it.polimi.ingsw.server.model.exceptions.InvalidCharacterParameterException;

import java.util.Objects;

/**
* Represents an abstract character card. Each card has one "character", a cost that goes up by 1 after the first
* use and two hooks into respectively the {@link PreparePhase} and {@link ActionPhase} of the game. This base class has
* only default implementations that either do nothing, or throw an exception. Please see all subclasses for different
* card effects.
*
* @author Alexandru Gabriel Bradatan
* @see ActionPhase
* @see PreparePhase
*/
abstract class Character {
private final CharacterType type;
/**
* This card's character. Represented as a {@link CharacterType} enum.
*/
private final CharacterType characterType;

/**
* The base cost of the card.
*/
private final int initialCost;

/**
* Indicates if a card has been used at least once.
*/
private boolean used;

/**
* Base constructor. Sets up only the card's initial cost and character
*
* @param characterType this card's character
* @throws IllegalArgumentException if {@code characterType} is null
*/
Character(CharacterType characterType) {
if (characterType == null) throw new IllegalArgumentException("characterType shouldn't be null");
this.characterType = characterType;
this.initialCost = characterType.getInitialCost();
used = false;
}

Character(CharacterType type) {
this.type = type;
/**
* Returns a copy of the passed Character
*
* @param old Character to copy
* @throws IllegalArgumentException if {@code old} is null
*/
Character(Character old) {
if (old == null) throw new IllegalArgumentException("old shouldn't be null");
this.characterType = old.characterType;
this.initialCost = this.characterType.getInitialCost();
this.used = old.used;
}

/**
* Abstract method that returns a shallow copy of the current object.
*
* @return returns a shallow copy of the current object.
*/
abstract Character shallowCopy();

/**
* Getter for this card's CharacterType
*
* @return this card's CharacterType
*/
CharacterType getCharacterType() {
return type;
return characterType;
}

/**
* Getter for this card's actual cost. This means that this will return the card's initial cost if this card hasn't
* been used before and the initial cos +1 otherwise.
*
* @return this card's actual cost
*/
int getCost() {
return type.getInitialCost();
return used ? initialCost + 1 : initialCost;
}

Tuple<ActionPhase, Character> doEffect(ActionPhase phase, CharacterStep[] params) {
/**
* Default implementation for the {@link PreparePhase} hook. This implementation only checks for nullity, so if
* subclasses want to not rewrite it themselves, they can call this implementation.
*
* @param phase the {@link PreparePhase} the card's hook has been called from
* @return a Tuple containing the updated PreparePhase and the updated Character
* @throws IllegalArgumentException if {@code phase} is null
*/
Tuple<PreparePhase, Character> doPrepare(PreparePhase phase) {
if (phase == null) throw new IllegalArgumentException("phase shouldn't be null");
return new Tuple<>(phase, this);
}

Character pushBlock(BlockCard c) {
throw new UnsupportedOperationException();
/**
* Default implementation for the card's effect. This implementation only marks the card as used and checks for
* nullity of parameters. All subclasses should call this implementation if they are overriding this method.
* <p>
* The number of steps and the parameters of each are detailed in each subclass. To signal that the player has not
* provided any steps, an empty array should be passed.
*
* @param phase the {@link ActionPhase} the card's effect has been called from
* @param steps an array of {@link CharacterStep} configuring the effect
* @return a Tuple containing the updated ActionPhase and the updated Character
* @throws IllegalArgumentException if {@code phase} or {@code steps} or are null
* @throws InvalidCharacterParameterException if any of the parameters in {@code steps} is formatted incorrectly
*/
Tuple<ActionPhase, Character> doEffect(ActionPhase phase, CharacterStep[] steps) throws InvalidCharacterParameterException {
if (phase == null) throw new IllegalArgumentException("phase shouldn't be null");
if (steps == null) throw new IllegalArgumentException("steps shouldn't be null");
Character t = this.shallowCopy();
t.used = true;
return new Tuple<>(phase, t);
}

/**
* Helper for validating parameters in subclasses: check for nullity and length of the step array
*
* @param phase the ActionPhase to check
* @param steps the CharacterStep array to check
* @param minimumSteps the minimum number of steps that {@code steps} should have
* @throws IllegalArgumentException in case of nullity
* @throws InvalidCharacterParameterException if the length of {@code steps} is less than {@code minimumSteps}
*/
void checkEffectParameters(ActionPhase phase, CharacterStep[] steps, int minimumSteps) throws InvalidCharacterParameterException {
if (phase == null) throw new IllegalArgumentException("phase shouldn't be null");
if (steps == null) throw new IllegalArgumentException("steps shouldn't be null");
if (steps.length < minimumSteps)
throw new InvalidCharacterParameterException("Too few parameters: at least 1 expected");
}

/**
* Returns the number of {@link BlockCard} available on this card. This implementation always returns 0 since
* block related methods always throw an exception.
*
* @return the number of {@link BlockCard} available on this card
*/
int getNumOfBlocks() {
return 0;
}

/**
* Adds the given {@link BlockCard} to the internal store. This implementation of the method throws a
* {@link UnsupportedOperationException}.
*
* @param block the {@link BlockCard} to add to the store
* @return the updated Character
* @throws UnsupportedOperationException always
*/
Character pushBlock(BlockCard block) {
throw new UnsupportedOperationException("this card doesn't receive blocks");
}

/**
* Pops a {@link BlockCard} from the internal store and returns it. This implementation of the method throws a
* {@link UnsupportedOperationException}.
*
* @return a Tuple containing the new Character and a BlockCard.
* @throws UnsupportedOperationException always
*/
Tuple<Character, BlockCard> popBlock() {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("this card doesn't produce blocks");
}

/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Character character = (Character) o;
return initialCost == character.initialCost && used == character.used && characterType == character.characterType;
}

/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hash(characterType, initialCost, used);
}
}
}
Loading

0 comments on commit dbe582b

Please sign in to comment.