bool Scene::ValidMove(const Position& a, const Position& b, const int ballStatus) const { double length = Position((b-a)).Norm(); if(length<=0.1) return true; Position mid = Position((a+b))/2.; if((ballStatus & TRANSPORTING_BALL) != 0) mid = robot.CorrectBallPos(mid); if(Collision(mid, ballStatus)) return false; return ValidMove(a, mid, ballStatus) && ValidMove(mid, b, ballStatus); /*if(((IGNORE_BALL_ENVIRONMENT_COLLISION | TAKING_BALL) & ballStatus) == 0 && !ValidMoveBallEnvironment(a, b)) return false; if((IGNORE_BALL_ROBOT_COLLISION & ballStatus) == 0) { if((TRANSPORTING_BALL & ballStatus) != 0 && !ValidMoveMovingBallRobot(a, b)) return false; } return ValidMoveRobotRobot(a, b) && ValidMoveRobotEnvironment(a, b);*/ }
// Determine if any valid moves are possible for either player bool SimpleGoPanel::ValidMoveExists() { char temp[21][21]; for(int i=1; i<=boardsize; i++) for(int j=1; j<=boardsize; j++) { memcpy(temp, board, BOARDMEMORYLEN); if(ValidMove(temp, i, j, BLACK)) return true; memcpy(temp, board, BOARDMEMORYLEN); if(ValidMove(temp, i, j, WHITE)) return true; } return false; }
// During idle time make random moves if Random! has been selected void SimpleGoPanel::Idle(wxIdleEvent& event) { if(!frame->playmenu->IsChecked(ID_RANDOM)) { if(!gnugopause && ((curmove%2==1 && frame->whitelevel>0) || (curmove%2==0 && frame->blacklevel>0))) frame->MakeGNUGoMove(); return; } int x = 1+rand()%boardsize, y = 1+rand()%boardsize; char attempts[21][21], temp[21][21]; memset(attempts, 0, BOARDMEMORYLEN); int count = 0; while(count<boardsize*boardsize) { while(attempts[x][y]==1) { x = 1+rand()%boardsize; y = 1+rand()%boardsize; } memcpy(temp, board, BOARDMEMORYLEN); if(ValidMove(temp, x, y, curmove%2+1)) { MakeMove(x, y); #ifdef __WXMSW__ event.RequestMore(); #endif return; } count++; attempts[x][y] = 1; } MakePass(); #ifdef __WXMSW__ event.RequestMore(); #endif }
vect GenDest(vect token, T_board board){ int i, j, k, exit=1, h=1; while(exit){ h=1; k=rand()%4; switch(k){ case 0: h=-1; case 1: i=h*(rand()%3); j=h*(rand()%3); break; case 2: h=-1; case 3: i=h*-(rand()%2); j=h*(rand()%2); break; } if(ValidMove(token, (vect){token.x+i, token.y+j}, board)!=INVALIDE){ exit=0; } } return (vect){token.x+i, token.y+j}; }
std::vector<int> Chariot::PossibleMovesAsVector(std::vector< std::vector<Piece*> >& pieces) { _pieces = pieces; _possibleMovesAsVector.clear(); for (int i = 0 - Config::NUM_OF_ROW; i < Config::NUM_OF_ROW; i++) { if (ValidMove(_row + i, _col)) { _possibleMovesAsVector.push_back((_row + i) * 10 + _col); } } for (int i = 0 - Config::NUM_OF_COL; i < Config::NUM_OF_COL; i++) { if (ValidMove(_row, _col + i)) { _possibleMovesAsVector.push_back(_row * 10 + _col + i); } } return _possibleMovesAsVector; }
std::vector<int> Elephant::PossibleMovesAsVector(std::vector< std::vector<Piece*> >& pieces) { _pieces = pieces; _possibleMovesAsVector.clear(); if (ValidMove(_row - 2, _col - 2)) { _possibleMovesAsVector.push_back((_row - 2) * 10 + _col - 2); } if (ValidMove(_row + 2, _col - 2)) { _possibleMovesAsVector.push_back((_row + 2) * 10 + _col - 2); } if (ValidMove(_row - 2, _col + 2)) { _possibleMovesAsVector.push_back((_row - 2) * 10 + _col + 2); } if (ValidMove(_row + 2, _col + 2)) { _possibleMovesAsVector.push_back((_row + 2)* 10 + _col + 2); } return _possibleMovesAsVector; }
/* ******************************************************************************** * * * StorePV() is called by Iterate() to insert the PV moves so they will be * * searched before any other moves. * * * ******************************************************************************** */ void StorePV(int ply, int wtm) { register BITBOARD temp_hash_key; register HASH_ENTRY *htable; /* ---------------------------------------------------------- | | | make sure the move being stored is legal, so that a | | bad move doesn't get into hash table. | | | ---------------------------------------------------------- */ if (!ValidMove(ply,wtm,pv[ply].path[ply])) { printf("\ninstalling bogus move...ply=%d\n",ply); printf("installing %s\n",OutputMove(&pv[ply].path[ply],ply,wtm)); return; } /* ---------------------------------------------------------- | | | first, compute the initial hash address and choose | | which hash table (based on color) to probe. | | | ---------------------------------------------------------- */ temp_hash_key=HashKey; htable=((wtm) ? trans_ref_wb : trans_ref_bb)+(((int) temp_hash_key)&hash_maskb); temp_hash_key=temp_hash_key>>16; /* ---------------------------------------------------------- | | | now "fill in the blank" and build a table entry from | | current search information. | | | ---------------------------------------------------------- */ htable->word1=Shiftl((BITBOARD) 65536,21); htable->word1=Or(htable->word1,Shiftl((BITBOARD) ((transposition_id<<2)+WORTHLESS),59)); htable->word1=Or(htable->word1,(BITBOARD) pv[ply].path[ply]); htable->word2=temp_hash_key; }
std::vector<Position> Scene::Optimize(std::vector<FullNode> path) { int optimization=0; std::vector<Position> retour; for(auto p : path) retour.push_back(p.pos); for(int essai=0; essai<NB_TRY; essai++) { int a = rand()%retour.size()-1; int b = rand()%retour.size()-1; if(a==b) continue; if(a>b) { int c=a; a=b; b=c; } double c= double(rand())/double(RAND_MAX); double d= double(rand())/double(RAND_MAX); Position start = retour[a]+(retour[a+1]-retour[a])*c; Position end = retour[b]+(retour[b+1]-retour[b])*d; if(ValidMove(start,end)) { retour.erase(retour.begin()+a+1,retour.begin()+b+1); retour.insert(retour.begin()+a+1,end); retour.insert(retour.begin()+a+1,start); optimization++; if(optimization>20) break; } } return retour; }
// Make a move on cell (x, y) if legal, and update the current board info and history void SimpleGoPanel::MakeMove(int x, int y) { if(x<=0 || y<=0 || x>boardsize || y>boardsize) return; char temp[21][21]; memcpy(temp, board, BOARDMEMORYLEN); if(ValidMove(temp, x, y, curmove%2+1)) { board[x][y] = curmove%2+1; wxClientDC dc(this); DrawStone(dc, x, y, curmove%2+1); if(memcmp(temp, board, BOARDMEMORYLEN)) { for(int i=0; i<21; i++) for(int j=0; j<21; j++) if(temp[i][j]!=board[i][j]) DrawStone(dc, i, j, temp[i][j]); memcpy(board, temp, BOARDMEMORYLEN); if(board[x][y] == EMPTY) frame->madesuicide = true; } if(gnugoscore) { gnugoscore = false; DrawBoard(dc, board); } curmove++; history = (char(*)[21][21])realloc(history, (curmove+1)*BOARDMEMORYLEN); memcpy(history[curmove], board, BOARDMEMORYLEN); movelist = (pos*)realloc(movelist, curmove*sizeof(pos)); movelist[curmove-1].x = x; movelist[curmove-1].y = y; totmove = curmove; UpdateStatus(); gnugopause = false; } }
void ListAvailableMoves() { //Mise à 0 du nombre de mouvements disponibles cptAvailableMoves = 0; int i,j,k; /* On recherche parmis toutes les cases du plateau, celles disponibles */ for(i=0;i<10;i++){ for(j=0;j<10;j++){ SBox current = currentGame->board[i][j]; //Si case contient une pièce qui est de la couleur de l'IA if( current.piece != EPnone && current.content == color ){ //On teste toutes les cases ou l'on peut se déplacer SBox nextBox; for( k=0;k<4;k++ ){ int endL; int endC; switch(k) { case 0: if( i==0 ){ continue; } //Si le pion ne peut reculer endL = i-1; endC = j; break; case 1: if( j==0 ){ continue; } //Si le pion ne peut se déplacer à gauche endL = i; endC = j-1; break; case 2: if( i==9 ){ continue; } //Si le pion ne peut avancer endL = i+1; endC = j; break; case 3: if( j==9 ){ continue; } //Si le pion ne peut se déplacer à droite endL = i; endC = j+1; break; } nextBox = currentGame->board[endL][endC]; MoveAvailable moveAvailable; SMove move; move.start.line = i; move.start.col = j; move.end.line = endL; move.end.col = endC; moveAvailable.move = move; //On vérifie que le coup est valide if( ValidMove(move) ){ //Si la case est vide on l'ajoute a la liste des mouvements disponibles if( nextBox.piece == EPnone ){ moveAvailable.val = 0; } else{ moveAvailable.val = EstimateValMove(move); } listAvailableMoves[cptAvailableMoves] = moveAvailable; cptAvailableMoves++; } } } } } }
/* ******************************************************************************** * * * Ponder() is the driver for "pondering" (thinking on the opponent's time.) * * its operation is simple: find a predicted move by (a) taking the second * * move from the principal variation, or (b) call lookup to see if it finds * * a suggested move from the transposition table. then, make this move and * * do a search from the resulting position. while pondering, one of three * * things can happen: (1) a move is entered, and it matches the predicted * * move. we then switch from pondering to thinking and search as normal; * * (2) a move is entered, but it does not match the predicted move. we then * * abort the search, unmake the pondered move, and then restart with the move * * entered. (3) a command is entered. if it is a simple command, it can be * * done without aborting the search or losing time. if not, we abort the * * search, execute the command, and then attempt to restart pondering if the * * command didn't make that impossible. * * * ******************************************************************************** */ int Ponder(int wtm) { int dummy=0, i, *n_ponder_moves, *mv; /* ---------------------------------------------------------- | | | first, let's check to see if pondering is allowed, or | | if we should avoid pondering on this move since it is | | the first move of a game, or if the game is over, or | | "force" mode is active, or there is input in the queue | | that needs to be read and processed. | | | ---------------------------------------------------------- */ if (!ponder || force || over || CheckInput()) return(0); /* ---------------------------------------------------------- | | | if we don't have a predicted move to ponder, try two | | sources: (1) look up the current position in the | | transposition table and see if it has a suggested best | | move; (2) do a short tree search to calculate a move | | that we should ponder. | | | ---------------------------------------------------------- */ strcpy(hint,"none"); if (!ponder_move) { (void) LookUp(0,0,wtm,&dummy,&dummy); if (hash_move[0]) ponder_move=hash_move[0]; } if (!ponder_move) { TimeSet(puzzle); if (time_limit < 3) return(0); puzzling=1; position[1]=position[0]; printf(" puzzling over a move to ponder.\n"); last_pv.path_length=0; last_pv.path_iteration_depth=0; for (i=0;i<MAXPLY;i++) { killer_move1[i]=0; killer_move2[i]=0; killer_count1[i]=0; killer_count2[i]=0; } (void) Iterate(wtm,puzzle,0); for (i=0;i<MAXPLY;i++) { killer_move1[i]=0; killer_move2[i]=0; killer_count1[i]=0; killer_count2[i]=0; } puzzling=0; if (pv[0].path_length) ponder_move=pv[0].path[1]; if (!ponder_move) return(0); for (i=1;i<(int) pv[0].path_length-1;i++) last_pv.path[i]=pv[0].path[i+1]; last_pv.path_length=pv[0].path_length-1; last_pv.path_iteration_depth=0; if (!ValidMove(1,wtm,ponder_move)) { ponder_move=0; return(0); } } /* ---------------------------------------------------------- | | | display the move we are going to "ponder". | | | ---------------------------------------------------------- */ if (wtm) printf("White(%d): %s [pondering]\n", move_number,OutputMove(&ponder_move,0,wtm)); else printf("Black(%d): %s [pondering]\n", move_number,OutputMove(&ponder_move,0,wtm)); sprintf(hint,"%s",OutputMove(&ponder_move,0,wtm)); if (post) printf("Hint: %s\n",hint); /* ---------------------------------------------------------- | | | set the ponder move list and eliminate illegal moves. | | | ---------------------------------------------------------- */ n_ponder_moves=GenerateCaptures(0, wtm, ponder_moves); num_ponder_moves=GenerateNonCaptures(0, wtm, n_ponder_moves)-ponder_moves; for (mv=ponder_moves;mv<ponder_moves+num_ponder_moves;mv++) { MakeMove(0, *mv, wtm); if (Check(wtm)) { UnMakeMove(0, *mv, wtm); *mv=0; } else UnMakeMove(0, *mv, wtm); } /* ---------------------------------------------------------- | | | now, perform an iterated search, but with the special | | "pondering" flag set which changes the time controls | | since there is no need to stop searching until the | | opponent makes a move. | | | ---------------------------------------------------------- */ MakeMove(0,ponder_move,wtm); if (Rule50Moves(1)==90 || Rule50Moves(1)==91) ClearHashTables(); last_opponent_move=ponder_move; if (ChangeSide(wtm)) *rephead_w++=HashKey; else *rephead_b++=HashKey; if (RepetitionDraw(wtm)) printf("game is a draw by repetition\n"); if (whisper) strcpy(whisper_text,"n/a"); thinking=0; pondering=1; (void) Iterate(ChangeSide(wtm),think,0); pondering=0; thinking=0; if (ChangeSide(wtm)) rephead_w--; else rephead_b--; last_opponent_move=0; UnMakeMove(0,ponder_move,wtm); /* ---------------------------------------------------------- | | | search completed. the possible return values are: | | | | (0) no pondering was done, period. | | | | (1) pondering was done, opponent made the predicted | | move, and we searched until time ran out in a | | normal manner. | | | | (2) pondering was done, but the ponder search | | terminated due to either finding a mate, or the | | maximum search depth was reached. the result of | | this ponder search are valid, but only if the | | opponent makes the correct (predicted) move. | | | | (3) pondering was done, but the opponent either made | | a different move, or entered a command that has to | | interrupt the pondering search before the command | | (or move) can be processed. this forces Main() to | | avoid reading in a move/command since one has been | | read into the command buffer already. | | | ---------------------------------------------------------- */ if (made_predicted_move) return(1); if (abort_search) return(3); return(2); }
/* ******************************************************************************** * * * Ponder() is the driver for "pondering" (thinking on the opponent's time.) * * its operation is simple: find a predicted move by (a) taking the second * * move from the principal variation, or (b) call lookup to see if it finds * * a suggested move from the transposition table. then, make this move and * * do a search from the resulting position. while pondering, one of three * * things can happen: (1) a move is entered, and it matches the predicted * * move. we then switch from pondering to thinking and search as normal; * * (2) a move is entered, but it does not match the predicted move. we then * * abort the search, unmake the pondered move, and then restart with the move * * entered. (3) a command is entered. if it is a simple command, it can be * * done without aborting the search or losing time. if not, we abort the * * search, execute the command, and then attempt to restart pondering if the * * command didn't make that impossible. * * * ******************************************************************************** */ int Ponder(int wtm) { int dummy=0, i, *n_ponder_moves; /* ---------------------------------------------------------- | | | if we don't have a predicted move to ponder, try two | | sources: (1) look up the current position in the | | transposition table and see if it has a suggested best | | move; (2) do a short tree search to calculate a move | | that we should ponder. | | | ---------------------------------------------------------- */ ponder_completed=0; if (!ponder_move) { (void) LookUp(0,0,wtm,&dummy,dummy); if (hash_move[0]) ponder_move=hash_move[0]; } if (!ponder_move) { TimeSet(puzzle); if (time_limit < 3) return(0); puzzling=1; position[1]=position[0]; Print(2," puzzling over a move to ponder.\n"); last_pv.path_length=0; last_pv.path_iteration_depth=0; for (i=0;i<MAXPLY;i++) { killer_move1[i]=0; killer_move2[i]=0; killer_count1[i]=0; killer_count2[i]=0; } (void) Iterate(wtm,puzzle); for (i=0;i<MAXPLY;i++) { killer_move1[i]=0; killer_move2[i]=0; killer_count1[i]=0; killer_count2[i]=0; } puzzling=0; if (pv[0].path_length) ponder_move=pv[0].path[1]; if (!ponder_move) return(0); for (i=1;i<(int) pv[0].path_length-1;i++) last_pv.path[i]=pv[0].path[i+1]; last_pv.path_length=pv[0].path_length-1; last_pv.path_iteration_depth=0; if (!ValidMove(1,wtm,ponder_move)) { printf("puzzle returned an illegal move!\n"); DisplayChessMove("move= ",ponder_move); ponder_move=0; return(0); } } if (!ponder_move) { strcpy(hint,"none"); return(0); } /* ---------------------------------------------------------- | | | display the move we are going to "ponder". | | | ---------------------------------------------------------- */ if (wtm) Print(2,"White(%d): %s [pondering]\n", move_number,OutputMove(&ponder_move,0,wtm)); else Print(2,"Black(%d): %s [pondering]\n", move_number,OutputMove(&ponder_move,0,wtm)); sprintf(hint,"%s",OutputMove(&ponder_move,0,wtm)); n_ponder_moves=GenerateCaptures(0, wtm, ponder_moves); num_ponder_moves=GenerateNonCaptures(0, wtm, n_ponder_moves)-ponder_moves; /* ---------------------------------------------------------- | | | now, perform an iterated search, but with the special | | "pondering" flag set which changes the time controls | | since there is no need to stop searching until the | | opponent makes a move. | | | ---------------------------------------------------------- */ MakeMove(0,ponder_move,wtm); if (Rule50Moves(1)==90 || Rule50Moves(1)==91) ClearHashTables(); last_opponent_move=ponder_move; if (ChangeSide(wtm)) *rephead_w++=HashKey; else *rephead_b++=HashKey; if (RepetitionDraw(wtm)) Print(0,"game is a draw by repetition\n"); if (whisper) strcpy(whisper_text,"n/a"); pondering=1; (void) Iterate(ChangeSide(wtm),think); pondering=0; if (!abort_search) ponder_completed=1; if (ChangeSide(wtm)) rephead_w--; else rephead_b--; last_opponent_move=0; UnMakeMove(0,ponder_move,wtm); /* ---------------------------------------------------------- | | | search completed. there are two possible reasons for | | us to get here. (1) the opponent made the predicted | | move and we have used enough time on the search, or; | | the operator typed in a command (or not-predicted | | move) that requires the search to abort and restart. | | | ---------------------------------------------------------- */ if (made_predicted_move) return(1); return(0); }