kwin4proc.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           kproc4.cpp  -  description
00003                              -------------------
00004     begin                : Sun Apr 9 2000
00005     copyright            : (C) 2000 by Martin Heni
00006     email                : kde@heni-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 #include <time.h>
00023 
00024 #include <QDataStream>
00025 #include <QByteArray>
00026 #include <QBuffer>
00027 
00028 #include <kgamemessage.h>
00029 #include <kdebug.h>
00030 
00031 #include "kwin4proc.h"
00032 
00033 #define MIN_TIME 1  // sec
00034 
00035 #define MAXANZAHL 6 /* Maximal 6 Steine pro Reihe */
00036 #define WIN4 4      /* 4er Reihe hat gewonnen */
00037 #define MAXZUG 42   /* Soviele Zuege moeglich */
00038 #define FELD_OFF 10
00039 #define LOWERT -999999999L
00040 #define SIEG_WERT 9999999L
00041 
00042 
00043 #define START_REK 1    // (0) 1:Nur Stellungsbewertung bei Level 1
00044                        //     0:Level 1 schon eine Rekursion
00045 
00046 KComputer::KComputer()
00047 {
00048     InitField();
00049 
00050     const char *s1="7777776666666123456654321123456654321";
00051     const char *s2="0000000000000000000123456000000123456";
00052 
00053     unsigned int i;
00054     for (i=0;i<strlen(s1);i++)
00055       lenofrow[i]=s1[i]-'0';
00056     for (i=0;i<strlen(s2);i++)
00057       startofrow[i]=s2[i]-'0';
00058 
00059   connect(&proc,SIGNAL(signalCommand(QDataStream &,int ,int ,int )),
00060                    this,SLOT(slotCommand(QDataStream & ,int ,int ,int )));
00061   connect(&proc,SIGNAL(signalInit(QDataStream &,int)),
00062                    this,SLOT(slotInit(QDataStream & ,int )));
00063   connect(&proc,SIGNAL(signalTurn(QDataStream &,bool )),
00064                    this,SLOT(slotTurn(QDataStream & ,bool )));
00065   fprintf(stderr, "----------------->\nKComputer::Computer\n");
00066 }
00067 
00068 void KComputer::slotInit(QDataStream &in,int id)
00069 {
00070   fprintf(stderr,"----------------->\nKComputer::slotInit\nid:%d\n",id);
00071   /*
00072   QByteArray buffer;
00073   QDataStream out(buffer,QIODevice::WriteOnly);
00074   int msgid=KGameMessage::IdProcessQuery;
00075   out << (int)1;
00076   proc.sendSystemMessage(out,msgid,0);
00077   */
00078 }
00079 
00080 void KComputer::slotTurn(QDataStream &in,bool turn)
00081 {
00082   QByteArray buffer;
00083   QDataStream out(&buffer,QIODevice::WriteOnly);
00084   fprintf(stderr,"----------------->\nKComputer::slotTurn\nturn:%d\n",turn);
00085   if (turn)
00086   {
00087     // Create a move
00088     qint32 value=think(in,out,false);
00089     int id=KGameMessage::IdPlayerInput;
00090     proc.sendSystemMessage(out,id,0);
00091     sendValue(value);
00092     fprintf(stderr,"  KComputer::sendValue in turn:%d\n",value);
00093   }
00094   fflush(stderr);
00095 }
00096 
00097 void KComputer::sendValue(long value)
00098 {
00099   qint8 cid=1; // notifies our KGameIO that this is a value message
00100   int id=KGameMessage::IdProcessQuery;
00101   QByteArray buffer;
00102   QDataStream out(&buffer,QIODevice::WriteOnly);
00103   out << cid << ( qint32 )value;
00104   proc.sendSystemMessage(out,id,0);
00105   fprintf(stderr,"  KComputer::sendValue in sendValue:%ld\n",(long)value);
00106   fflush(stderr);
00107 }
00108 
00109 long KComputer::think(QDataStream &in,QDataStream &out,bool hint)
00110 {
00111   qint32 pl;
00112   qint32 move;
00113   qint32 tmp;
00114   in >> pl ;
00115   in >> tmp;
00116   aktzug=tmp;
00117   in >> tmp;
00118   // We need all the +1 because the main program has different defines
00119   // for the colors. And changing it here seems not to work....
00120   amZug=(Farbe)(tmp+1);
00121   in >> tmp;
00122   beginner=(Farbe)(tmp+1);
00123   in >> tmp;
00124   second=(Farbe)(tmp+1);
00125   in >> tmp;
00126   mymaxreklev=tmp;
00127   fprintf(stderr,"think: pl=%d, aktzug=%d amzug=%d begin=%d second=%d level=%d\n",
00128                  pl,aktzug,amZug,beginner,second,mymaxreklev);
00129 
00130   InitField();
00131 
00132   // Field as 42 qint8's
00133   int i,j;
00134   for (i=0;i<=SIZE_Y;i++)
00135   {
00136     for (j=0;j<=SIZE_X;j++)
00137     {
00138       qint8 col;
00139       in >> col;
00140       Farbe colour;
00141       if (col<2) colour=(Farbe)(col+1);
00142       else colour=(Farbe)col;
00143       DoMove(j,colour,feldmatrix,anzahlmatrix);
00144     }
00145   }
00146 
00147   for (i=0;i<=SIZE_Y;i++)
00148   {
00149     char tstr[1024];
00150     tstr[0]=0;
00151     for (j=0;j<=SIZE_X;j++)
00152     {
00153       sprintf(tstr+strlen(tstr),"%02d ", feldmatrix[i][j]);
00154     }
00155     fprintf(stderr,"%s\n",tstr);
00156   }
00157 
00158   in >> tmp;
00159   fprintf(stderr,"CHECKSUM=%ld should be 421256\n",(long)tmp);
00160 
00161   time_t timea,timee;
00162   timea=time(0);
00163 
00164   int mymove;
00165   mymove= GetCompMove();
00166 
00167   fprintf(stderr,"Computer sends move; to %d value=%ld\n",mymove,aktwert);
00168 
00169   timee=time(0);
00170   // Sleep a minimum amount to slow down moves
00171   if (timee-timea < MIN_TIME) sleep((MIN_TIME-(timee-timea)));
00172 
00173 
00174   move=mymove;
00175   out << pl << move;
00176   return aktwert;
00177 }
00178 
00179 void KComputer::slotCommand(QDataStream &in,int msgid,int receiver,int sender)
00180 {
00181   fprintf(stderr,"----------------->\nKComputer::slotCommand\nMsgid:%d\n",msgid);
00182   QByteArray buffer;
00183   QDataStream out(&buffer,QIODevice::WriteOnly);
00184   switch(msgid)
00185   {
00186     case 2:  // hint
00187     {
00188       qint8 cid=2;
00189       qint32 pl=0;
00190       qint32 move=3;
00191       out << cid;
00192       long value=think(in,out,true);
00193       out << ( qint32 )value;
00194       int id=KGameMessage::IdProcessQuery;
00195       proc.sendSystemMessage(out,id,0);
00196     }
00197     break;
00198     default:
00199       fprintf(stderr,"KComputer:: unknown command Msgid:%d\n",msgid);
00200   }
00201 }
00202 
00206 int KComputer::GetCompMove()
00207 {
00208   int cmove;
00209   long cmax,wert;
00210   int x;
00211   FARBE lfeld[SIZE_Y_ALL+1][SIZE_X+1];
00212   char lanzahl[SIZE_Y_ALL+1];
00213   Farbe farbe;
00214 
00215 
00216   farbe=amZug;
00217   cmove=-1; /* Kein Zug */
00218   cmax=LOWERT;
00219   for (x=0;x<=SIZE_X;x++)
00220   {
00221     if (anzahlmatrix[6+x]>=MAXANZAHL) continue;
00222    memcpy(lanzahl,anzahlmatrix,sizeof(lanzahl));
00223    memcpy(lfeld,feldmatrix,sizeof(lfeld));
00224 
00225    DoMove(x,farbe,lfeld,lanzahl);
00226    wert=Wertung(farbe,lfeld,lanzahl,START_REK,aktzug+1);
00227 
00228    if (wert>=cmax)
00229    {
00230     cmax=wert;
00231     cmove=x;
00232     if (cmax>=SIEG_WERT) break;
00233    }
00234   }/*next x*/
00235   aktwert=cmax;
00236   amZug=farbe; // Wertung changes amZug!
00237 return cmove;
00238 }
00239 
00240 long KComputer::Wertung(Farbe farbe,FARBE feld[][SIZE_X+1],char anzahl[],int reklev,int zug)
00241 {
00242   static long gaus[]={10,50,300,500,300,50,10};
00243   FARBE lfeld[SIZE_Y_ALL+1][SIZE_X+1];
00244   char lanzahl[SIZE_Y_ALL+1];
00245   long max,wert;
00246   int x;
00247   Farbe winner;
00248 
00249    winner=GameOver(feld,anzahl);
00250    if (winner!=Niemand)
00251    {
00252                 if (winner==farbe) return(SIEG_WERT);
00253         else return(-SIEG_WERT);
00254    }
00255    if (zug>=MAXZUG) return(0); /* Remis */
00256    if (reklev>=mymaxreklev)  return Bewertung(farbe,feld);
00257 
00258 
00259    farbe=SwitchPlayer(farbe);
00260    max=LOWERT;
00261    for (x=0;x<=SIZE_X;x++)
00262    {
00263           if (anzahl[6+x]>=MAXANZAHL) continue;
00264           memcpy(lfeld,feld,sizeof(lfeld));
00265     memcpy(lanzahl,anzahl,sizeof(lanzahl));
00266           DoMove(x,farbe,lfeld,lanzahl);
00267           wert=Wertung(farbe,lfeld,lanzahl,reklev+1,zug+1)+gaus[x];
00268           if (wert>=max)
00269           {
00270                 max=wert;
00271                 if (max>=SIEG_WERT) break;
00272           }
00273     }/*next x*/
00274     return(-max);
00275 }/*end wertung*/
00276 
00277 long KComputer::Bewertung(Farbe farbe,FARBE feld[][SIZE_X+1])
00278 {
00279 /* Abstand:              0    1    2    3    4    5    */
00280 static long myWERT[]={2200,600, 300,  75,  20,   0};
00281 //static long myWERT[]={0,0,0,0,0,0};
00282 /* Wieviele von Farbe:       0     1     2     3    4 */
00283 static long steinWERT[4][5]=
00284 {
00285         {     0,  500L, 40000L,200000L,SIEG_WERT}, // Leerfelder=0
00286         {     0,  500L,  8000L, 40000L,SIEG_WERT}, //           =1
00287         {     0,   00L,  4000L, 25000L,SIEG_WERT}, //                   =2
00288         {     0,   00L,  2000L, 12500L,SIEG_WERT}, //           =3
00289 };
00290   long gelb_wert,rot_wert,wert;
00291   int cntcol,cnt;
00292   Farbe color;
00293   FARBE field;
00294   int y,i,j;
00295         gelb_wert=random(2500);
00296         rot_wert=random(2500);
00297         for (y=0;y<=SIZE_Y_ALL;y++)
00298         {
00299                 if (lenofrow[y]<WIN4) continue;
00300                 for (i=0;i<=(lenofrow[y]-WIN4);i++)
00301                 {
00302                         color=Niemand;
00303             wert=0;
00304                         cntcol=0;
00305                         cnt=0;
00306                         for (j=0;j<WIN4;j++)
00307                         {
00308                                 field=feld[y][i+j+startofrow[y]];
00309                                 if ((Farbe)field==Rot)
00310                                 {
00311                                         if (color==Gelb) {color=Niemand;break;}
00312                                         cntcol++;
00313           color=Rot;
00314                                 }
00315                                 else if ((Farbe)field==Gelb)
00316                                 {
00317                                         if (color==Rot) {color=Niemand;break;}
00318                                         cntcol++;
00319           color=Gelb;
00320                                 }
00321                                 else
00322                                 {
00323                                         cnt+=field-FELD_OFF;
00324                                         wert+=myWERT[field-FELD_OFF];
00325                                 }
00326                         }/*next j */
00327       if (cnt>3) cnt=3;
00328                         if (color==Rot) rot_wert+=(wert+steinWERT[cnt][cntcol]);
00329                         else if (color==Gelb) gelb_wert+=(wert+steinWERT[cnt][cntcol]);
00330     }/*next i*/
00331         }/*next y*/
00332         if (farbe==Rot) wert=rot_wert-gelb_wert;
00333         else wert=gelb_wert-rot_wert;
00334 return(wert);
00335 }
00336 
00337 Farbe KComputer::GameOver(FARBE feld[][SIZE_X+1],char anzahl[])
00338 {
00339   Farbe thiscolor,field;
00340   int x,y,cnt;
00341   for (y=0;y<=SIZE_Y_ALL;y++)
00342   {
00343          if (anzahl[y]<WIN4) continue;
00344          if ( lenofrow[y]<WIN4 ) continue;
00345          cnt=0;
00346          thiscolor=Niemand;
00347          for (x=0;x<lenofrow[y];x++)
00348          {
00349            field=(Farbe)feld[y][x+startofrow[y]];
00350        if (field==thiscolor) cnt++;
00351        else {cnt=1;thiscolor=field;}
00352            if ( (cnt>=WIN4)&&( (thiscolor==Gelb)||(thiscolor==Rot) ) ) return(thiscolor);
00353      }/*next x */
00354   }/*next y*/
00355   return(Niemand);
00356 }
00357 
00358 Farbe KComputer::SwitchPlayer(Farbe m_amZug)
00359 {
00360   if (m_amZug==Niemand)
00361     m_amZug=amZug;
00362   if (m_amZug==Rot)
00363     amZug=Gelb;
00364   else if (m_amZug==Gelb)
00365      amZug=Rot;
00366   else amZug=beginner;
00367   return amZug;
00368 }
00369 
00370 void KComputer::DoMove(char move,Farbe farbe,FARBE feld[][SIZE_X+1],char anzahl[])
00371 {
00372   int x,i,y;
00373 
00374   if (farbe==Tip || farbe==Niemand) return ;  // no real move
00375   x=move;
00376   y=anzahl[6+move];
00377   feld[y][x]=farbe;
00378 
00379   //if (farbe==Tip || farbe==Niemand) return ;  // no real move
00380 
00381   feld[6+x][y]=farbe;
00382   feld[13+x+y][x]=farbe;
00383   feld[30+x-y][x]=farbe;
00384   anzahl[y]++;
00385   anzahl[6+x]++;
00386   anzahl[13+x+y]++;
00387   anzahl[30+x-y]++;
00388   for (i=y+1;i<=SIZE_Y;i++)
00389   {
00390      feld[i][x]--;
00391      feld[6+x][i]--;
00392      feld[13+x+i][x]--;
00393      feld[30+x-i][x]--;
00394   }
00395 }
00396 
00397 void KComputer::InitField() {
00398   int x,y;
00399   for (y=0;y<=SIZE_Y_ALL;y++)
00400     anzahlmatrix[y]=0;
00401   for (y=0;y<=SIZE_Y;y++)
00402   {
00403     for (x=0;x<=SIZE_X;x++)
00404     {
00405       feldmatrix[y][x]=(FARBE)(y+FELD_OFF);
00406       feldmatrix[6+x][y]=(FARBE)(y+FELD_OFF);
00407       feldmatrix[13+x+y][x]=(FARBE)(y+FELD_OFF);
00408       feldmatrix[30+x-y][x]=(FARBE)(y+FELD_OFF);
00409     }
00410   }/* next y */
00411 }
00412 
00413 long KComputer::random(long max)
00414 {
00415   long wert;
00416   wert=proc.random()->getLong(max);
00417   return wert;
00418 }
00419 
00420 // Main startup
00421 int main(int argc ,char * argv[])
00422 {
00423   // This is the computer player...it should do the calculation
00424   // It doesn't do much here
00425   fprintf(stderr,"Vor KComputer START *****************************************************\n");
00426   fflush(stderr);
00427   KComputer comp;
00428   fprintf(stderr,"Vor exec *************************\n");
00429   fflush(stderr);
00430   // And start the event loop
00431   comp.proc.exec(argc,argv);
00432   fprintf(stderr,"nach KComputer exec\n");
00433   return 1;
00434 }
00435 #include "kwin4proc.moc"

Generated on Sun Mar 4 10:56:43 2007 for KWin4 by  doxygen 1.4.6