00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00036 #define WIN4 4
00037 #define MAXZUG 42
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
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
00073
00074
00075
00076
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
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;
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
00119
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
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
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:
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;
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 }
00235 aktwert=cmax;
00236 amZug=farbe;
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);
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 }
00274 return(-max);
00275 }
00276
00277 long KComputer::Bewertung(Farbe farbe,FARBE feld[][SIZE_X+1])
00278 {
00279
00280 static long myWERT[]={2200,600, 300, 75, 20, 0};
00281
00282
00283 static long steinWERT[4][5]=
00284 {
00285 { 0, 500L, 40000L,200000L,SIEG_WERT},
00286 { 0, 500L, 8000L, 40000L,SIEG_WERT},
00287 { 0, 00L, 4000L, 25000L,SIEG_WERT},
00288 { 0, 00L, 2000L, 12500L,SIEG_WERT},
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 }
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 }
00331 }
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 }
00354 }
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 ;
00375 x=move;
00376 y=anzahl[6+move];
00377 feld[y][x]=farbe;
00378
00379
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 }
00411 }
00412
00413 long KComputer::random(long max)
00414 {
00415 long wert;
00416 wert=proc.random()->getLong(max);
00417 return wert;
00418 }
00419
00420
00421 int main(int argc ,char * argv[])
00422 {
00423
00424
00425 fprintf(stderr,"Vor KComputer START *****************************************************\n");
00426 fflush(stderr);
00427 KComputer comp;
00428 fprintf(stderr,"Vor exec *************************\n");
00429 fflush(stderr);
00430
00431 comp.proc.exec(argc,argv);
00432 fprintf(stderr,"nach KComputer exec\n");
00433 return 1;
00434 }
00435 #include "kwin4proc.moc"