/**
* 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 org.apache.log4j.Logger;
import org.jskat.data.JSkatOptions;
import org.jskat.util.Card;
import org.jskat.util.CardList;
import org.jskat.util.GameType;
import org.jskat.util.Rank;
import org.jskat.util.Suit;
/**
* @author Daniel Loreck
*
*/
public class AlgorithmRamsch extends AbstractAlgorithmAI {
private static final Logger log = Logger.getLogger(AlgorithmRamsch.class);
/**
*
*/
AlgorithmRamsch(final AlgorithmAI p, GameType pGameType) {
super(p, pGameType);
log.debug(String.format("/s is %s", myPlayer.getPlayerName(), this
.getClass().getName()));
}
@Override
public Card startGame() {
CardList cards = knowledge.getOwnCards();
if (cards.get(0).getRank() == Rank.JACK
&& cards.get(0).getSuit().ordinal() > 2
&& cards.get(1).getRank() != Rank.JACK) {
return cards.get(0);
}
int resultIndex = -1;
for (Suit s : Suit.values()) {
if (cards.getSuitCount(s, false) == 1) {
if (resultIndex < 0
|| cards.get(resultIndex).getRamschOrder() > cards.get(
cards.getFirstIndexOfSuit(s)).getRamschOrder()) {
resultIndex = cards.getFirstIndexOfSuit(s);
}
} else if (cards.getSuitCount(s, false) == 2
&& cards.get(cards.getLastIndexOfSuit(s)).getRank() == Rank.SEVEN) {
resultIndex = cards.getFirstIndexOfSuit(s);
}
}
if (resultIndex >= 0) {
return cards.get(resultIndex);
}
return cards.get(cards.size() - 1);
}
@Override
public Card playForehandCard() {
CardList cards = knowledge.getOwnCards();
int[] playedCards = knowledge.getPlayedCardsBinary();
int resultIndex = -1;
// see if I want to get rid of any single cards
for (Suit s : Suit.values()) {
if ((knowledge.getPlayedCardsBinary()[s.ordinal()] & 127) > 0) {
continue;
}
Card c = cards.get(cards.getFirstIndexOfSuit(s, false));
if (cards.getSuitCount(s, false) == 1
&& c.getRank().getRamschOrder() < 6
&& c.getRank().getRamschOrder() > 2) {
if (resultIndex < 0) {
resultIndex = cards.getIndexOf(c);
} else {
if (c.getRamschOrder() > cards.get(resultIndex)
.getRamschOrder()) {
resultIndex = cards.getIndexOf(c);
}
}
}
Card lowCard = cards.get(cards.getLastIndexOfSuit(s, false));
if (cards.getSuitCount(s, false) == 2
&& c.getRank().getRamschOrder() < 6
&& lowCard.getRank().getRamschOrder() < 2) {
resultIndex = cards.getIndexOf(c);
}
}
if (resultIndex >= 0) {
Card result = cards.get(resultIndex);
log.debug("Playing single (or high double) suit card: " + result
+ " of " + cards);
return result;
}
int jack = Rank.JACK.toBinaryFlag();
if ((playedCards[0] & jack) + (playedCards[1] & jack)
+ (playedCards[2] & jack) + (playedCards[3] & jack) == 0) {
log.debug("no jack played yet - trying it myself");
if (cards.get(0).getRank() == Rank.JACK
&& cards.get(0).getSuit().ordinal() > 1
&& cards.get(1).getRank() != Rank.JACK) {
return cards.get(0);
}
}
// check best card, if there are no "easy" suits
for (Card c : cards) {
if (c.getRamschOrder() == 1) {
resultIndex = cards.getIndexOf(c);
} else if (c.getRamschOrder() == 0 && resultIndex < 0) {
resultIndex = cards.getIndexOf(c);
}
}
if (resultIndex >= 0) {
return cards.get(resultIndex);
}
return cards.get(cards.size() - 1);
}
@Override
public Card playMiddlehandCard() {
log.debug("I (" + myPlayer.getPlayerName()
+ ") am in middlehand (OpponentPlayer)");
CardList cards = myPlayer.getPlayableCards(knowledge.getTrickCards());
Card initialCard = knowledge.getTrickCards().get(0);
GameType gameType = knowledge.getGameType();
// Card result = null;
// fallback: get last valid card
return getDefaultCard(cards, initialCard, gameType);
}
@Override
public Card playRearhandCard() {
log.debug("I (" + myPlayer.getPlayerName()
+ ") am in rearhand (OpponentPlayer)");
CardList cards = myPlayer.getPlayableCards(knowledge.getTrickCards());
Card initialCard = knowledge.getTrickCards().get(0);
Card middlehandCard = knowledge.getTrickCards().get(1);
GameType gameType = knowledge.getGameType();
Card result = null;
CardList allowed = new CardList();
for (Card c : cards) {
if (c.isAllowed(gameType, initialCard, cards)) {
allowed.add(c);
}
}
if (allowed.size() == 1) {
return allowed.get(0);
}
// if possible, take the highest card
result = allowed.get(0);
for (Card c : allowed) {
boolean beatsCheck = c.beats(gameType, initialCard)
&& c.beats(gameType, middlehandCard);
boolean beatsResult = result.beats(gameType, initialCard)
&& result.beats(gameType, middlehandCard);
if (beatsResult && !beatsCheck) {
result = c;
}
}
// fallback: take the first valid card
return result == null ? getDefaultCard(cards, initialCard, gameType)
: result;
}
/**
* Gets a fallback card, if no other algorithm returned a card
*
* @param cards
* @param initialCard
* @param gameType
* @return a default card
*/
private Card getDefaultCard(final CardList cards, final Card initialCard,
final GameType gameType) {
Card result = null;
for (Card c : cards) {
if (c.isAllowed(gameType, initialCard, cards)) {
result = c;
}
}
if (result != null) {
log.debug("playCard (8)");
return result;
}
log.warn("no possible card found in card list [" + cards + "] with "
+ gameType + " / " + initialCard);
log.debug("playCard (9)");
return cards.get(0);
}
/*
* (non-Javadoc)
*
* @see
* org.jskat.ai.algorithmic.IAlgorithmicAIPlayer#discardSkat(org.jskat.ai
* .algorithmic.BidEvaluator)
*/
@Override
public CardList discardSkat(final BidEvaluator bidEvaluator) {
log.debug(myPlayer.getPlayerName() + " (" + this.getClass()
+ ") is discarding cards");
if (JSkatOptions.instance().isSchieberamschJacksInSkat()) {
return discardWithJacks();
}
return discardNoJacks();
}
private CardList discardWithJacks() {
CardList result = new CardList();
CardList cards = new CardList(knowledge.getOwnCards());
log.debug("cards left before discarding(withJacks): " + cards.size()
+ " - " + cards);
cards.sort(GameType.RAMSCH);
if (cards.get(0).getRank() == Rank.JACK
&& cards.get(0).getSuit() == Suit.CLUBS
|| cards.get(0).getSuit() == Suit.SPADES) {
result.add(cards.remove(0));
}
if (cards.get(0).getRank() == Rank.JACK
&& cards.get(0).getSuit() == Suit.SPADES) {
result.add(cards.remove(0));
}
if (result.size() == 2) {
return result;
}
result.addAll(discardNoJacks());
while (result.size() > 2) {
cards.add(result.remove(result.size() - 1));
}
log.debug("cards left after discarding(withJacks): " + cards.size()
+ " - " + cards);
return result;
}
private CardList discardNoJacks() {
CardList result = new CardList();
CardList cards = new CardList(knowledge.getOwnCards());
cards.sort(GameType.RAMSCH);
log.debug("cards left before discarding(noJacks): " + cards.size()
+ " - " + cards);
for (Card c : cards) {
if (result.size() < 2 && c.getRank() == Rank.ACE) {
result.add(c);
} else if (result.size() == 2 && c.getRank() == Rank.ACE) {
int len = knowledge.getOwnCards().getSuitCount(c.getSuit(),
false);
int len0 = knowledge.getOwnCards().getSuitCount(
result.get(0).getSuit(), false);
int len1 = knowledge.getOwnCards().getSuitCount(
result.get(1).getSuit(), false);
if (len < len0) {
result.remove(0);
result.add(c);
} else if (len < len1) {
result.remove(1);
result.add(c);
}
}
}
for (Card c : cards) {
if (result.size() < 2 && c.getRank() == Rank.TEN) {
result.add(c);
} else if (result.size() == 2 && c.getRank() == Rank.TEN) {
int len = knowledge.getOwnCards().getSuitCount(c.getSuit(),
false);
int len0 = knowledge.getOwnCards().getSuitCount(
result.get(0).getSuit(), false);
int len1 = knowledge.getOwnCards().getSuitCount(
result.get(1).getSuit(), false);
if (len < len0) {
result.remove(0);
result.add(c);
} else if (len < len1) {
result.remove(1);
result.add(c);
}
}
}
for (Card c : cards) {
if (result.size() < 2 && c.getRank() == Rank.KING) {
result.add(c);
}
}
for (Card c : cards) {
if (result.size() < 2 && c.getRank() != Rank.JACK) {
result.add(c);
}
}
log.debug("cards left after discarding(noJacks): " + cards.size()
+ " - " + cards);
return result;
}
}