From c90c389a8a8d9d8661e9772ec4144c5cf2039f23 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- lskat/lskatproc/lskatproc.cpp | 596 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 596 insertions(+) create mode 100644 lskat/lskatproc/lskatproc.cpp (limited to 'lskat/lskatproc/lskatproc.cpp') diff --git a/lskat/lskatproc/lskatproc.cpp b/lskat/lskatproc/lskatproc.cpp new file mode 100644 index 00000000..c1fdcfba --- /dev/null +++ b/lskat/lskatproc/lskatproc.cpp @@ -0,0 +1,596 @@ +/*************************************************************************** + lskatproc.cpp - description + ------------------- + begin : Sun Apr 9 2000 + copyright : (C) 2000 by Martin Heni + email : martin@heni-online.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "lskatproc.h" + +#define MIN_TIME 1000 // usec + +// ------------ class game --------------------------------- +lgame::lgame() +{ + int i; + for (i=0;i<14;i++) cardvalues[i]=0; + cardvalues[(int)Ace]=11; + cardvalues[(int)Ten]=10; + cardvalues[(int)King]=4; + cardvalues[(int)Queen]=3; + cardvalues[(int)Jack]=2; + curmove[0]=-1; + curmove[1]=-1; + score[0]=0; + score[1]=0; + level=0; + endgame=false; + for (i=0;i=0) played[card]=1; + } + } + } +} + +// Add value of both cards to the score of startplayer +void lgame::AddScore(int c1,int c2) +{ + score[startplayer]+=CardValue(c1); + score[startplayer]+=CardValue(c2); +} +// Switch the startplayer +void lgame::SwitchStartplayer() +{ + startplayer=1-startplayer; +} + +// pos=0..7, player=0..1 +void lgame::SetHeight(int player, int pos,int h) +{ + int i; + i=8*player+pos; + cardheight[i]=h; +} +bool lgame::LegalMove(int p1, int p2) +{ + CCOLOUR col1,col2,col3; + CCARD card1,card2,card3; + card1=(CCARD)((p1)/4); + col1=(CCOLOUR)((p1)%4); + card2=(CCARD)((p2)/4); + col2=(CCOLOUR)((p2)%4); + + // force trump colour + if (card1==Jack) col1=trump; + if (card2==Jack) col2=trump; + + // same colour always ok + if (col1==col2) return true; + + // Search for same colour + bool flag=true; + for (int i=0;i<8;i++) + { + int h,c; + h=GetHeight(1-startplayer,i); + if (h==0) continue; + c=GetCard(1-startplayer,i,h); + card3=(CCARD)((c)/4); + col3=(CCOLOUR)((c)%4); + if (card3==Jack) col3=trump; + + if (col3==col1) + { + flag=false; + break; + } + } + if (flag) return true; + + + return false; +} +int lgame::CardValue(int card) +{ + int card1; + + card1=card/4; + return cardvalues[card1]; +} +int lgame::WonMove(int c1,int c2) +{ + CCOLOUR col1,col2; + CCARD card1,card2; + + card1=(CCARD)((c1)/4); + col1=(CCOLOUR)((c1)%4); + card2=(CCARD)((c2)/4); + col2=(CCOLOUR)((c2)%4); + + // Two jacks + if (card1==Jack && card2==Jack) + { + if (col15) sc+=800; + + if (haveten[i]&&havecol[i]<2) + { + card=8*i+Ace; + if (!played[card] && !haveace[i]) sc-=2500; // free ten + } + if (haveace[i]) sc+=1500; // ace + if (havejack[i]) + { + if (trump==Grand) sc+=4000+300*(4-i); + else sc+=2700+100*(4-i); + } + } + // evaluate + sc+=trum1*2500; + if (trum1==0) sc-=7000; + else if (trum1==1) sc-=5000; + return sc; +} + +int lgame::Value(int player) +{ + int sc; + sc=0; + + // Someone won? + if (score[0]>90) sc+=90000; + else if (score[0]>60) sc+=70000; + else if (score[0]==60) sc+=40000; + + if (score[1]>90) sc-=90000; + else if (score[1]>60) sc-=70000; + else if (score[1]==60) sc-=40000; + + // Reward points + sc+=(score[0]-score[1])*650; + + // Calulate cards + sc+=Subvalue(0); + sc-=Subvalue(1); + + // random + sc+=random(500)-250; + + if (player==1) return -sc; + return sc; +} + + +// -------------class lskatproc ---------------------------- +lskatproc::lskatproc() + : KInputChildProcess(4096) +{ + + initrandom(); +} + +lskatproc::~lskatproc(){ +} + + + +bool lskatproc::ReceiveMsg(KEMessage* msg,int id) +{ +// time_t timee,timea; +short x,y; + + SendDebug("Receiv Msg"); + // end of process + if (msg->HasKey(QCString("Terminate"))) + { + Terminate(); + } + // Init of process + if (msg->HasKey(QCString("Init"))) + { + // No init necessary + } + // Make a move + if (msg->HasKey(QCString("Cards"))) + { + SendDebug("Process HasKey(Cards)"); + // new game object + lgame game; + // extract data from message + game.ExtractGame(msg); + game.Init(); // must be AFTER ExtractGame + + // Debug stuff only + sprintf(buf,"Trump=%d move=%d sc1=%d sc2=%d", + game.trump,game.curmove[1-game.currentplayer],game.score[0],game.score[1]); + SendDebug(buf); + + if (game.currentplayer==0 && game.startplayer==0) + sprintf(buf,"+++ Computer ACTS as player ONE\n"); + else if (game.currentplayer==0 && game.startplayer==1) + sprintf(buf,"+++ Computer REACTS as player ONE\n"); + else if (game.currentplayer==1 && game.startplayer==1) + sprintf(buf,"+++ Computer ACTS as player TWO\n"); + else + sprintf(buf,"+++ Computer REACTS as player TWO\n"); + SendDebug(buf); + + // fills data + x=0;y=0; + GetComputerMove(game,x,y,0); + sprintf(buf,"Computer move player=%d x=%d y=%d",game.currentplayer,x,y); + SendDebug(buf); + + + // report move + msg->RemoveAll(); + msg->AddData(QCString("Move"),game.currentplayer); + msg->AddData(QCString("MoveX"),x); + msg->AddData(QCString("MoveY"),y); + + //timee=time(0); + // Sleep a minimum amount to slow down moves + //if ( 1000*(timee-timea) < MIN_TIME) usleep((MIN_TIME-1000*(timee-timea))); + SendDebug("Sending move back to main"); + + if (!IsTerminated()) SendMsg(msg); + fflush(stdout); // I do not know why it is needed..send does it too? + } + + return true; +} + + +/* --------------------------------------------------------------------------- */ +/* Computer Routinen */ +/* --------------------------------------------------------------------------- */ + +// extract game from msg +int lgame::ExtractGame(KEMessage *msg) +{ + int i; + short tmp; + char *p; + int size; + + msg->GetData(QCString("Startplayer"),startplayer); + msg->GetData(QCString("CurrentPlayer"),currentplayer); + msg->GetData(QCString("Cards"),p,size); + msg->GetData(QCString("Level"),level); + level--; // start with level 0 + for (i=0;iGetData(QCString("Height"),p,size); + for (i=0;iGetData(QCString("Trump"),tmp); + trump=(CCOLOUR)tmp; + short mm; + msg->GetData(QCString("CurrentMove"),mm); + curmove[1-currentplayer]=(int)mm; + curmove[currentplayer]=-1; + msg->GetData(QCString("No"),movenumber); + msg->GetData(QCString("Sc1"),score[0]); + msg->GetData(QCString("Sc2"),score[1]); + return 1; +} + +long lgame::random(long max) +{ +double value; +int r; + r=rand(); + value=(double)((double)r*(double)max)/(double)RAND_MAX; + return (long)value; +} + +void lskatproc::initrandom() +{ + srand( (unsigned)time( NULL ) ); // randomize +} + + +int lskatproc::GetComputerMove(lgame game,short &x,short &y,int rek) +{ + int i,maxvalue,maxmove,h,c; + //short oldscore; + bool startflag; + int startplayer; + int value; + lgame cgame; + char sbuf[100]; + short mx,my; + + + for (i=0;i<2*rek;i++) sbuf[i]=' '; + sbuf[2*rek]=0; + + x=0; + y=0; + if (game.currentplayer==game.startplayer) startflag=true; + else startflag=false; + + startplayer=game.startplayer; + + maxmove=0; + maxvalue=LOWERT; + + sprintf(buf,"%s:Prepareing computer move (cur=%d) startflag=%d", + sbuf,game.currentplayer,startflag); + //SendDebug(buf); + for (i=0;i<8;i++) + { + sprintf(buf,"%s:Checking for card %d of player %d\n",sbuf,i,game.currentplayer); + // SendDebug(buf); + cgame=game; + h=cgame.GetHeight(cgame.currentplayer,i); + if (h<1) + { + sprintf(buf,"%s:i=%d:: no cards left",sbuf,i); + // SendDebug(buf); + continue; // no cards left + } + c=cgame.GetCard(cgame.currentplayer,i,h); + if (cgame.MakeMove(c,i)<0) + { + sprintf(buf,"%s:i=%d:: no legal move c1=%d c2=%d", + sbuf,i,cgame.curmove[cgame.startplayer],c); + // SendDebug(buf); + continue; // wrong card + } + if (!startflag) // we are second + { + sprintf(buf,"LEVEL %d %d",cgame.level,rek); + SendDebug(buf); + // Still recursion necessary and game not yet ended? + if (rek<2*cgame.level && !cgame.endgame) + { + // If we have the same startplayer the movesequence + // is not switched and we can take the negative value + // otherwise we play again, and have to take the poitiv value + if (cgame.startplayer==startplayer) + { + value=-GetComputerMove(cgame,mx,my,rek+1); + // if (value==-LOWERT) value=LOWERT; // no move possible + } + else + value=GetComputerMove(cgame,mx,my,rek+1); + } + else // evaluate position + { + value=cgame.Value(1-startplayer); + } + } + else // we are first player + { + // Alwayss the other player moves now + value=-GetComputerMove(cgame,mx,my,rek+1); + } + + sprintf(buf,"%s:i=%d:: Value=%d",sbuf,i,value); + SendDebug(buf); + + if (value>maxvalue) + { + maxvalue=value; + maxmove=i; + } + } + x=maxmove%4; + y=maxmove/4; + return maxvalue; +} + +void lskatproc::SendDebug(const char *s) +{ + KEMessage *msg=new KEMessage; + msg->AddData(QCString("Debug"),s); +// msg->AddData("KLogSendMsg","debug.log"); +// DEBUG +// SendMsg(msg); +// printf("%s\n",s); + + delete msg; +} -- cgit v1.2.1