|
|
|
@ -1,18 +1,23 @@
|
|
|
|
|
package eu.jonahbauer.tichu.common.model;
|
|
|
|
|
|
|
|
|
|
import eu.jonahbauer.tichu.common.model.combinations.*;
|
|
|
|
|
import eu.jonahbauer.tichu.common.model.exceptions.InvalidCombinationException;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A type of combination.
|
|
|
|
|
*/
|
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
public enum CombinationType {
|
|
|
|
|
/**
|
|
|
|
|
* A single card, {@linkplain Card#isNormal() normal} or {@linkplain Card#isSpecial() special}. This is the
|
|
|
|
|
* correct {@code CombinationType} for playing the {@link Card#HOUND} or {@link Card#DRAGON}.
|
|
|
|
|
*/
|
|
|
|
|
SINGLE {
|
|
|
|
|
SINGLE(Single.class, Single::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG, Card.DRAGON, Card.HOUND);
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -24,7 +29,7 @@ public enum CombinationType {
|
|
|
|
|
* A pair, i.e. two {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value} or the
|
|
|
|
|
* {@link Card#PHOENIX} and a normal card.
|
|
|
|
|
*/
|
|
|
|
|
PAIR {
|
|
|
|
|
PAIR(Pair.class, Pair::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
|
|
|
|
|
private static final int[] INDICES = new int[] {0, 1};
|
|
|
|
|
|
|
|
|
@ -38,7 +43,7 @@ public enum CombinationType {
|
|
|
|
|
* A triple, i.e. three {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value}
|
|
|
|
|
* or the {@linkplain Card#PHOENIX} and two normal cards of the same value.
|
|
|
|
|
*/
|
|
|
|
|
TRIPLE {
|
|
|
|
|
TRIPLE(Triple.class, Triple::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
|
|
|
|
|
private static final int[] INDICES = new int[] {0, 1, 2};
|
|
|
|
|
|
|
|
|
@ -53,7 +58,7 @@ public enum CombinationType {
|
|
|
|
|
* @apiNote A list of cards representing a full house must have the triple at the first three indices and the pair
|
|
|
|
|
* at the last two. This prevents any ambiguity, e.g. when the full house consists of two pairs and the phoenix.
|
|
|
|
|
*/
|
|
|
|
|
FULL_HOUSE {
|
|
|
|
|
FULL_HOUSE(FullHouse.class, FullHouse::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
|
|
|
|
|
|
|
|
|
|
private static final int[] INDICES_TRIPLE = new int[] {0, 1, 2};
|
|
|
|
@ -72,7 +77,7 @@ public enum CombinationType {
|
|
|
|
|
* @apiNote A list of cards representing a sequence must be sorted by ascending value. This allows to distinguish
|
|
|
|
|
* between a sequence starting with the phoenix and a sequence ending with the phoenix.
|
|
|
|
|
*/
|
|
|
|
|
SEQUENCE {
|
|
|
|
|
SEQUENCE(SingleSequence.class, SingleSequence::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG);
|
|
|
|
|
|
|
|
|
|
private int getStartValue(@NotNull List<@NotNull Card> cards) {
|
|
|
|
@ -107,7 +112,7 @@ public enum CombinationType {
|
|
|
|
|
* @apiNote Although not strictly necessary, for consistency with {@link #SEQUENCE} a list of cards representing
|
|
|
|
|
* a sequence of pairs must be sorted by ascending value.
|
|
|
|
|
*/
|
|
|
|
|
PAIR_SEQUENCE {
|
|
|
|
|
PAIR_SEQUENCE(PairSequence.class, PairSequence::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = EnumSet.of(Card.PHOENIX);
|
|
|
|
|
|
|
|
|
|
private int getStartValue(@NotNull List<@NotNull Card> cards) {
|
|
|
|
@ -137,7 +142,7 @@ public enum CombinationType {
|
|
|
|
|
/**
|
|
|
|
|
* A bomb, i.e. four {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value}.
|
|
|
|
|
*/
|
|
|
|
|
BOMB {
|
|
|
|
|
BOMB(BombTuple.class, BombTuple::of) {
|
|
|
|
|
private static final int[] INDICES = new int[] {0, 1, 2, 3};
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = Collections.emptySet();
|
|
|
|
|
|
|
|
|
@ -154,7 +159,7 @@ public enum CombinationType {
|
|
|
|
|
* bomb sequence must be sorted by ascending value.
|
|
|
|
|
* @apiNote
|
|
|
|
|
*/
|
|
|
|
|
BOMB_SEQUENCE {
|
|
|
|
|
BOMB_SEQUENCE(BombSequence.class, BombSequence::of) {
|
|
|
|
|
private static final Set<Card> SPECIAL_CARDS = Collections.emptySet();
|
|
|
|
|
|
|
|
|
|
private int getStartValue(@NotNull List<@NotNull Card> cards) {
|
|
|
|
@ -179,14 +184,48 @@ public enum CombinationType {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private final @NotNull Class<? extends Combination> combinationClass;
|
|
|
|
|
private final @NotNull Function<@NotNull List<@NotNull Card>, @NotNull Combination> factory;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks whether the given cards form a valid combination of this type. See the documentation of a specific
|
|
|
|
|
* {@code CombinationType} for more information on what cards form a combination of that particular type.
|
|
|
|
|
* @param cards a list of cards
|
|
|
|
|
* @return {@code true} if the cards form a valid combination of this type.
|
|
|
|
|
* @throws NullPointerException if the list or any of its elements are {@code null}.
|
|
|
|
|
*/
|
|
|
|
|
public abstract boolean check(@NotNull List<@NotNull Card> cards);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new combination of this type consisting of the given cards.
|
|
|
|
|
* @param cards a list of cards forming a {@linkplain #check(List) valid} combination
|
|
|
|
|
* @return a new combination.
|
|
|
|
|
* @throws InvalidCombinationException if the given cards do not form a valid combination.
|
|
|
|
|
* @throws NullPointerException if the list or any of its elements are {@code null}.
|
|
|
|
|
*/
|
|
|
|
|
public @NotNull Combination of(@NotNull List<@NotNull Card> cards) {
|
|
|
|
|
return factory.apply(cards);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new combination of this type consisting of the given cards.
|
|
|
|
|
* @param cards a list of cards forming a {@linkplain #check(List) valid} combination
|
|
|
|
|
* @return a new combination.
|
|
|
|
|
* @throws InvalidCombinationException if the given cards do not form a valid combination.
|
|
|
|
|
* @throws NullPointerException if the list or any of its elements are {@code null}.
|
|
|
|
|
*/
|
|
|
|
|
public @NotNull Combination of(@NotNull Card @NotNull... cards) {
|
|
|
|
|
return of(List.of(cards));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the class representing a combination of this type.
|
|
|
|
|
* @return the class representing a combination of this type.
|
|
|
|
|
*/
|
|
|
|
|
public @NotNull Class<? extends Combination> getCombinationClass() {
|
|
|
|
|
return combinationClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//<editor-fold desc="Utility Methods" defaultstate="collapsed">
|
|
|
|
|
/**
|
|
|
|
|
* Performs basic checks on a list of cards, i.e. this method checks
|
|
|
|
|