/* Euchre - a free as in freedom and as in beer version of the euchre card game Copyright 2002 C Nathan Buckles (nbuckles@bigfoot.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "Options.hpp" #include "ComputerPlayerMedium.hpp" ComputerPlayerMedium::ComputerPlayerMedium(Common::PlayerPosition myPos) : ComputerPlayer(myPos) {} ComputerPlayerMedium::~ComputerPlayerMedium() {} Common::Bid ComputerPlayerMedium::auction1(const Card& upCard, Common::PlayerPosition dealer) { /* take into account if we are the dealer that we will have upCard in our hand. This modifies itsHand, so make sure to set it back to copyHand before we return */ Hand copyHand = itsHand; Card copyCard = upCard; if (dealer == itsPos) { discard(copyCard); } int minPoints; if (dealer == itsPos || dealer == Common::getPartner(itsPos)) { minPoints = 33; } else { minPoints = 36; } /* adjust for aggression level */ minPoints -= (2* Options::get()->getAIAgg(itsPos)); int myPoints = itsHand.getValue(upCard.getSuit()); if (myPoints > minPoints) { if (myPoints > 40) { itsBid = Common::LONER; } else { itsBid = Common::PICKITUP; } } else { itsBid = Common::PASS; } /* reset itsHand */ itsHand = copyHand; /* reset loner to pickitup if we are the human's partner and we are not allowed to go loner */ if (itsBid == Common::LONER && itsPos == Common::NORTH) { if (Options::get()->getPartnerLoner() == 0) { LOG("AI going pickitup instead of loner!" << endl); itsBid = Common::PICKITUP; } } return itsBid; } Common::Bid ComputerPlayerMedium::auction2(Card& yourTrump, const Card& upCard, bool stuck) { Card t; Common::Bid bid; for (int i = Card::Diamonds; i <= Card::Spades; i++) { if (upCard.getSuit() == i) { continue; } t.setSuit((Card::Suit)i); bid = ComputerPlayerMedium::auction1(t, (Common::PlayerPosition) (itsPos + 1)); if (bid != Common::PASS) { yourTrump = t; break; } } /* if we are stuck with doing it and we didn't find a good suit, then just go with the highest scoring suit. */ if (stuck && bid == Common::PASS) { bid = Common::PICKITUP; yourTrump.setSuit(getStuckTrumpSuit(upCard.getSuit())); } itsBid = bid; return bid; } Card ComputerPlayerMedium::discard(Card& newCard) { Card ret; /* first option is to go void in a suit provided that suit is not trump and the single card is not an ACE */ for (int i = 0; i < Common::CARDS_PER_HAND; i++) { ret = itsHand.getCard(i); /* if not trump */ if (! ret.isSuit(Common::getTrump())) { /* and not an ACE */ if (ret.getNumber() != Card::Ace) { /* and there is only one of this suit */ if (itsHand.count(ret.getSuit()) == 1) { /* then replace that card and return */ itsHand.setCard(i, newCard); return ret; } } } } /* if we don't have any singletons then just return our lowest card */ ret = itsHand.getWorstCard(); itsHand.replaceCard(ret, newCard); return ret; } Card ComputerPlayerMedium::getCard(const Round& theRound, Common::PlayerPosition whoStarted) { /* logic is just a little more complicated than easy if we are the one leading if we have the highest or second highest card in a suit lead that else lead our worst card else if we are second if we can win the trick by following suit play our highest in this suit else if we can win the trick with trump play our lowest trump else play our lowest card (following suit if we can) else if we are third basically the same logic as second, but don't trump partner's Aces if they are winning. If we do play over our partner's winning card, make sure our card is at least 2 points better. else (we are fourth) if our partner isn't winning if we can win the trick win the trick with the lowest possible winner else play our lowest card (following suit if we can) else play our lowest card (following suit if we can) */ int cardsPlayed = (itsPos - whoStarted); if (cardsPlayed < 0) { cardsPlayed += Common::PLAYERS_PER_GAME; } LOG(" " << itsPos << " cardPlayed=" << cardsPlayed << endl); Card ret; if (cardsPlayed == 0) { /* if it's my lead */ ret = getCard1(theRound, whoStarted); } else if (cardsPlayed == 1) { /* if i'm second */ ret = getCard2(theRound, whoStarted); } else if (cardsPlayed == 2) { /* if i'm third */ ret = getCard3(theRound, whoStarted); } else { /* if i'm fourth */ ret = getCard4(theRound, whoStarted); } itsHand.removeCard(ret); return ret; } Card ComputerPlayerMedium::getCard1(const Round& theRound, Common::PlayerPosition whoStarted) { /* if we have an ace or a king lead that */ Card ret = itsHand.getBestNonTrump(); if (ret.getValue() >= Card::King) { return ret; } /* if we have the big trump lead that */ ret = itsHand.getBestCard(); if (ret.getValue() == Card::JackTrumpVal) { return ret; } /* if we're still here then we should lead low */ ret = itsHand.getWorstCard(); return ret; } /* This method could be simpler, but it's used by getCard3 and getCard4 in certain cases, so it is little more complicated to be a little more generic */ Card ComputerPlayerMedium::getCard2(const Round& theRound, Common::PlayerPosition whoStarted) { Card ret; Card winningCard; Card::Suit suitLed; Common::PlayerPosition winningPos; suitLed = theRound.getSuit(whoStarted); winningPos = theRound.getWinner(whoStarted, Common::getTrump()); winningCard = theRound.getCard(winningPos); if (itsHand.contains(suitLed)) { /* if we need to follow suit then play a winner if we can */ ret = itsHand.getBestCard(suitLed); /* if we can't win then play low */ if (ret.getValue() < winningCard.getValue()) { ret = itsHand.getWorstCard(suitLed); } } else { /* if we don't have any cards of the suit then win with the lowest trump we can */ int min_index = -1; int min_score = (Card::JackTrumpVal + 1); for (int i = 0; i < Common::CARDS_PER_HAND; i++) { Card t = itsHand.getCard(i); /* if the card is trump */ if (t.isSuit(Common::getTrump())) { /* and the card would win the trick */ if (t.getValue() > winningCard.getValue()) { /* and the card is the lowest we can play and still win */ if (t.getValue() < min_score) { min_score = t.getValue(); min_index = i; } } } } if (min_index != -1) { /* if we have a trump that will win */ ret = itsHand.getCard(min_index); } else { /* if we can't win with trump */ ret = itsHand.getWorstCard(); } } return ret; } Card ComputerPlayerMedium::getCard3(const Round& theRound, Common::PlayerPosition whoStarted) { Card ret; Card winningCard; Card::Suit suitLed; Common::PlayerPosition winningPos; suitLed = theRound.getSuit(whoStarted); winningPos = theRound.getWinner(whoStarted, Common::getTrump()); winningCard = theRound.getCard(winningPos); if (winningPos == Common::getPartner(itsPos)) { /* if our partner is winning so far */ if (itsHand.contains(suitLed)) { /* if we have the suit led */ ret = itsHand.getBestCard(suitLed); /* if our card is not at least two better then our partner's then try to duck (ie don't play an Ace on partner's King if we don't have too). */ if ((ret.getValue() - winningCard.getValue()) < 2) { ret = itsHand.getWorstCard(suitLed); } } else { /* if we don't have the suit then try to duck */ ret = itsHand.getWorstCard(); } } else { /* follow logic in getCard2() */ ret = getCard2(theRound, whoStarted); } return ret; } Card ComputerPlayerMedium::getCard4(const Round& theRound, Common::PlayerPosition whoStarted) { Card ret; Card winningCard; Card::Suit suitLed; Common::PlayerPosition winningPos; suitLed = theRound.getSuit(whoStarted); winningPos = theRound.getWinner(whoStarted, Common::getTrump()); winningCard = theRound.getCard(winningPos); if (winningPos == Common::getPartner(itsPos)) { /* if our partner is winning then duck */ if (itsHand.contains(suitLed)) { ret = itsHand.getWorstCard(suitLed); } else { ret = itsHand.getWorstCard(); } } else { /* follow the logic in getCard2() */ ret = getCard2(theRound, whoStarted); } return ret; }