static void DoMaxMarginMove(HWND hWnd, LPPOINT pt, LPRECT target, LPRECT parent) { move moves[NUM_DIR]; int max_value = INT_MIN; direction max_index = NUM_DIR; direction i; dump("MaxMargin"); for (i = LEFT; i < NUM_DIR; i++) CalculateMove(i, moves + i, pt, target, parent); for (i = LEFT; i < NUM_DIR; i++) { if (moves[i].valid && (moves[i].margin > max_value)) { max_value = moves[i].margin; max_index = i; } } if ((max_index < NUM_DIR) && (max_value > 0)) { dump("%d: %d", max_index, max_value); PerformMove(max_index, max_value, hWnd, pt, target); } }
static void DoMinDeltaMove(HWND hWnd, LPPOINT pt, LPRECT target, LPRECT parent) { move moves[NUM_DIR]; int min_value = INT_MAX; direction min_index = NUM_DIR; direction i; dump("MinDelta"); for (i = LEFT; i < NUM_DIR; i++) CalculateMove(i, moves + i, pt, target, parent); for (i = LEFT; i < NUM_DIR; i++) { if (moves[i].valid && (moves[i].distance < min_value)) { min_value = moves[i].distance; min_index = i; } } if (min_index < NUM_DIR) { dump("%d: %d, %d", min_index, min_value, moves[min_index].margin); PerformMove(min_index, moves[min_index].margin, hWnd, pt, target); } }
void Game::AIPlay() { currentMove = AI(pieces, modeAI).BestMove(); PerformMove(currentMove); if (currentGameState == GameState::RED_TURN) { if (currentMove.GetToPiece()->GetCharacter() == Piece::GENERAL_BLUE) { currentGameState = GameState::END; winner = 1; } else { currentGameState = GameState::BLUE_TURN; } } else { if (currentMove.GetToPiece()->GetCharacter() == Piece::GENERAL_RED) { currentGameState = GameState::END; winner = 0; } else { currentGameState = GameState::RED_TURN; } } currentMove.ResetMove(); currentMove.ResetValidMove(); }
/* and the PerformMove function */ void *FindBestMoveThread1(void *data) { int i,x,best[50],numbest; struct State state; double val; double maxv = -1000000.0; int player; int depth=1; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); fprintf(stderr,"FindBestMoveThread1\n"); player = *((int*)data); /* Set up the current state */ state.player = player; memcpy(state.board,board,64*sizeof(char)); /* Find the legal moves for the current state */ FindLegalMoves(&state); i = rand()%state.numLegalMoves; memset(bestmove,0,12*sizeof(char)); memcpy(bestmove,state.movelist[i],MoveLength(state.movelist[i])); evals=0; while(1) { maxv = -1000000.0; numbest=1; best[0]=0; for(x=0;x<state.numLegalMoves;x++) { State newState; memcpy(&newState, &state, sizeof(State)); PerformMove(newState.board, newState.movelist[x],MoveLength(newState.movelist[x])); newState.player = (newState.player==1) ? 2 : 1; val = minVal(&newState, depth); if(val>maxv) { best[0]=x; numbest=1; maxv = val; } if(val==maxv) { best[numbest++]=x; } } memset(bestmove,0,12*sizeof(char)); i=best[rand()%numbest]; // pick a random best move memcpy(bestmove, state.movelist[i], MoveLength(state.movelist[i])); maxDepth=depth++; } return NULL; }
//----------------------------------------------------------------------- // void ReturnFromMoveRenameYesNo( bool result) { // Routine if invoked upon return from the "Automatic Rename on Move" confirmation prompt. char str1[200], str2[200]; int renameResult; appendToLogfile("ReturnFromMoveRenameYesNo: Started.", INFO); // Check the result of the confirmation panel to decide what to do. switch (result) { case TRUE: // YES appendStringToLogfile("ReturnFromMoveRenameYesNo: Rename from %s", GlbSourceFile, WARNING); appendStringToLogfile("ReturnFromMoveRenameYesNo: to %s", GlbRenamedFile, WARNING); #ifdef WIN32 // If testing on WIN32 platform don't do rename as not yet implemented in the TAP SDK. renameResult=0; #else renameResult=TAP_Hdd_Rename(GlbSourceFile,GlbRenamedFile); #endif if (renameResult!=0) { TAP_SPrint(str1,"Error renaming: '%s'", GlbSourceFile); TAP_SPrint(str2,"to: '%s'", GlbRenamedFile); fileMoved = FALSE; returnFromMove = FALSE; // Don't close the Move window to give user a chance to choose a different folder. ShowMessageWin( rgn, "Rename On Move Failed.", str1, str2, 500 ); break; } strncpy( GlbSourceFile, GlbRenamedFile, 256 ); // Copy the renamed filename into the Global variable so that we move the renamed file. PerformMove(); switch (RenameOnMoveOption) { case 0: // "Rename and confirm" // Close the Move Window after this, otherwise it is closed as part of the other routines. CloseArchiveMoveWindow(); // Close the move window break; case 2: // "Rename automatically (with message) " TAP_SPrint(str1, "%s/%s", GlbTargetDir, GlbRenamedFile); ShowMessageWin( rgn, "File Move Successful.", "Moved and renamed file to:", str1, 400 ); break; default: // "Rename automatically (no message) " break; } break; case FALSE: // NO fileMoved = FALSE; returnFromMove = FALSE; // Don't close the Move window to give user a chance to choose a different folder. break; } appendToLogfile("ReturnFromMoveRenameYesNo: Finished.", INFO); }
void UAITask_MoveTo::ConditionalPerformMove() { if (MoveRequest.IsUsingPathfinding() && OwnerController && OwnerController->ShouldPostponePathUpdates()) { UE_VLOG(GetGameplayTasksComponent(), LogGameplayTasks, Log, TEXT("%s> can't path right now, waiting..."), *GetName()); OwnerController->GetWorldTimerManager().SetTimer(MoveRetryTimerHandle, this, &UAITask_MoveTo::ConditionalPerformMove, 0.2f, false); } else { MoveRetryTimerHandle.Invalidate(); PerformMove(); } }
void Game::OnMouseButtonUp(int xPos, int yPos) { GameState state = currentGameState; currentMove.SetToLocation(xPos, yPos); if (currentMove.GetValidMove()) { currentMove.SetFromPiece(pieces[currentMove.GetFromRow()][currentMove.GetFromCol()]); currentMove.SetToPiece(pieces[currentMove.GetToRow()][currentMove.GetToCol()]); if (currentMove.GetFromPiece()->GetCharacter() != Piece::PieceCharacter::NONE) { if ((currentMove.GetFromPiece()->PossibleMoves(pieces)[currentMove.GetToRow() * 10 + currentMove.GetToCol()] == true) && (currentMove.GetFromPiece()->GetColor() != currentMove.GetToPiece()->GetColor())) { PerformMove(currentMove); if (currentGameState == GameState::RED_TURN) { if (currentMove.GetToPiece()->GetCharacter() == Piece::GENERAL_BLUE) { currentGameState = GameState::END; winner = 0; } else { currentGameState = GameState::BLUE_TURN; } } else { if (currentMove.GetToPiece()->GetCharacter() == Piece::GENERAL_RED) { currentGameState = GameState::END; winner = 1; } else { currentGameState = GameState::RED_TURN; } } } } currentMove.ResetMove(); currentMove.ResetValidMove(); if (state != currentGameState) TriggerAIEvent(); } }
/* * Returns the maximum value from a tree. */ double maxVal(double alpha, double beta, struct State *state, int depth) { int x; struct State newState; /* If we've reached the depth limit then evaluate this node and return its * value. */ if (depth <= 0) { return evaluateBoard(state); } --depth; /* descend one level in the tree */ FindLegalMoves(state); /* Walk the move list and find the best one. */ for (x=0; x<state->numLegalMoves; ++x) { /* Check to see if this thread has been cancelled before moving on. */ pthread_testcancel(); /* Copy the current board state. */ memcpy(&newState, state, sizeof(struct State)); /* Perform a move on the copied state. */ PerformMove(newState.board, newState.movelist[x], MoveLength(newState.movelist[x])); /* Toggle the current player. */ newState.player = (newState.player == 1) ? 2 : 1; /* Perform a depth limited MiniMax search for the best move. * Uses Alpha-Beta pruning. */ alpha = MAX(alpha, minVal(alpha, beta, &newState, depth)); if (alpha >= beta) { return beta; } } return alpha; }
double minVal(State *state, int depth) { int x; double minv=100000.0; if(depth--<=0) return evalBoard1(state); FindLegalMoves(state); for(x=0;x<state->numLegalMoves;x++) { State newState; memcpy(&newState, state, sizeof(State)); PerformMove(newState.board, newState.movelist[x],MoveLength(newState.movelist[x])); newState.player = (newState.player==1) ? 2 : 1; minv = MIN(maxVal(&newState, depth),minv); } return minv; }
/* Combines min and max into one function that always does max */ double minMax(State *currBoard, int depth) { State nextBoard; double rval; int i; double maxv=-100000.0; if(depth <= 0) return evalBoard2(currBoard); FindLegalMoves(currBoard); for(i=0; i<currBoard->numLegalMoves; i++) { /* Set up the next state by copying the current state and then updating the new */ /* state to reflect the new board after performing the move */ memcpy (&nextBoard, currBoard, sizeof(State)); PerformMove(nextBoard.board,currBoard->movelist[i],MoveLength(currBoard->movelist[i])); nextBoard.player = 3-nextBoard.player; rval = -minMax(&nextBoard, depth-1); if (rval > maxv) maxv = rval; } return maxv; }
int main(int argc, char *argv[]) { char buf[1028],move[12]; int len,mlen; /* Convert command line parameters */ SecPerMove = (float) atof(argv[1]); /* Time allotted for each move */ MaxDepth = (argc == 4) ? atoi(argv[3]) : -1; fprintf(stderr, "%s SecPerMove == %lg\n", argv[0], SecPerMove); /* Determine if I am player 1 (red) or player 2 (white) */ //fgets(buf, sizeof(buf), stdin); len=read(STDIN_FILENO,buf,1028); buf[len]='\0'; if(!strncmp(buf,"Player1", strlen("Player1"))) { fprintf(stderr, "I'm Player 1\n"); player1 = 1; } else { fprintf(stderr, "I'm Player 2\n"); player1 = 0; } if(player1) me = 1; else me = 2; /* Set up the board */ ResetBoard(); srand((unsigned int)time(0)); if (player1) { start = times(&bff); goto determine_next_move; } for(;;) { /* Read the other player's move from the pipe */ //fgets(buf, sizeof(buf), stdin); len=read(STDIN_FILENO,buf,1028); buf[len]='\0'; start = times(&bff); memset(move,0,12*sizeof(char)); /* Update the board to reflect opponents move */ mlen = TextToMove(buf,move); PerformMove(board,move,mlen); determine_next_move: /* Find my move, update board, and write move to pipe */ if(player1) FindBestMove(1); else FindBestMove(2); if(bestmove[0] != 0) { /* There is a legal move */ mlen = MoveLength(bestmove); PerformMove(board,bestmove,mlen); MoveToText(bestmove,buf); } else exit(1); /* No legal moves available, so I have lost */ /* Write the move to the pipe */ //printf("%s", buf); write(STDOUT_FILENO,buf,strlen(buf)); fflush(stdout); } return 0; }
/* and the PerformMove function */ void *FindBestMoveThread2(void *p) { int player; int i, depth, best[50], numbest=0; struct State state, nextstate; double maxv=-100000.0,minval[50]; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); fprintf(stderr,"FindBestMoveThread2\n"); player = *((int*)p); /* Set up the current state */ state.player = player; memcpy(state.board,board,64*sizeof(char)); /* Find the legal moves for the current state */ FindLegalMoves(&state); /* init bestmove to first move */ memset(bestmove,0,12*sizeof(char)); memcpy(bestmove,state.movelist[0],MoveLength(state.movelist[0])); evals=0; for(depth=1;;depth++) { maxv=-1000000.0; numbest=1; best[0] = 0; /* For each legal move */ for(i=0; i<state.numLegalMoves; i++) { /* Set up the next state by copying the current state and then updating the new */ /* state to reflect the new board after performing the move */ memcpy(&nextstate,&state,sizeof(struct State)); PerformMove(nextstate.board,state.movelist[i],MoveLength(state.movelist[i])); if(state.player == 1) nextstate.player = 2; else nextstate.player = 1; /* Call your search routine to determine the value of this move. Note: */ /* if you choose to use alpha/beta search you will need to write the */ /* MinVal and MaxVal functions, as well as your heuristic eval function */ minval[i] = -minMax(&nextstate,depth); if(minval[i] > maxv) { numbest=1; best[0]=i; maxv= minval[i]; //memcpy(bestmove,state.movelist[order[i]],12*sizeof(char)); } else if(minval[i] == maxv) { best[numbest++]=i; } } //fprintf(stderr,"Evaluation of best move gives a score of %lg\n", minval[best]); maxDepth=depth; memset(bestmove,0,12*sizeof(char)); i = best[rand()%numbest]; // Pick a random best move memcpy(bestmove,state.movelist[i],MoveLength(state.movelist[i])); } }
int main(int argc, char *argv[]) { char text[1028],temptext[1028], str[1028]; int tlen,mlen,move[12],numlegal,done; if(argc>=3) { if(!strncasecmp("-MaxDepth",argv[argc-2], strlen("-MaxDepth"))) { MaxDepth = atoi(argv[argc-1]); argc-=2; } else MaxDepth = -1; } else MaxDepth = -1; #ifndef GRAPHICS printf("No graphics\n"); if(argc != 4) Usage(argv[0]); strcpy(player1,argv[1]); strcpy(player2,argv[2]); SecPerMove = atof(argv[3]); #endif #ifdef GRAPHICS printf("Graphics\n"); InitGraphics(argc,argv); #else NewGame(); { int x,y; /* I'll wait a bit to make sure both oponents are ready to go */ printf("waiting\n"); sleep(1); for(x=0;x<1000;x++) for(y=0;y<10000;y++); } #endif ResetBoard(); for(;;) { pthread_t thread; int rc, dummy; HandleEvents(); if(playing) { sprintf(str,"Waiting for player %d",turn+1); Message(str); HumanMoved = done = 0; //start = times(&bff); rc = pthread_create(&thread, NULL, timer, (void*)&done); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy); do { HandleEvents(); /* Give humans all the time they want to move */ if(player[turn] == HUMAN) done = HumanMoved; else if(player[turn] == COMPUTER) { char *ptr; memset(temptext,0,sizeof(temptext)); tlen = read(readfd[turn],temptext,1028); if(tlen > 0) { ptr = temptext; while(*ptr == 10 && *ptr !=0) ptr++; strcpy(text,ptr); if(strlen(text)) done=1; } } } while(playing && !done); pthread_cancel(thread); if(!playing) continue; if(player[turn] == COMPUTER && tlen <= 0) { sprintf(str,"Player %d has lost the game (time limit reached).",turn+1); Message(str); StopGame(); } else { if(player[turn] == COMPUTER) { text[tlen] = '\0'; memset(move,0,12*sizeof(int)); mlen = TextToMove(text,move); } else if(player[turn] == HUMAN) { mlen = hlen; memcpy(move,hmove,12*sizeof(int)); hlen = 0; memset(hmove,0,12*sizeof(int)); MoveToText(move,text); } if(!mlen) { /* Illegal move check 1 */ /*char temp[1000]; char *ptr1, *ptr2; ptr1=text; temp[0] = 0; ptr2=temp; while(*ptr1) { sprintf(ptr2,"%i, ", *ptr1); ptr1++; ptr2 = &(ptr2[strlen(ptr2)]); }*/ //sprintf(str,"Player %d has lost the game (illegal move %s %s submitted).",turn+1,text, temp); sprintf(str,"Player %d has lost the game (illegal move %s submitted).",turn+1,text); Message(str); StopGame(); } else { if(!IsLegal(move,mlen)) { /* Illegal move check 2 */ /*char temp[1000]; char *ptr1, *ptr2; ptr1=text; temp[0] = 0; ptr2=temp; while(*ptr1) { sprintf(ptr2,"%i, ", *ptr1); ptr1++; ptr2 = &(ptr2[strlen(ptr2)]); } sprintf(str,"Player %d has lost the game (illegal move %s %s submitted).",turn+1,text, temp);*/ sprintf(str,"Player %d has lost the game (illegal move %s submitted).",turn+1,text); Message(str); StopGame(); } else { /* Legal Move */ PerformMove(move,mlen); #ifdef GRAPHICS UpdateBoard(); #else printf("Move: %s\n",text); PrintBoard(); #endif if(turn) turn=0; else turn=1; /* Check to see if other player has now lost */ numlegal = FindLegalMoves(turn+1); if(!numlegal) { sprintf(str,"Player %d has lost the game.",turn+1); Message(str); StopGame(); } else if(player[turn] == COMPUTER) { write(writefd[turn],text,strlen(text)); } } } } } } }
//------------ // void MoveAFile(char* sourceDir, char* destDir, char* sourceFile, dword attr) { bool fileAlreadyExists; char targetDir[500]; char currentFileName[256], baseFileName[256], title1[50], title2[50], str1[256], str2[256], fileName[256], counter[6]; int fileIncrement; // A counter used in case we need to append a number to an already existing file name. appendToLogfile("MoveAFile: Started.", WARNING); // If we try to move a file and there is already an existing file in the target directory // with the same name, we will append an incrementing counter to the file name. (eg. news-1.rec news-23.rec) fileAlreadyExists = FALSE; // Flag to indicate that the renamed file already exists. fileIncrement = 0; // Counter in case we need to append a number to an already existing file name. if (attr != ATTR_FOLDER) { strncpy( currentFileName, sourceFile, 256 ); // Copy the current filename strncpy( fileName, sourceFile, 256 ); // Copy the current filename strncpy( baseFileName, sourceFile, 256 ); // Copy the current filename StripFileName( baseFileName ); // Strip off the ".rec" strncpy( fileName, baseFileName, 256 ); // Copy the stripped off filename in case we need to rename on a move. strcat( fileName, REC_STRING ); // Append ".rec" to the base filename } // Perform check that the Move routine is available for this firmware. #ifdef WIN32 #else if (!TAP_Hdd_Move_Available()) { ShowMessageWin( rgn, "Move NOT available.", "This firmware does not support", "the move function via Archive.", 400 ); returnFromMove = TRUE; // Force a closer of the Move window, and refresh the list. return; } #endif appendToLogfile("MoveAFile: Creating target filename.", WARNING); // Create the fully qualified target directory name. // // Start with the Source Directory strcpy(targetDir, sourceDir); // Add the intermediate "/" strcat(targetDir, "/" ); // Add the target directory. strcat(targetDir, destDir); // Check in the target directory to make sure a file with the same name doesn't already exists. // // Change to the target directory. appendStringToLogfile("MoveAFile: Changing to targetdir: %s.",targetDir, WARNING); GotoPath( targetDir ); // Check for the same file. appendStringToLogfile("MoveAFile: Calling TAP_Hdd_Exist for:%s",sourceFile, WARNING); fileAlreadyExists = TAP_Hdd_Exist(sourceFile); // If we're moving a file and the target already exists, try to rename it - if the config option #28 has been set to allow rename.. while ((fileAlreadyExists) && (fileIncrement < 99999) && (attr != ATTR_FOLDER) && (RenameOnMoveOption!=3)) { fileIncrement++; // Increase the counter for the number to append to the filename. appendIntToLogfile("MoveAFile: fileAlreadyExists loop:%d",fileIncrement, WARNING); sprintf(counter, "-%d", fileIncrement); // Create the counter text strncpy( fileName, baseFileName, 256); // Copy back the original filename strcat( fileName, counter); // Append the counter text to the filename strcat( fileName, REC_STRING ); // Append the ".rec" to the end. appendStringToLogfile("MoveAFile: fileAlreadyExists loop calling TAP_Hdd_Exist for: %s", fileName, WARNING); fileAlreadyExists = TAP_Hdd_Exist(fileName); // Check if the file exists. appendToLogfile("MoveAFile: fileAlreadyExists loop TAP_Hdd_Exist finished", WARNING); } // Return to the original directory. appendStringToLogfile("MoveAFile: Changing to sourceDir: %s.",sourceDir, WARNING); GotoPath( sourceDir ); // Set up appropriate text strings for message windows, depending on whether it's a file or folder. switch (attr) { case ATTR_FOLDER: TAP_SPrint(title1, "Folder Move Failed."); TAP_SPrint(title2, ""); TAP_SPrint(str1, "Same folder already exists:"); TAP_SPrint(str2, ""); break; default: TAP_SPrint(title1, "File Move Failed."); TAP_SPrint(title2, "File Move Conflict."); TAP_SPrint(str1, "Same file already exists."); TAP_SPrint(str2, "Same file already exists. Rename to:"); break; } // Copy source and destination information to Global variables so that they are available for the actual move routine. strncpy( GlbSourceFile, sourceFile, 256 ); // Copy the source filename strncpy( GlbSourceDir, sourceDir, 256 ); // Copy the source directory strncpy( GlbTargetDir, targetDir, 256 ); // Copy the target directory // If the target file already exists in the target directory we can't move. if (fileAlreadyExists) { ShowMessageWin( rgn, title1, str1, sourceFile, 400 ); fileMoved = FALSE; returnFromMove = FALSE; // Don't close the Move window to give user a chance to choose a different folder. return; // Jump out of this routine as we can't do the move. } // Check if we needed to rename the file in the target directory. if (fileIncrement > 0) { strncpy( GlbRenamedFile, fileName, 256 ); // Copy the renamed filename into the Global variable // Check the config option #28 to see if the Rename On Move requires a confirmation or not. if (RenameOnMoveOption == 0) // Need to display a confirmation panel. { DisplayYesNoWindow(title2, str2, fileName, "Yes", "No", 1, &ReturnFromMoveRenameYesNo ); fileMoved = FALSE; returnFromMove = FALSE; // Don't close the Move window until after the Yes/No window. return; // Jump out of this routine as Move will be done after Yes/No window. } else // Otherwise call routine as if we said "Yes" on the confirmation window. { ReturnFromMoveRenameYesNo( TRUE ); return; // Jump out of this routine as we've already done the move in the ReturnFromMoveRenameYesNo routine. } } // Call the routine to perform the actual move. PerformMove(); appendToLogfile("MoveAFile: Finished.", WARNING); }
/* and the PerformMove function */ void *FindBestMoveThread(void *arg) { int i,x, depth; double val; double alpha = DBL_MIN; double beta = DBL_MAX; struct State state; struct State newState; int player = *((int *)arg); int max_depth = (MaxDepth == -1) ? INT_MAX : MaxDepth; /* Set up the current state */ state.player = player; memcpy(state.board,board,64*sizeof(char)); memset(bestmove,0,12*sizeof(char)); /* Find the legal moves for the current state */ FindLegalMoves(&state); /* Pick a random move as the best move just to get started. */ i = rand() % state.numLegalMoves; memcpy(bestmove, state.movelist[i], MoveLength(state.movelist[i])); /* Do an iterative deepening search for the best move. This uses alpha * beta pruning to discard unnecessary branches from the search. */ for (depth=START_DEPTH; depth <= max_depth; depth++) { /* Check to see if this thread has been cancelled before moving on. */ pthread_testcancel(); /* Walk the move list and find the best one. */ for (x=0; x<state.numLegalMoves; ++x) { /* Copy the current board state. */ memcpy(&newState, &state, sizeof(struct State)); /* Perform a move on the copied state. */ PerformMove(newState.board, state.movelist[x], MoveLength(state.movelist[x])); /* Toggle the current player. */ newState.player = (newState.player == 1) ? 2 : 1; /* Perform a depth limited MiniMax search for the best move. * Uses Alpha-Beta pruning. */ val = minVal(alpha, beta, &newState, depth); if (val > alpha) { i = x; alpha = val; } } /* Clear the best move and then copy in the new best move. */ memset(bestmove, 0, 12*sizeof(char)); memcpy(bestmove, state.movelist[i], MoveLength(state.movelist[i])); /* fprintf(stderr, "DEBUG :: %s searched to depth %d.\n", prog_name, depth); */ } return NULL; }