00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <QPixmap>
00023 #include <QTimer>
00024
00025
00026 #include <kdebug.h>
00027
00028
00029 #include "lskatglobal.h"
00030 #include "aiinput.h"
00031 #include "player.h"
00032 #include "deck.h"
00033
00034
00035
00036 AiInput::AiInput(EngineTwo* engine, QObject* parent)
00037 : AbstractInput(parent)
00038 {
00039
00040 mEngine = engine;
00041 }
00042
00043
00044
00045 void AiInput::setInputAllowed(bool allowed)
00046 {
00047 AbstractInput::setInputAllowed(allowed);
00048 if (allowed) QTimer::singleShot(1000, this, SLOT(aiTurn()));
00049 }
00050
00051
00052
00053 void AiInput::aiTurn()
00054 {
00055
00056 if (!mInputAllowed) return;
00057
00058 if (global_debug > 5) kDebug() << "==================================================="<<endl;
00059 if (global_debug > 5) kDebug() << "AI TURN START " <<mInputAllowed<< endl;
00060
00061
00062 if (mId != mEngine->currentPlayer())
00063 {
00064 kFatal() << "AI plays for wrong player " << endl;
00065 return;
00066 }
00067
00068
00069 AiInput::Board board = getBoardFromEngine();
00070 AiInput::Move move;
00071
00072
00073 if (mEngine->currentMovePhase() == EngineTwo::FirstPlayerTurn)
00074 {
00075 if (global_debug > 5) kDebug() << "Performing initiual move "<<mId << endl;
00076 move = initiateMove(mId, board);
00077 }
00078
00079 else
00080 {
00081 if (global_debug > 5) kDebug() << "Performing answer move "<<mId << endl;
00082 move = answerMove(mId, board);
00083 }
00084
00085
00086
00087 if (global_debug > 5) kDebug() << "AI player " << mId << " moves to " << move.move << endl;
00088 if (move.move>=0) emit signalPlayerInput(mId, mId, move.move);
00089 else kError() << "Illegal AI Move ??? " << endl;
00090 }
00091
00092
00093
00094 AiInput::Board AiInput::getBoardFromEngine()
00095 {
00096 Board b;
00097 for (int i=0; i<2; i++)
00098 {
00099 Player* p = mEngine->player(i);
00100 for (int c=0; c<16; c++)
00101 {
00102 int card = p->getCard(c);
00103 b.cards[i][c] = card;
00104 b.points[i] = p->points();
00105 }
00106 }
00107 b.whoseTurn = mEngine->currentPlayer();
00108 b.firstPlay = mEngine->currentMovePhase() == EngineTwo::FirstPlayerTurn;
00109 b.playedCard = mEngine->playedCard(0);
00110 return b;
00111 }
00112
00113
00114
00115 #define RATING_SCHWARZ 100000.0
00116 #define RATING_SCHNEIDER 70000.0
00117 #define RATING_WON 50000.0
00118 #define RATING_REMIS 20000.0
00119 #define RATING_ONE_POINT 500.0
00120
00121
00122 double AiInput::evaluteGame(int p, const AiInput::Board current)
00123 {
00124 double rating = 0.0;
00125
00126 if (current.points[p] == 120) rating += RATING_SCHWARZ;
00127 else if (current.points[p] >= 90) rating += RATING_SCHNEIDER;
00128 else if (current.points[p] > 60) rating += RATING_WON;
00129 else if (current.points[p] == 60) rating += RATING_REMIS;
00130
00131 if (current.points[1-p] == 120) rating -= RATING_SCHWARZ;
00132 else if (current.points[1-p] >= 90) rating -= RATING_SCHNEIDER;
00133 else if (current.points[1-p] > 60) rating -= RATING_WON;
00134 else if (current.points[1-p] == 60) rating -= RATING_REMIS;
00135
00136
00137 rating += (current.points[p]-current.points[1-p])*RATING_ONE_POINT;
00138 return rating;
00139 }
00140
00141
00142
00143 AiInput::Move AiInput::initiateMove(int p, const AiInput::Board& board)
00144 {
00145 AiInput::Move maxMove;
00146 maxMove.move = -1;
00147 maxMove.value = -100.0*RATING_SCHWARZ;
00148
00149
00150 for (int m=0; m<8; m++)
00151 {
00152 AiInput::Board current(board);
00153 int card = current.cards[p][m];
00154 current.cards[p][m] = -1;
00155 if (card < 0)
00156 {
00157 card = current.cards[p][m+8];
00158 current.cards[p][m+8] = -1;
00159 }
00160 if (card < 0) continue;
00161
00162 current.playedCard = card;
00163 if (global_debug > 5) kDebug() << "First mover try move on " << m << " ("<<Deck::name(card) <<endl;
00164 AiInput::Move answer = answerMove(1-p, current);
00165
00166 double rating = -answer.value;
00167 if (global_debug > 5) kDebug() << "First mover yields rating of " << rating << endl;
00168
00169 if (rating > maxMove.value)
00170 {
00171 maxMove.value = rating;
00172 maxMove.move = m;
00173 }
00174 }
00175
00176 return maxMove;
00177 }
00178
00179
00180
00181 AiInput::Move AiInput::answerMove(int p, const AiInput::Board& board)
00182 {
00183 AiInput::Move maxMove;
00184 maxMove.move = -1;
00185 maxMove.value = -100.0*RATING_SCHWARZ;
00186
00187
00188 for (int m=0; m<8; m++)
00189 {
00190 AiInput::Board current(board);
00191
00192
00193
00194
00195 int card = current.cards[p][m];
00196 current.cards[p][m] = -1;
00197 if (card < 0)
00198 {
00199 card = current.cards[p][m+8];
00200 current.cards[p][m+8] = -1;
00201 }
00202 if (card < 0) continue;
00203
00204
00205 if (!mEngine->isLegalMove(current.playedCard, card, p)) continue;
00206
00207
00208 int winner = mEngine->whoWonMove(current.playedCard, card);
00209 if (global_debug > 5)
00210 kDebug() << " Card " << m<< " (" << Deck::name(card) << ") is valid "
00211 << " countering " << Deck::name(current.playedCard)<<" with "
00212 << " winner (0:other, 1:we) " << winner << endl;
00213 int deltaPoints = 0;
00214 deltaPoints += Deck::getCardValue(current.playedCard);
00215 deltaPoints += Deck::getCardValue(card);
00216
00217 if (winner == 0)
00218 {
00219 current.points[1-p] += deltaPoints;
00220 }
00221
00222 else
00223 {
00224 current.points[p] += deltaPoints;
00225 }
00226
00227 double rating = evaluteGame(p, current);
00228
00229
00230 if (global_debug > 5)
00231 kDebug() << " Points after 2nd move "<<m<<" would be we: "
00232 << current.points[p] << " other: " << current.points[1-p]
00233 << " rating is thus " << rating << endl;
00234
00235 if (rating > maxMove.value)
00236 {
00237 maxMove.value = rating;
00238 maxMove.move = m;
00239 }
00240 }
00241 return maxMove;
00242 }
00243
00244
00245
00246 AiInput::Board::Board(const AiInput::Board& board)
00247 {
00248 for (int i=0;i<2;i++)
00249 {
00250 points[i] = board.points[i];
00251 for (int j=0;j<16;j++)
00252 {
00253 cards[i][j] = board.cards[i][j];
00254 }
00255 }
00256 playedCard = board.playedCard;
00257 whoseTurn = board.whoseTurn;
00258 firstPlay = board.firstPlay;
00259 }
00260
00261
00262 #include "aiinput.moc"