/**
* Copyright (C) 2017 Jan Schäfer (jansch@users.sourceforge.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jskat.ai.newalgorithm;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.jskat.ai.newalgorithm.exception.IllegalMethodException;
import org.jskat.util.Card;
import org.jskat.util.CardList;
import org.jskat.util.GameType;
import org.jskat.util.Player;
import org.jskat.util.Rank;
import org.jskat.util.Suit;
public class AlgorithmOpponentSuit extends AbstractAlgorithmAI {
private static final Logger log = Logger
.getLogger(AlgorithmOpponentSuit.class);
AlgorithmOpponentSuit(final AlgorithmAI p, GameType pGameType) {
super(p, pGameType);
log.debug(String.format("/s is %s", myPlayer.getPlayerName(), this
.getClass().getName()));
}
@Override
protected Card startGame() {
log.debug("Suit-Opponent starts Game: "
+ knowledge.getCurrentTrick().getForeHand());
return playStartGameCard(knowledge.getOwnCards(),
knowledge.getTrickCards(), oPlayedCards, oNotOpponentCards,
oSituation, knowledge.getPlayerPosition(),
knowledge.getDeclarer());
}
@Override
protected Card playForehandCard() {
log.debug("Suit-Opponent plays Forehand-Card: "
+ knowledge.getCurrentTrick().getForeHand());
return playForehandCard(knowledge.getOwnCards(),
knowledge.getTrickCards(), oPlayedCards, oNotOpponentCards,
oSituation, knowledge.getPlayerPosition(),
knowledge.getDeclarer());
}
@Override
protected Card playMiddlehandCard() {
log.debug("Suit-Opponent plays Middlehand-Card: "
+ knowledge.getCurrentTrick().getMiddleHand());
return playMiddlehandCard(
myPlayer.getPlayableCards(knowledge.getTrickCards()),
knowledge.getTrickCards(), oPlayedCards, oNotOpponentCards,
oSituation, knowledge.getPlayerPosition(),
knowledge.getDeclarer());
}
@Override
protected Card playRearhandCard() {
log.debug("Suit-Opponent plays Rearhand-Card: "
+ knowledge.getCurrentTrick().getRearHand());
return playRearhandCard(
myPlayer.getPlayableCards(knowledge.getTrickCards()),
knowledge.getTrickCards(), oPlayedCards, oNotOpponentCards,
oSituation, knowledge.getPlayerPosition(),
knowledge.getDeclarer());
}
@Override
public CardList discardSkat(BidEvaluator bidEvaluator) {
throw new IllegalMethodException(
"AlgorithmOpponentSuit has nothing to discard!");
}
// static methods for creating JUnit-tests and test cardplaybehavior
public static Card playStartGameCard(CardList pCards, CardList pTrickCards,
CardList pPlayedCards, CardList pNotOpponentCards,
Situation pSituation, Player pPlayerPosition, Player pDeclarer) {
pCards.sort(pSituation.getGameType());
boolean tDeclarerInMiddle = pPlayerPosition.getLeftNeighbor() == pDeclarer;
CardList tPossibleHighCard = new CardList();
CardList tPossibleLowCard = new CardList();
for (Suit s : Suit.values()) {
if (s == pSituation.getTrumpSuit()
|| pCards.getSuitCount(s, false) == 0) {
continue;
}
if (pCards.get(pCards.getFirstIndexOfSuit(s, false)).getRank() == Rank.ACE) {
tPossibleHighCard.add(pCards.get(pCards.getFirstIndexOfSuit(s,
false)));
}
if ((tDeclarerInMiddle || pCards.getSuitCount(s, false) >= 3)
&& pCards.get(pCards.getLastIndexOfSuit(s, false))
.getPoints() <= 0) {
tPossibleLowCard.add(pCards.get(pCards.getLastIndexOfSuit(s,
false)));
}
}
if (!tPossibleHighCard.isEmpty()) {
return playRandomCard(tPossibleHighCard);
}
if (!tPossibleLowCard.isEmpty()) {
return playRandomCard(tPossibleLowCard);
}
return playForehandCard(pCards, pTrickCards, pPlayedCards,
pNotOpponentCards, pSituation, pPlayerPosition, pDeclarer);
}
public static Card playForehandCard(CardList pCards, CardList pTrickCards,
CardList pPlayedCards, CardList pNotOpponentCards,
Situation pSituation, Player pPlayerPosition, Player pDeclarer) {
pCards.sort(pSituation.getGameType());
boolean tDeclarerInMiddle = pPlayerPosition.getLeftNeighbor() == pDeclarer;
CardList possibleCards = new CardList();
for (Suit lSuit : Suit.values()) {
if (lSuit == pSituation.getTrumpSuit()
|| pCards.getSuitCount(lSuit, false) == 0) {
continue;
}
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
lSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(lSuit,
false)); // lowest Card
// Wenn nur eine Karte und diese weniger als 10 Puntke wert ist
if (possibleHighCard.equals(possibleLowCard)
&& possibleHighCard.getPoints() < 10) {
possibleCards.add(possibleHighCard);
}
// Wenn der Solo-Spieler in Mittelhand
if (tDeclarerInMiddle) {
// Wenn nur noch der Spieler selbst Karten der Farbe hat ->
// versuchen Truempfe vom Solo-Spieler ziehen
if ((Helper.getSuitCardsToBinary(pPlayedCards, lSuit) & Helper
.getSuitCardsToBinary(pCards, lSuit)) == 127) {
return possibleHighCard;
}
possibleCards.add(possibleLowCard);
} else {
if ((Helper.getSuitCardsToBinary(pPlayedCards, lSuit) & Helper
.getSuitCardsToBinary(pCards, lSuit)) == 127
&& pCards.getSuitCount(lSuit, false) <= 3) {
return possibleHighCard;
}
if (possibleLowCard.getPoints() <= 4) {
possibleCards.add(possibleLowCard);
}
}
// Wenn der Spieler die hoechste Karte der Farbe hat
// und der Solo-Spieler nicht blank ist
if (pPlayedCards.getSuitCount(lSuit, false) <= 4
&& (pPlayerPosition.getLeftNeighbor() == pDeclarer
&& !pSituation.isLeftPlayerBlankOnColor(lSuit) || pPlayerPosition
.getRightNeighbor() == pDeclarer
&& !pSituation.isRightPlayerBlankOnColor(lSuit))
&& Helper.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards, null)) {
return possibleHighCard;
}
}
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
return getRandomAllowedCard(pCards, null, pSituation.getGameType());
}
public static Card playMiddlehandCard(CardList pCards,
CardList pTrickCards, CardList pPlayedCards,
CardList pNotOpponentCards, Situation pSituation,
Player pPlayerPosition, Player pDeclarer) {
pCards.sort(pSituation.getGameType());
boolean tDeclarerInForhand = pPlayerPosition.getRightNeighbor() == pDeclarer;
Card tForehandCard = pTrickCards.get(0);
Suit tSuit = tForehandCard.getSuit();
ArrayList<Suit> tDeclarerBlankSuits = pSituation
.getLeftPlayerBlankSuits();
if (pPlayerPosition.getRightNeighbor() == pDeclarer) {
tDeclarerBlankSuits = pSituation.getRightPlayerBlankSuits();
}
CardList possibleCards = new CardList();
// Trumpfkarte wurde gespielt
if (tForehandCard.getSuit() == pSituation.getTrumpSuit()
|| tForehandCard.getRank() == Rank.JACK) {
// Wenn Solo-Spieler in Forehand sitzt und die erste Karte des
// Tricks seine ist
if (tDeclarerInForhand) {
// Wenn der Spieler Trumpfkarten hat
if (pCards.hasTrump(pSituation.getGameType())) {
int tTrumpCount = Helper.countJacks(pCards)
+ pCards.getSuitCount(pSituation.getTrumpSuit(),
false);
if (tTrumpCount == 1) {
return pCards.get(0);
}
// Wenn schlagbar
if (pCards.get(0).beats(pSituation.getGameType(),
tForehandCard)) {
if (pCards.contains(Card.getCard(
pSituation.getTrumpSuit(), Rank.ACE))
&& Rank.ACE.toBinaryFlag() > tForehandCard
.getRank().toBinaryFlag()) {
return Card.getCard(pSituation.getTrumpSuit(),
Rank.ACE);
} else if (pCards.contains(Card.getCard(
pSituation.getTrumpSuit(), Rank.TEN))
&& Rank.TEN.toBinaryFlag() > tForehandCard
.getRank().toBinaryFlag()) {
return Card.getCard(pSituation.getTrumpSuit(),
Rank.TEN);
}
return getLowestBeatingCard(pCards,
pSituation.getGameType(), tForehandCard);
}
return Helper.getLowestTrumpValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
// Wenn kein Trumpf mehr auf der Hand
for (Suit lSuit : Suit.values()) {
if (lSuit == pSituation.getTrumpSuit()
|| pCards.getSuitCount(lSuit, false) == 0) {
continue;
}
Card possibleHighCard = pCards.get(pCards
.getFirstIndexOfSuit(lSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards
.getLastIndexOfSuit(lSuit, false)); // lowest Card
// Wenn nur eine Karte der Farbe und nicht das Ass
if (possibleHighCard == possibleLowCard
&& possibleHighCard.getRank() != Rank.ACE) {
// Wenns kein Ass oder 10 ist TODO
if (possibleHighCard.getRank() == Rank.TEN) {
if (Helper
.getSuitCardsToBinary(pPlayedCards, lSuit) >= Rank.ACE
.toBinaryFlag()) {
continue;
}
possibleCards.add(possibleHighCard);
} else {
return possibleHighCard;
}
} else if (Helper.getSuitCardsToBinary(pPlayedCards, lSuit) > 2) {
return possibleLowCard;
// Wenn genau 2 Karten
} else {
possibleCards.add(possibleLowCard);
}
}
}
// Solo-Spieler sitzt in Hinterhand
else {
// Wenn nur noch ein Trumpf
if (Helper.getTrumpCardsToBinary(pCards,
pSituation.getTrumpSuit()) == 1) {
return pCards.get(0);
}
// Wenn der Spieler Trumpfkarten hat
if (pCards.hasTrump(pSituation.getGameType())) {
// Wenn der Trumpf vom Mitspieler nicht geschlagen werden
// kann
if (Helper.isHighestTrumpCard(tForehandCard,
pSituation.getGameType(), pPlayedCards)) {
Card tPossibleCard = Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
// Wenn die HighValueCard des Spielers danach die
// hoechste Karte ist
if (Helper.isHighestTrumpCard(tPossibleCard,
pSituation.getGameType(), pPlayedCards)) {
return pCards
.get(pCards.getIndexOf(tPossibleCard) + 1);
}
return tPossibleCard;
}
// Wenn das gelegte Ass oder die gelegte 10 die hoechste
// Karte ist
if (tForehandCard.getRank() == Rank.ACE
&& (Helper.getTrumpCardsToBinary(pPlayedCards,
pSituation.getTrumpSuit()) & Helper
.getTrumpCardsToBinary(pCards,
pSituation.getTrumpSuit())) >= 1920 // CJ,
// SJ,
// HJ,
// DJ
|| tForehandCard.getRank() == Rank.TEN
&& (Helper.getTrumpCardsToBinary(pPlayedCards,
pSituation.getTrumpSuit()) & Helper
.getTrumpCardsToBinary(pCards,
pSituation.getTrumpSuit())) >= 1984) { // CJ,
// SJ,
// HJ,
// DJ,
// ACE
return pCards.get(pCards.getFirstIndexOfSuit(
pSituation.getTrumpSuit(), false));
}
// Wenn Trumpfkarte auf der Hand -> niedrigste spielen
if (pCards.getSuitCount(pSituation.getTrumpSuit(), false) > 0) {
return pCards.get(pCards.getLastIndexOfSuit(
pSituation.getTrumpSuit(), false));
}
// Sonst niedrigsten Buben spielen
return pCards.get(Helper.countJacks(pCards) - 1);
}
// Wenn keine Trumpfkarte in der Hand
// Wenn der Trumpf vom Mitspieler nicht geschlagen werden kann
if (Helper.isHighestTrumpCard(tForehandCard,
pSituation.getGameType(), pPlayedCards)) {
for (int i = 0; i < tDeclarerBlankSuits.size(); i++) {
Card lCard = Helper.getHighestValueCard(pCards,
tDeclarerBlankSuits.get(i), false);
if (lCard != null && lCard.getPoints() >= 10) {
return lCard;
}
possibleCards.add(lCard);
}
if (possibleCards.size() > 0) {
return playRandomCard(possibleCards);
}
}
// Spiele zuerst niedrige Karten der blanken Farbe des
// Solo-Spielers
for (int i = 0; i < tDeclarerBlankSuits.size(); i++) {
Card lCard = Helper.getLowestValueCard(pCards,
tDeclarerBlankSuits.get(i));
if (lCard != null) {
if (lCard.getPoints() <= 3) {
return lCard;
}
possibleCards.add(lCard);
}
}
for (Suit s : Suit.values()) {
Card lCard = Helper.getLowestValueCard(pCards, s);
if (lCard != null) {
if (lCard.getPoints() <= 3) {
return lCard;
}
possibleCards.add(lCard);
}
}
if (possibleCards.size() > 0) {
return playRandomCard(possibleCards);
}
}
}
// Wenn nur eine Karte der Farbe vorhanden
if (pCards.getSuitCount(tSuit, false) == 1) {
return pCards.get(pCards.getFirstIndexOfSuit(tSuit, false));
}
// Keine Trumpkarte wurde gespielt
if (tDeclarerInForhand) {
// Wenn der Spieler bedienen kann/muss
if (pCards.getSuitCount(tSuit, false) > 1) {
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
tSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(
tSuit, false)); // lowest Card
// Wenn der Solo-Spieler schlagbar ist -> schlagen
if (possibleHighCard.beats(pSituation.getGameType(),
tForehandCard)) {
// Wenn die zweithöchste Karte anschliessend unschlagbar
// ist
if (Helper.isHighestSuitCard(pCards.get(pCards
.getFirstIndexOfSuit(tSuit, false) + 1), pSituation
.getGameType(), pNotOpponentCards, pTrickCards)) {
return possibleHighCard;
}
for (int i = pCards.getLastIndexOfSuit(tSuit, false); i >= pCards
.getFirstIndexOfSuit(tSuit, false); i--) {
if (pCards.get(i).beats(pSituation.getGameType(),
tForehandCard)) {
return pCards.get(i);
}
}
}
int i = Helper.getSuitCardsToBinary(pNotOpponentCards, tSuit)
+ Helper.getSuitCardsToBinary(pTrickCards, tSuit);
if (Helper.getSuitCardsToBinary(pNotOpponentCards, tSuit)
+ Helper.getSuitCardsToBinary(pTrickCards, tSuit) == 127) {
return possibleHighCard;
}
return possibleLowCard;
}
// Wenn keine Karte dieser Farbe
// Wenn Trumpfkarte vorhanden
if (pCards.hasTrump(pSituation.getGameType())) {
Card tPossibleCard = Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
int jackCount = Helper.countJacks(pCards);
if (tPossibleCard != null) {
// Wenn die hochwertige Karte des Spielers die hoechste
// Trumpkarte ist
if (Helper.isHighestTrumpCard(tPossibleCard,
pSituation.getGameType(), pPlayedCards)
&& pCards.get(pCards.getIndexOf(tPossibleCard) + 1)
.getSuit() == pSituation.getTrumpSuit()) {
return pCards.get(pCards.getIndexOf(tPossibleCard) + 1);
}
return tPossibleCard;
} else if (jackCount > 0) {
return pCards.get(jackCount - 1);
}
}
// TODO: Wenn vom Mitspieler schlagbar -> hochwertige Karte, sonst
// niedrige Karte spielen
// Wenn die Karte des Solo-Spielers nicht die hoechste ist
if (!Helper.isHighestSuitCard(tForehandCard,
pSituation.getGameType(), pPlayedCards, pTrickCards)
&& pPlayedCards.getSuitCount(pSituation.getTrumpSuit(),
false) < 3
|| pPlayedCards.getSuitCount(pSituation.getTrumpSuit(),
false) > 5) {
for (int i = 0; i < tDeclarerBlankSuits.size(); i++) {
Card lCard = Helper.getHighestValueCard(pCards,
tDeclarerBlankSuits.get(i), false);
if (lCard != null && lCard.getPoints() >= 10) {
possibleCards.add(lCard);
}
}
if (possibleCards.size() > 0) {
return playRandomCard(possibleCards);
}
}
// Solo-Spielers blanke Farben abwerfen wenn <= 4 Punkte Karte
// vorhanden
for (int i = 0; i < tDeclarerBlankSuits.size(); i++) {
Card lCard = Helper.getLowestValueCard(pCards,
tDeclarerBlankSuits.get(i));
if (lCard != null && lCard.getPoints() <= 4) {
possibleCards.add(lCard);
}
}
if (possibleCards.size() > 0) {
return playRandomCard(possibleCards);
}
}
// Forehand-Karte ist keine Trumpfkarte und Solo-Spieler sitzt in
// Hinterhand
else {
// Wenn mehr als eine Karte der Farbe habe und bedienen kann/muss
if (pCards.getSuitCount(tSuit, false) > 1) {
// Solo-Spieler ist blank auf der Farbe -> niedrigste Karte
// legen
if (!tDeclarerBlankSuits.contains(tSuit)) {
return pCards.get(pCards.getLastIndexOfSuit(tSuit, false));
}
return pCards.get(pCards.getFirstIndexOfSuit(tSuit, false));
} else if (pCards.getSuitCount(tSuit, false) == 0) {
// Wenn >= 10 Punkte im Stich und Spieler hat den hoechsten
// Trumpf in der Hand
if (tDeclarerBlankSuits.contains(pSituation.getTrumpSuit())
&& tForehandCard.getPoints() >= 10
&& pCards.get(0).getSuit() == pSituation.getTrumpSuit()
&& Helper.isHighestTrumpCard(pCards.get(0),
pSituation.getGameType(), pPlayedCards)) {
return pCards.get(0);
}
// Solo-Spieler hat wahrscheinlich noch eine Karte und A oder 10
// ist noch nicht gespielt
if (!tDeclarerBlankSuits.contains(pSituation.getTrumpSuit())
&& (!pPlayedCards.contains(Card.getCard(
pSituation.getTrumpSuit(), Rank.ACE))
|| !pPlayedCards.contains(Card.getCard(
pSituation.getTrumpSuit(), Rank.TEN)) || tForehandCard
.getPoints() >= 10)) {
if (pCards.hasTrump(pSituation.getGameType())) {
return Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
return pCards.get(Helper.countJacks(pCards) - 1);
}
}
if (tDeclarerBlankSuits.contains(pSituation.getTrumpSuit())
|| Helper.isHighestTrumpCard(pCards.get(0),
pSituation.getGameType(), pPlayedCards)) {
return pCards.get(0); // highest Card
} else {
return pCards.get(pCards.getLastIndexOfSuit(
pSituation.getTrumpSuit(), false));
}
}
return getRandomAllowedCard(pCards, tForehandCard,
pSituation.getGameType());
}
public static Card playRearhandCard(CardList pCards, CardList pTrickCards,
CardList pPlayedCards, CardList pNotOpponentCards,
Situation pSituation, Player pPlayerPosition, Player pDeclarer) {
pCards.sort(pSituation.getGameType());
Card tForehandCard = pTrickCards.get(0);
Suit tSuit = tForehandCard.getSuit();
Card tMiddlehandCard = pTrickCards.get(1);
CardList possibleCards = new CardList();
Card tCardToBeat = tForehandCard;
if (tMiddlehandCard.beats(pSituation.getGameType(), tCardToBeat)) {
tCardToBeat = tMiddlehandCard;
}
Suit tCardToBeatSuit = tCardToBeat.getSuit();
ArrayList<Suit> tDeclarerBlankSuits = pSituation
.getLeftPlayerBlankSuits();
if (pPlayerPosition.getRightNeighbor() == pDeclarer) {
tDeclarerBlankSuits = pSituation.getRightPlayerBlankSuits();
}
// Wenn der Stich bislang dem Solo-Spieler gehoert
// Wenn Middlehand die hoehere ist und rechts vom Spieler sitzt der
// Solo-Spieler
// oder Forehand ist der Solo-Spieler und liegt vorne
if (tMiddlehandCard.beats(pSituation.getGameType(), tForehandCard) == (pPlayerPosition
.getRightNeighbor() == pDeclarer)) {
// Wenn Solo-Spieler in Forehand sitzt
if (tCardToBeat == tForehandCard) {
// Wenn kein Trumpf
if (!tForehandCard.isTrump(pSituation.getGameType())) {
// Wenn bedienen kann/muss
if (pCards.getSuitCount(tCardToBeatSuit, false) > 0) {
// Wenn schlagbar
if (pCards.get(
pCards.getFirstIndexOfSuit(tCardToBeatSuit,
false)).beats(pSituation.getGameType(),
tCardToBeat)) {
return getLowestBeatingCard(pCards,
pSituation.getGameType(), tCardToBeat);
}
return pCards.get(pCards.getLastIndexOfSuit(
tCardToBeatSuit, false));
}
// Wenn genug Punkte im Stich und Trumpf vorhanden -> Punkte
// mitnehmen
if (pCards.hasTrump(pSituation.getGameType())
&& tForehandCard.getPoints()
+ tMiddlehandCard.getPoints() >= 10) {
if (pCards.hasTrump(pSituation.getGameType())) {
return Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
return pCards.get(Helper.countJacks(pCards) - 1);
}
// FremdSuit-Karte abwerfen
for (Suit lSuit : Suit.values()) {
int lSuitCount = pCards.getSuitCount(lSuit, false);
if (lSuit == pSituation.getTrumpSuit()
|| lSuitCount == 0) {
continue;
}
Card possibleHighCard = pCards.get(pCards
.getFirstIndexOfSuit(lSuit, false)); // highest
// Card
Card possibleLowCard = pCards.get(pCards
.getLastIndexOfSuit(lSuit, false)); // lowest
// Card
// Wenn eine Karte der Farbe
if (lSuitCount == 1) {
// Solo-Spieler hat Farbe blank && Kartenwert < 10
if (tDeclarerBlankSuits.contains(lSuit)
&& possibleLowCard.getPoints() < 10) {
possibleCards.add(possibleLowCard);
}
// Wenn die Karte 0 Wert hat -> Farbe blank spielen
if (possibleLowCard.getPoints() == 0) {
return possibleLowCard;
}
}
// Wenn zwei Karte der Farbe
if (lSuitCount == 2) {
// Solo-Spieler hat Farbe blank && Kartenwert < 10
if (tDeclarerBlankSuits.contains(lSuit)
&& possibleLowCard.getPoints() < 10) {
possibleCards.add(possibleLowCard);
}
// Wenn niedrige Karte 7,8,9 oder Q ist und die hohe
// Karte unschlagbar ist
if (possibleLowCard.getPoints() <= 3
&& Helper.isHighestSuitCard(
possibleHighCard,
pSituation.getGameType(),
pPlayedCards, pTrickCards)) {
possibleCards.add(possibleLowCard);
}
}
if (lSuitCount > 2) {
// Wenn niedrige Karte 7,8,9 oder Q ist
if (possibleLowCard.getPoints() < 4) {
possibleCards.add(possibleLowCard);
}
}
}
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
// mit einem niedrigen Trumpf mitnehmen
if (pCards.getSuitCount(pSituation.getTrumpSuit(), false) > 0) {
return Helper.getLowestTrumpValueCard(pCards,
pSituation.getTrumpSuit(), false);
}
}
// Wenn Trumpf
else {
// Wenn bedienen kann/muss
if (pCards.hasTrump(pSituation.getGameType())) {
// Wenn schlagbar
if (pCards.get(0).beats(pSituation.getGameType(),
tCardToBeat)) {
return getLowestBeatingCard(pCards,
pSituation.getGameType(), tCardToBeat);
}
// nicht schlagbar
return Helper.getLowestTrumpValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
// FremdSuit-Karte abwerfen
for (Suit lSuit : Suit.values()) {
int lSuitCount = pCards.getSuitCount(lSuit, false);
if (lSuit == pSituation.getTrumpSuit()
|| lSuitCount == 0) {
continue;
}
Card possibleHighCard = pCards.get(pCards
.getFirstIndexOfSuit(lSuit, false)); // highest
// Card
Card possibleLowCard = pCards.get(pCards
.getLastIndexOfSuit(lSuit, false)); // lowest
// Card
// Wenn eine Karte der Farbe
if (lSuitCount == 1) {
// Solo-Spieler hat Farbe blank && Kartenwert < 10
if (tDeclarerBlankSuits.contains(lSuit)
&& possibleLowCard.getPoints() < 10) {
possibleCards.add(possibleLowCard);
}
// Wenn die Karte 0 Wert hat -> Farbe blank spielen
if (possibleLowCard.getPoints() == 0) {
return possibleLowCard;
}
}
// Wenn zwei Karte der Farbe
if (lSuitCount == 2) {
// Solo-Spieler hat Farbe blank && Kartenwert < 10
if (tDeclarerBlankSuits.contains(lSuit)
&& possibleLowCard.getPoints() < 10) {
possibleCards.add(possibleLowCard);
}
// Wenn niedrige Karte 7,8,9 oder Q ist und die hohe
// Karte unschlagbar ist
if (possibleLowCard.getPoints() <= 3
&& Helper.isHighestSuitCard(
possibleHighCard,
pSituation.getGameType(),
pPlayedCards, pTrickCards)) {
possibleCards.add(possibleLowCard);
}
}
if (lSuitCount > 2) {
// Wenn niedrige Karte 7,8,9 oder Q ist
if (possibleLowCard.getPoints() < 4) {
possibleCards.add(possibleLowCard);
}
}
}
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
}
}
// Solo-Spieler ist in Mittelhand und bislang gehört ihm der
// Stich
// Wenn Vorhand schon eine Trumpfkarte ist
if (tForehandCard.isTrump(pSituation.getGameType())) {
// Wenn der Spieler noch einen Trumpf auf der Hand hat
if (pCards.hasTrump(pSituation.getGameType())) {
// niedrigen Trumpf
if (pCards.get(0).beats(pSituation.getGameType(),
tCardToBeat)) {
return getLowestBeatingCard(pCards,
pSituation.getGameType(), tCardToBeat);
}
return getLowValueTrumpCard(pCards,
pSituation.getTrumpSuit());
}
// Kein Trumpf mehr auf der Hand
possibleCards = getPossibleMaxValueCards(pCards, 0,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
possibleCards = getPossibleMaxValueCards(pCards, 3,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
possibleCards = getPossibleMaxValueCards(pCards, 4,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
}
// Wenn Vorhand eine andere Farbe ist
// UND Solo-Spieler sticht mit Trumpf
else if (!tForehandCard.isTrump(pSituation.getGameType())
&& tMiddlehandCard.isTrump(pSituation.getGameType())) {
if (pCards.hasSuit(pSituation.getGameType(), tSuit)) {
return Helper.getLowestValueCard(pCards, tSuit);
}
}
// Wenn Solo-Spieler mit selber Farbe den Stich haelt
else {
// Wenn der Spieler eine Karte der Farbe hat
if (pCards.hasSuit(pSituation.getGameType(), tSuit)) {
Card firstCard = pCards.get(pCards.getFirstIndexOfSuit(
tSuit, false));
Card secondCard = pCards.get(pCards.getFirstIndexOfSuit(
tSuit, false));
// Wenn mit zweiter Karte schlagbar
if (secondCard.beats(pSituation.getGameType(), tCardToBeat)) {
// Wenn es moeglich ist, dass eine Karte dazwischen beim
// Solo-Spieler ist
List<Rank> ranks = Rank.getRankList();
for (int i = ranks.indexOf(firstCard.getRank()) + 1; i < ranks
.indexOf(secondCard.getRank()); i++) {
if (!pNotOpponentCards.contains(Card.getCard(
firstCard.getSuit(), ranks.get(i)))) {
return secondCard;
}
}
return firstCard;
}
if (firstCard.beats(pSituation.getGameType(), tCardToBeat)) {
return firstCard;
}
return Helper.getLowestValueCard(pCards, tSuit);
} else {
// Wenn mehr als 10 Punkte im Stich und noch Trumpf auf der
// Hand
if (tForehandCard.getPoints() + tMiddlehandCard.getPoints() >= 8
&& pCards.hasTrump(pSituation.getGameType())) {
return Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
// Lusche abwerfen
possibleCards = getPossibleMaxValueCards(pCards, 0,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
possibleCards = getPossibleMaxValueCards(pCards, 3,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
possibleCards = getPossibleMaxValueCards(pCards, 4,
pSituation.getTrumpSuit());
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
}
}
}
// Wenn Trumpf bedient werden muss
if (tSuit == pSituation.getTrumpSuit()
|| tForehandCard.getRank() == Rank.JACK) {
if (pCards.hasTrump(pSituation.getGameType())) {
return Helper.getHighestValueCard(pCards,
pSituation.getTrumpSuit(), true);
}
if (Helper.countJacks(pCards) > 0) {
return pCards.get(Helper.countJacks(pCards) - 1);
}
}
// Wenn bedienen kann/muss
int tSuitCount = pCards.getSuitCount(tSuit, false);
if (tSuitCount == 1) {
// Karte spielen
return pCards.get(pCards.getFirstIndexOfSuit(tSuit, false));
} else if (tSuitCount == 2) {
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
tSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(tSuit,
false)); // lowest Card
// Spieler spielt die hoechste Karte, wenn:
// - hoechste Karte hat und es sind nur noch 3 Karten im Spiel
// - pDeclarer in Mittelhand und hat die Farbe schon blank
// - pDeclarer in Forhand und hat die Farbe schon blank
if (Helper.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards, pTrickCards)
&& (pNotOpponentCards.getSuitCount(tSuit, false) > 4 || possibleHighCard
.getRank().toBinaryFlag() >> 1 == possibleLowCard
.getRank().toBinaryFlag())
|| pDeclarer == Player.MIDDLEHAND
&& pSituation.isRightPlayerBlankOnColor(tSuit)
|| pDeclarer == Player.FOREHAND
&& pSituation.isLeftPlayerBlankOnColor(tSuit)) {
return possibleHighCard;
}
possibleCards.add(possibleLowCard);
} else if (tSuitCount > 2) {
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
tSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(tSuit,
false)); // lowest Card
if (Helper.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards, pTrickCards)
&& possibleHighCard.getRank().toBinaryFlag() >> 1 == pCards
.get(pCards.getFirstIndexOfSuit(tSuit, false) + 1)
.getRank().toBinaryFlag()
|| pNotOpponentCards.getSuitCount(tSuit, false) > 4) {
return possibleHighCard;
}
possibleCards.add(pCards.get(pCards.getFirstIndexOfSuit(tSuit,
false) + 1));
} else if (tSuitCount == 0) {
for (Suit lSuit : Suit.values()) {
int lSuitCount = pCards.getSuitCount(lSuit, false);
if (lSuit == pSituation.getTrumpSuit() || lSuitCount == 0) {
continue;
}
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
lSuit, false)); // highest Card
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(
lSuit, false)); // lowest Card
// Wenn nur eine Karte der Farbe und diese Karte ist nicht die
// hoechste Karte
if (lSuitCount == 1) {
if (!Helper
.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards,
pTrickCards)) {
return possibleHighCard;
}
} else if (lSuitCount == 2) {
// Wenn die hoehere Karte die hoechste ist
if (Helper
.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards,
pTrickCards)) {
CardList after = new CardList(pPlayedCards);
after.add(possibleHighCard);
// Wenn die niedrigere Karte die Hoechste nach der
// Hoechsten ist --> Hoechste spielen, sonst die
// niedrige spielen
if (possibleHighCard.getRank().toBinaryFlag() >> 1 == possibleLowCard
.getRank().toBinaryFlag()) {
return possibleHighCard;
}
}
if (possibleLowCard.getPoints() > 3) {
return possibleLowCard;
}
possibleCards.add(possibleLowCard);
}
// Mehr Karten als 2 von der Farbe
else {
// Wenn die hoehere Karte die hoechste ist
if (Helper
.isHighestSuitCard(possibleHighCard,
pSituation.getGameType(), pPlayedCards,
pTrickCards)) {
CardList after = new CardList(pPlayedCards);
after.add(possibleHighCard);
// Wenn die niedrigere Karte die Hoechste nach der
// Hoechsten ist --> Hoechste spielen, sonst die
// niedrige spielen
if (possibleHighCard.getRank().toBinaryFlag() >> 1 == pCards
.get(pCards.getFirstIndexOfSuit(lSuit, false) + 1)
.getRank().toBinaryFlag()) {
return possibleHighCard;
}
}
possibleCards.add(possibleHighCard);
}
}
}
if (!possibleCards.isEmpty()) {
return playRandomCard(possibleCards);
}
return getRandomAllowedCard(pCards, tForehandCard,
pSituation.getGameType());
}
protected static CardList getPossibleMaxValueCards(CardList pCards,
int pMaxCardValue, Suit pTrumpSuit) {
CardList possibleCards = new CardList();
for (Suit lSuit : Suit.values()) {
if (lSuit == pTrumpSuit) {
continue;
}
int suitCount = pCards.getSuitCount(lSuit, false);
Card possibleHighCard = pCards.get(pCards.getFirstIndexOfSuit(
lSuit, false));
Card possibleLowCard = pCards.get(pCards.getLastIndexOfSuit(lSuit,
false));
if (suitCount > 0 && possibleHighCard == possibleLowCard
&& possibleLowCard.getPoints() <= pMaxCardValue) {
possibleCards.add(possibleLowCard);
} else if (suitCount > 2
&& possibleLowCard.getPoints() <= pMaxCardValue) {
possibleCards.add(possibleLowCard);
}
}
return possibleCards;
}
}