/** * 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.mjl; import java.util.Vector; import org.jskat.util.Card; import org.jskat.util.CardList; import org.jskat.util.Rank; import org.jskat.util.Suit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Markus J. Luzius (markus@luzius.de) * */ public class RamschSkatProcessor { private static Logger log = LoggerFactory .getLogger(RamschSkatProcessor.class); private void testProcessor(final CardList cards, final CardList skat) { int[] cardBin = new int[4]; cardBin[3] = Helper.suitCardsToBinaryWithSkat(cards, skat, Suit.DIAMONDS); cardBin[2] = Helper.suitCardsToBinaryWithSkat(cards, skat, Suit.HEARTS); cardBin[1] = Helper.suitCardsToBinaryWithSkat(cards, skat, Suit.SPADES); cardBin[0] = Helper.suitCardsToBinaryWithSkat(cards, skat, Suit.CLUBS); Vector<Double> relevance = new Vector<Double>(); cards.add(skat.remove(0)); cards.add(skat.remove(0)); for (int i = 0; i < cards.size(); i++) { Card c = cards.get(i); // TODO (js) changed due to refactoring, // don't know if it's still work as intended // double rel = 1.0 * (double) c.getRank() / 6.0; double rel = 1.0 * c.getRank().getSuitGrandOrder() / 6.0; if (c.getRank() == Rank.JACK) { rel = 0.0; } log.debug("Card(" + i + "): " + c + ", Rel=" + rel); // TODO (js) changed due to refactoring, // don't know if it's still work as intended // int tmpBin = cardBin[c.getSuit()]; int tmpBin = Helper.suitCardsToBinaryWithSkat(cards, skat, c.getSuit()); log.debug("suit=" + bin(tmpBin, 8) + " & 15 = " + (tmpBin & 15)); if (Tools.isIn(tmpBin & 15, new int[] { 7, 11, 13 })) { rel = 0.0; } else if (Tools.isIn(tmpBin & 15, new int[] { 3, 5 })) { rel = rel * 0.1; } else if (Tools.isIn(tmpBin & 15, new int[] { 1, 2, 6, 9 })) { rel = rel * 0.4; } else if (Tools.isIn(tmpBin & 15, new int[] { 4, 10 })) { rel = rel * 0.5; } log.debug("Card(" + i + "): " + c + ", Rel=" + rel); relevance.add(new Double(rel)); } log.debug("cards =" + cards); log.debug("relevance=" + relevance); int maxIndex = findMax(relevance); log.debug("Max: " + maxIndex); skat.add(cards.remove(maxIndex)); relevance.remove(maxIndex); maxIndex = findMax(relevance); log.debug("Max: " + maxIndex); skat.add(cards.remove(maxIndex)); relevance.remove(maxIndex); log.debug("New skat: " + skat); } /** * Processes the skat for a Ramsch game * * @param cards * the player's hand * @param skat * the skat */ public void processSkat(final CardList cards, final CardList skat) { log.debug("\n\n================================================================"); testProcessor(cards, skat); log.debug("\n================================================================\n\n"); // TODO (mjl) check for potential Durchmarsch when processing the skat log.debug("My cards:" + cards + ", Skat=" + skat); // int cDiamonds = cards.getSuitCount(GameType.RAMSCH, Suit.DIAMONDS); // int cHearts = cards.getSuitCount(GameType.RAMSCH, Suit.HEARTS); // int cSpades = cards.getSuitCount(GameType.RAMSCH, Suit.SPADES); // int cClubs = cards.getSuitCount(GameType.RAMSCH, Suit.CLUBS); // // cDiamonds += skat.getSuitCount(GameType.RAMSCH, Suit.DIAMONDS); // cHearts += skat.getSuitCount(GameType.RAMSCH, Suit.HEARTS); // cSpades += skat.getSuitCount(GameType.RAMSCH, Suit.SPADES); // cClubs += skat.getSuitCount(GameType.RAMSCH, Suit.CLUBS); // // log.debug("#: C="+cClubs+", S="+cSpades+", H="+cHearts+", D="+cDiamonds); // // int diamonds = Helper.suitCardsToBinaryWithSkat(cards, skat, // Suit.DIAMONDS); // int hearts = Helper.suitCardsToBinaryWithSkat(cards, skat, // Suit.HEARTS); // int spades = Helper.suitCardsToBinaryWithSkat(cards, skat, // Suit.SPADES); // int clubs = Helper.suitCardsToBinaryWithSkat(cards, skat, // Suit.CLUBS); // // log.debug("cards: C="+bin(clubs,8)+", S="+bin(spades,8)+", H="+bin(hearts,8)+", D="+bin(diamonds,8)); // // int saveSuits = 0; // if(Tools.isIn((diamonds & 31), new int[] {7,11,13,15,19,21})) // saveSuits += 1; // if(Tools.isIn((hearts & 31), new int[] {7,11,13,15,19,21})) saveSuits // += 2; // if(Tools.isIn((spades & 31), new int[] {7,11,13,15,19,21})) saveSuits // += 4; // if(Tools.isIn((clubs & 31), new int[] {7,11,13,15,19,21})) saveSuits // += 8; // log.debug("saveSuits="+bin(saveSuits,4)); // // int possibleSkatSuits = 0; // if (cDiamonds > 0 && cDiamonds < 3 && (diamonds & 64) == 0 && // !Tools.isIn((diamonds & 7), new int[] {1,3,5})) possibleSkatSuits += // 1; // if (cHearts > 0 && cHearts < 3 && (hearts & 64) == 0 && // !Tools.isIn((hearts & 7), new int[] {1,3,5})) possibleSkatSuits += 2; // if (cSpades > 0 && cSpades < 3 && (spades & 64) == 0 && // !Tools.isIn((spades & 7), new int[] {1,3,5})) possibleSkatSuits += 4; // if (cClubs > 0 && cClubs < 3 && (clubs & 64) == 0 && // !Tools.isIn((clubs & 7), new int[] {1,3,5})) possibleSkatSuits += 8; // log.debug("possibleSkatSuits="+bin(possibleSkatSuits,4)); // // Card skatOne = skat.remove(0); // Card skatTwo = skat.remove(0); // // if (possibleSkatSuits > 0) { // Suit skatSuit = Helper.binaryToSuit(possibleSkatSuits); // if(skatSuit != null) { // // if more than one possible color: do nothing for the time being // // TODO (mjl): skat processing with more than one possible color // log.debug("More than one possible color found..."); // if(skatOne.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatOne); // } else { // skat.add(skatOne); // } // if(skatTwo.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatTwo); // } else { // skat.add(skatTwo); // } // } // else { // log.debug("Color for skat:"+skatSuit); // if(skatOne.getSuit() == skatSuit || // cards.getSuitCount(GameType.RAMSCH, skatSuit)<1) { // if(skatOne.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatOne); // } else { // skat.add(skatOne); // } // } else { // skat.add(cards.remove(cards.getFirstIndexOfSuit(skatSuit))); // cards.add(skatOne); // } // if(skatTwo.getSuit()==skatSuit || cards.getSuitCount(GameType.RAMSCH, // skatSuit)<1) { // if(skatTwo.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatTwo); // } else { // skat.add(skatTwo); // } // } else { // skat.add(cards.remove(cards.getFirstIndexOfSuit(skatSuit))); // cards.add(skatTwo); // } // } // } else { // // if more than one possible color: do nothing for the time being // // TODO: skat processing with no possible color from the first // iteration // if(skatOne.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatOne); // } else { // skat.add(skatOne); // } // if(skatTwo.getRank()==Rank.JACK) { // int index = 0; // while(cards.get(index).getRank()==Rank.JACK) index++; // skat.add(cards.remove(index)); // cards.add(skatTwo); // } else { // skat.add(skatTwo); // } // } log.debug("Done - my cards:" + cards + ", Skat=" + skat); } /** * Decides, whether the AI player should look at the skat or rather play * hand * * @param cards * the player's hand * @return true, if the player should look at the skat */ public boolean lookAtSkat(final CardList cards) { return true; } private int pow(final int a, final int b) { int res = 1; for (int i = 0; i < b; i++) { res = res * a; } return res; } private String bin(final int i, final int bits) { StringBuffer sb = new StringBuffer(); for (int j = bits - 1; j >= 0; j--) { if ((i & pow(2, j)) > 0) { sb.append("X"); } else { sb.append("-"); } } return sb.toString(); } private int findMax(final Vector<Double> list) { int res = 0; int pos = 1; while (list.size() > pos) { if (list.get(pos).doubleValue() > list.get(res).doubleValue()) { res = pos; } pos++; } return res; } }