/*************************************************************************** kproc4.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 "twin4proc.h" #include #include #include #include #include #include #define MIN_TIME 1 // sec #define NOOFPLAYER 2/* Zwei Spieler */ #define MAXANZAHL 6 /* Maximal 6 Steine pro Reihe */ #define WIN4 4 /* 4er Reihe hat gewonnen */ #define MAXZUG 42 /* Soviele Zuege moeglich */ #define FELD_OFF 10 #define LOWERT -999999999L #define SIEG_WERT 9999999L #define START_REK 1 // (0) 1:Nur Stellungsbewertung bei Level 1 // 0:Level 1 schon eine Rekursion KComputer::KComputer() : TQObject(0,0) { InitField(); const char *s1="7777776666666123456654321123456654321"; const char *s2="0000000000000000000123456000000123456"; unsigned int i; for (i=0;i\nKComputer::Computer\n"); } void KComputer::slotInit(TQDataStream &in,int id) { fprintf(stderr,"----------------->\nKComputer::slotInit\nid:%d\n",id); /* TQByteArray buffer; TQDataStream out(buffer,IO_WriteOnly); int msgid=KGameMessage::IdProcessQuery; out << (int)1; proc.sendSystemMessage(out,msgid,0); */ } void KComputer::slotTurn(TQDataStream &in,bool turn) { TQByteArray buffer; TQDataStream out(buffer,IO_WriteOnly); fprintf(stderr,"----------------->\nKComputer::slotTurn\nturn:%d\n",turn); if (turn) { // Create a move long value=think(in,out,false); int id=KGameMessage::IdPlayerInput; proc.sendSystemMessage(out,id,0); sendValue(value); } } void KComputer::sendValue(long value) { TQ_INT8 cid=1; // notifies our KGameIO that this is a value message int id=KGameMessage::IdProcessQuery; TQByteArray buffer; TQDataStream out(buffer,IO_WriteOnly); out << cid << value; proc.sendSystemMessage(out,id,0); } long KComputer::think(TQDataStream &in,TQDataStream &out,bool hint) { TQ_INT32 pl; TQ_INT32 move; TQ_INT32 tmp; in >> pl ; in >> tmp; aktzug=tmp; in >> tmp; // We need all the +1 because the main programm has different defines // for the colours. And chaning it here seems not to work.... amZug=(Farbe)(tmp+1); in >> tmp; beginner=(Farbe)(tmp+1); in >> tmp; second=(Farbe)(tmp+1); in >> tmp; mymaxreklev=tmp; fprintf(stderr,"think: pl=%d, aktzug=%d amzug=%d begin=%d second=%d level=%d\n", pl,aktzug,amZug,beginner,second,mymaxreklev); InitField(); // Field as 42 TQ_INT8's int i,j; for (i=0;i<=SIZE_Y;i++) { for (j=0;j<=SIZE_X;j++) { TQ_INT8 col; in >> col; Farbe colour; if (col<2) colour=(Farbe)(col+1); else colour=(Farbe)col; DoMove(j,colour,feldmatrix,anzahlmatrix); } } for (i=0;i<=SIZE_Y;i++) { char tstr[1024]; tstr[0]=0; for (j=0;j<=SIZE_X;j++) { sprintf(tstr+strlen(tstr),"%02d ", feldmatrix[i][j]); } fprintf(stderr,"%s\n",tstr); } in >> tmp; fprintf(stderr,"CHECKSUM=%ld should be 421256\n",(long)tmp); time_t timea,timee; timea=time(0); int mymove; mymove= GetCompMove(); fprintf(stderr,"Computermove to %d value=%ld\n",mymove,aktwert); timee=time(0); // Sleep a minimum amount to slow down moves if (timee-timea < MIN_TIME) sleep((MIN_TIME-(timee-timea))); move=mymove; if (hint) { out << pl << move; } else { out << pl << move; } return aktwert; } void KComputer::slotCommand(TQDataStream &in,int msgid,int receiver,int sender) { fprintf(stderr,"----------------->\nKComputer::slotCommand\nMsgid:%d\n",msgid); TQByteArray buffer; TQDataStream out(buffer,IO_WriteOnly); switch(msgid) { case 2: // hint { TQ_INT8 cid=2; TQ_INT32 pl=0; TQ_INT32 move=3; out << cid; long value=think(in,out,true); out << value; int id=KGameMessage::IdProcessQuery; proc.sendSystemMessage(out,id,0); } break; default: fprintf(stderr,"KComputer:: unknown command Msgid:%d\n",msgid); } } /** * Computer Routinen */ int KComputer::GetCompMove() { int cmove; long cmax,wert; int x; FARBE lfeld[SIZE_Y_ALL+1][SIZE_X+1]; char lanzahl[SIZE_Y_ALL+1]; Farbe farbe; farbe=amZug; cmove=-1; /* Kein Zug */ cmax=LOWERT; for (x=0;x<=SIZE_X;x++) { if (anzahlmatrix[6+x]>=MAXANZAHL) continue; memcpy(lanzahl,anzahlmatrix,sizeof(lanzahl)); memcpy(lfeld,feldmatrix,sizeof(lfeld)); DoMove(x,farbe,lfeld,lanzahl); wert=Wertung(farbe,lfeld,lanzahl,START_REK,aktzug+1); if (wert>=cmax) { cmax=wert; cmove=x; if (cmax>=SIEG_WERT) break; } }/*next x*/ aktwert=cmax; amZug=farbe; // Wertung changes amZug! return cmove; } long KComputer::Wertung(Farbe farbe,FARBE feld[][SIZE_X+1],char anzahl[],int reklev,int zug) { static long gaus[]={10,50,300,500,300,50,10}; FARBE lfeld[SIZE_Y_ALL+1][SIZE_X+1]; char lanzahl[SIZE_Y_ALL+1]; long max,wert; int x; Farbe winner; winner=GameOver(feld,anzahl); if (winner!=Niemand) { if (winner==farbe) return(SIEG_WERT); else return(-SIEG_WERT); } if (zug>=MAXZUG) return(0); /* Remis */ if (reklev>=mymaxreklev) return Bewertung(farbe,feld); farbe=SwitchPlayer(farbe); max=LOWERT; for (x=0;x<=SIZE_X;x++) { if (anzahl[6+x]>=MAXANZAHL) continue; memcpy(lfeld,feld,sizeof(lfeld)); memcpy(lanzahl,anzahl,sizeof(lanzahl)); DoMove(x,farbe,lfeld,lanzahl); wert=Wertung(farbe,lfeld,lanzahl,reklev+1,zug+1)+gaus[x]; if (wert>=max) { max=wert; if (max>=SIEG_WERT) break; } }/*next x*/ return(-max); }/*end wertung*/ long KComputer::Bewertung(Farbe farbe,FARBE feld[][SIZE_X+1]) { /* Abstand: 0 1 2 3 4 5 */ static long myWERT[]={2200,600, 300, 75, 20, 0}; //static long myWERT[]={0,0,0,0,0,0}; /* Wieviele von Farbe: 0 1 2 3 4 */ static long steinWERT[4][5]= { { 0, 500L, 40000L,200000L,SIEG_WERT}, // Leerfelder=0 { 0, 500L, 8000L, 40000L,SIEG_WERT}, // =1 { 0, 00L, 4000L, 25000L,SIEG_WERT}, // =2 { 0, 00L, 2000L, 12500L,SIEG_WERT}, // =3 }; long gelb_wert,rot_wert,wert; int cntcol,cnt; Farbe color; FARBE field; int y,i,j; gelb_wert=random(2500); rot_wert=random(2500); for (y=0;y<=SIZE_Y_ALL;y++) { if (lenofrow[y]3) cnt=3; if (color==Rot) rot_wert+=(wert+steinWERT[cnt][cntcol]); else if (color==Gelb) gelb_wert+=(wert+steinWERT[cnt][cntcol]); }/*next i*/ }/*next y*/ if (farbe==Rot) wert=rot_wert-gelb_wert; else wert=gelb_wert-rot_wert; return(wert); } Farbe KComputer::GameOver(FARBE feld[][SIZE_X+1],char anzahl[]) { Farbe thiscolor,field; int x,y,cnt; for (y=0;y<=SIZE_Y_ALL;y++) { if (anzahl[y]=WIN4)&&( (thiscolor==Gelb)||(thiscolor==Rot) ) ) return(thiscolor); }/*next x */ }/*next y*/ return(Niemand); } Farbe KComputer::SwitchPlayer(Farbe m_amZug) { if (m_amZug==Niemand) m_amZug=amZug; if (m_amZug==Rot) amZug=Gelb; else if (m_amZug==Gelb) amZug=Rot; else amZug=beginner; return amZug; } void KComputer::DoMove(char move,Farbe farbe,FARBE feld[][SIZE_X+1],char anzahl[]) { int x,i,y; if (farbe==Tip || farbe==Niemand) return ; // no real move x=move; y=anzahl[6+move]; feld[y][x]=farbe; //if (farbe==Tip || farbe==Niemand) return ; // no real move feld[6+x][y]=farbe; feld[13+x+y][x]=farbe; feld[30+x-y][x]=farbe; anzahl[y]++; anzahl[6+x]++; anzahl[13+x+y]++; anzahl[30+x-y]++; for (i=y+1;i<=SIZE_Y;i++) { feld[i][x]--; feld[6+x][i]--; feld[13+x+i][x]--; feld[30+x-i][x]--; } } void KComputer::InitField() { int x,y; for (y=0;y<=SIZE_Y_ALL;y++) anzahlmatrix[y]=0; for (y=0;y<=SIZE_Y;y++) { for (x=0;x<=SIZE_X;x++) { feldmatrix[y][x]=(FARBE)(y+FELD_OFF); feldmatrix[6+x][y]=(FARBE)(y+FELD_OFF); feldmatrix[13+x+y][x]=(FARBE)(y+FELD_OFF); feldmatrix[30+x-y][x]=(FARBE)(y+FELD_OFF); } }/* next y */ } long KComputer::random(long max) { long wert; wert=proc.random()->getLong(max); return wert; } // Main startup int main(int argc ,char * argv[]) { // This is the computer player...it should do the calulation // It doesn't do much here fprintf(stderr,"Vor KComputer\n"); fflush(stderr); KComputer comp; fprintf(stderr,"Vor exec\n"); // And start the event loop comp.proc.exec(argc,argv); fprintf(stderr,"nach exec\n"); return 1; } #include "twin4proc.moc"