Move* addEatToMove(Move* move, Position targetPosition, Position eatPosition) { Move* newMove = copyMove(move); PositionList* newPositionNode = createPositionList(targetPosition); PositionList* head = newMove->to; if(head==NULL){ newMove->to = newPositionNode; }else{ while(head->next){ head = head->next; } head->next = newPositionNode; } PositionList* newEatNode = createPositionList(eatPosition); head = newMove->eatenAt; if(head==NULL){ newMove->eatenAt = newEatNode; }else{ while(head->next){ head = head->next; } head->next = newEatNode; } newMove->eatCount++; return newMove; }
/*Get Move with Maximum Score from Tree*/ Move *getMinimaxMove(Game *game, Color uCol) { ListNode *moves = getMinimaxMoves(game, uCol); ListNode *temp = moves; Move *res = NULL; int size, r, i; if (RANDOM) { size = listSize(moves); r = rand() % size; for (i = 0; i < r; i++) { if (temp->next!=NULL) temp = temp->next; } res = copyMove(temp->move); } else res = copyMove(moves->move); freeList(moves); return res; }
/*Debug - Get first Move with Maximum Score*/ Move* getMaximumMove(MinimaxNode*root) { int i = 0; for (i = 0; i < root->sonsK; i++) { if (root->sons[i]->val == root->val) { Move* res = copyMove(root->sons[i]->move); return res; } } //printf("moveFromMMT FAILED"); return NULL; }
/*Add legal Moves for Pawn at Location to Linked List*/ void getPawnSingleMove(char board[BOARD_SIZE][BOARD_SIZE], Location *loc, ListNode *temp, Move *move){ int i; if (loc->row + shiftUp(board, loc) == topLimit(board, loc)){ for (i = 0; i < sizeof(PROMOTIONS) / sizeof(Type); i++){ Move *newMove = copyMove(move); newMove->promotion = PROMOTIONS[i]; addMoveToList(temp, newMove); } freeMove(move); } else{ addMoveToList(temp, move); } }
/*Build Minimax Tree of fixed depth via DFS*/ MinimaxNode *getMinimaxTreeFixedDepth(Game *game, int depth, Move *move, Color uCol) { MinimaxNode *curr = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (curr == NULL) exitOnError("malloc"); curr->game = (Game*)malloc(sizeof(Game)); if (curr->game == NULL) exitOnError("malloc"); struct ListNode *moves; int i = 0; curr->depth = depth; copyGame(game, curr->game); curr->sons = NULL; curr->sonsK = 0; if (move != NULL) { updateBoard(curr->game, move); } if (depth == 1) { curr->move = move; } else { freeMove(move); curr->move = NULL; } if (depth == game->difficulty) { return curr; } if ((depth % 2 == 0 && uCol == WHITE) || (depth % 2 == 1 && uCol == BLACK)) { moves = getMoves(curr->game, WHITE); } else { moves = getMoves(curr->game, BLACK); } int size = listSize(moves); curr->sonsK = size; if (!size) { free(moves); return curr; } else { curr->sons = (MinimaxNode**)malloc(sizeof(MinimaxNode)*size); if (curr->sons == NULL) exitOnError("malloc"); struct ListNode *temp = moves; for (i = 0; i < size; i++) { Move* tMove = copyMove(temp->move); curr->sons[i] = getMinimaxTreeFixedDepth(curr->game, depth + 1, tMove, uCol); temp = temp->next; } freeList(moves); } return curr; }
/*Get Moves with Maximum Score*/ ListNode* getMaximumMoves(MinimaxNode*root) { ListNode *res = (ListNode*)malloc(sizeof(ListNode)); if (res == NULL) exitOnError("malloc"); res->move = NULL; res->next = NULL; int i = 0; for (i = 0; i < root->sonsK; i++) { if (root->sons[i]->val == root->val) { //printf("Found same val %d\n", root->val); Move* cMove = copyMove(root->sons[i]->move); addMoveToList(res, cMove); } } return res; }
/*Build Minimax Tree for Best Difficulty using BFS Algorithm*/ MinimaxNode *getMinimaxTreeBestDepth(Game *game, Color uCol) { MinimaxNode *root = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (root == NULL)exitOnError("malloc"); root->game = (Game*)malloc(sizeof(Game)); if (root->game == NULL) exitOnError("malloc"); root->val = 0; MinimaxNode *curr; ListNode *moves; int i; int leavesLocal = 1; Queue *q = setQueue(); /*Create empty Queue for BFS Traversing*/ int size = 0; root->depth = 0; root->move = NULL; copyGame(game, root->game); root->sons = NULL; root->sonsK = 0; enqueue(q, root); /*While Queue is not empty and there are less than MAX_BOARDS_TO_EVAL Leaves in Tree*/ while (q->size&&leavesLocal + size <= MAX_BOARDS_TO_EVAL) { curr = dequeue(q); /*Pop from Queue*/ if (curr->depth % 2 == 0)moves = getMoves(curr->game, uCol); /*Get possible Moves at current Board state*/ else moves = getMoves(curr->game, oppositeCol(uCol)); size = listSize(moves); if (!size) { free(moves); continue; } curr->sons = (MinimaxNode**)malloc(sizeof(MinimaxNode)*size); if (curr->sons == NULL) exitOnError("malloc"); curr->sonsK = size; ListNode *temp = moves; for (i = 0; i < size; i++) { /*Add Nodes for each possible Move*/ curr->sons[i] = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (curr->sons[i] == NULL) exitOnError("malloc"); curr->sons[i]->game = (Game*)malloc(sizeof(Game)); if (curr->sons[i]->game == NULL) exitOnError("malloc"); curr->sons[i]->val = 0; copyGame(curr->game, curr->sons[i]->game); Move* tMove = copyMove(temp->move); updateBoard(curr->sons[i]->game, tMove); curr->sons[i]->depth = curr->depth + 1; if (curr->sons[i]->depth == 1) { curr->sons[i]->move = tMove; } else { freeMove(tMove); curr->sons[i]->move = NULL; } curr->sons[i]->sons = NULL; curr->sons[i]->sonsK = 0; enqueue(q, curr->sons[i]); /*Push to Queue*/ temp = temp->next; } /*Update amount of Leaves in Tree*/ freeList(moves); leavesLocal += size; if (size) leavesLocal--; } freeQueue(q); return root; }
void selectMove() { // First, the two variables we'll use int i; double bestScore; int bestIndex; int bestCount; int *tempBoard; boardEvaluation *tempEval; tempBoard = malloc(boardWidth * boardHeight * sizeof(int)); if (tempBoard == null) { printf("Unable to allocate space for a temporary game board.\n"); exit(1); } // A sanity check if (possibleMovesFound == 0) { printf("Error! No possible moves found!\n"); printBoard(gameBoard); exit(1); } // Now the real work bestScore = -7.0; // Lower than the lowest possible score bestIndex = -1; bestCount = -1; // i = rand() % possibleMovesFound; for (i = 0; i < possibleMovesFound; i++) { // First, get us a temporary copy of the current game board copyBoard(gameBoard, tempBoard); // Now, run the trial move on it runMoveWithStruct(me, possibleMoves[i], tempBoard); // Now, evaluate it tempEval = evaluateBoard(tempBoard, possibleMoves[i]); // Now, score it possibleMoves[i]->score = scoreEvaluation(tempEval); // Now free that evaluation free(tempEval); // Now, see if it is the best one we've found if (possibleMoves[i]->score == 7.0) { // We found a winner, no need to score the rest bestIndex = i; bestCount = 1; break; } else if (possibleMoves[i]->score > bestScore) { bestCount = 1; bestScore = possibleMoves[i]->score; bestIndex = i; } else if (possibleMoves[i]->score == bestScore) { // If the scores are the same... bestCount++; // Make a random choice between them if ((float) rand() / RAND_MAX <= ((double) (1.0 / (double) bestCount))) { bestIndex = i; // Note, this is biased towards the front } } } // Set up the move copyMove(possibleMoves[bestIndex], &finalMove); free(tempBoard); }
int main(int argc, char** argv) { char fromXChar, toXChar, fromYChar, toYChar; int useIPC; ipc_memory *ipc; myDNA = malloc(sizeof(dna)); if (myDNA == null) { printf("Unable to allocate memory for my DNA!\n"); exit(1); } myDNA->noBasePair = 0.984120; // After 47 evolutions myDNA->oneBasePair = 0.576126; myDNA->twoBasePair = 0.315090; myDNA->threeBasePair = -0.972065; myDNA->lineLengthBasePair = 0.020435; myDNA->currentMarginBasePair = 0.660055; // Initial stuff gameBoard = null; possibleMovesFound = 0; useIPC = 0; if (DEBUG) { printf("\n"); } // Make sure we have arguments if ((argc < 2) || (argc > 4)) { printf("Error: bad command line arguments. Please call as:\n"); printf("\t/path/to/program /path/to/input [/path/to/output] [/path/to/dna]\n"); printf("\t/path/to/program --ipc key_number\n"); exit(1); } if (strncmp(argv[1], "--ipc", 5) == 0) { if (argc == 3) { // Key is in the command line, so let's get it if(sscanf(argv[2], "%d", &useIPC) != 1) { // We couldn't load it printf("Unable to load the IPC key. Given '%s'.\n", argv[3]); exit(1); } } else { // We didn't get enough info printf("Error: bad command line arguments for IPC. Please call as:\n"); printf("\t/path/to/program /path/to/input [/path/to/output] [/path/to/dna]\n"); printf("\t/path/to/program --ipc key_number\n"); exit(1); } } // Read the input file if (useIPC) { // Set up the IPC shared memory ipc = null; ipc = (ipc_memory *) shmat(useIPC, 0, 0); if (ipc == (ipc_memory *) -1) { printf("Unable to get shared memory: error %d\n", errno); exit(1); } // Now set the stuff that readInputFile would do for us me = ipc->player; boardHeight = ipc->height; boardWidth = ipc->width; gameBoard = (int *) &(ipc->gameBoard); playerOneScore = ipc->pOneScore; playerOneTimeLeft = ipc->pOneTime; playerTwoScore = ipc->pTwoScore; playerTwoTimeLeft = ipc->pTwoTime; if (me == 1) { him = 2; ourScore = &playerOneScore; ourTime = &playerOneTimeLeft; hisScore = &playerTwoScore; hisTime = &playerTwoTimeLeft; } else { him = 1; hisScore = &playerOneScore; hisTime = &playerOneTimeLeft; ourScore = &playerTwoScore; ourTime = &playerTwoTimeLeft; } } else { readInputFile(argv[1]); } // Read our DNA if they gave it to us if (useIPC) { // We get the DNA through the IPC myDNA = &(ipc->theDNA); } else { // Load the DNA from a file if given if (argc == 4) { loadDNA(argv[3]); } } // Initialize other stuff memset(possibleMoves, 0, MAX_POSSIBLE_MOVES * sizeof(move *)); // Clear out the possible moves array // Generate a list of possible moves generateMoveList(); if (DEBUG) { printf("We found %d possible moves.\n\n", possibleMovesFound); } // Seed the RNG srand((unsigned) time(NULL)); // Time to start processing. selectMove(); // Figure out our move // Print out the move if (useIPC) { // Since we are using IPC, things are easy copyMove(&finalMove, &(ipc->chosenMove)); } else { fromXChar = columnToChar(finalMove.from_x); toXChar = columnToChar(finalMove.to_x); fromYChar = '1' + finalMove.from_y; toYChar = '1' + finalMove.to_y; if (argc == 2) { // Just print out the result printf("%c%c %c%c\n", fromXChar, fromYChar, toXChar, toYChar); } else { // They want our output put into a file, so we'll have to do that. FILE *out = null; out = fopen(argv[2], "w"); if (out == null) { // We couldn't open the file, so complain printf("Unable to open output file! Error %d.\n", errno); printf("%c%c %c%c\n", fromXChar, fromYChar, toXChar, toYChar); } else { // We opened the file, write out stuff and quit. fprintf(out, "%c%c %c%c\n", fromXChar, fromYChar, toXChar, toYChar); fclose(out); } } } if (DEBUG) { printBoard(gameBoard); printf("%c%c %c%c\n", fromXChar, fromYChar, toXChar, toYChar); } // Clean up the possible move list if (possibleMovesFound > 0) { int i; for (i = 0; i < possibleMovesFound; i++) { free(possibleMoves[i]); } } // Detatch from the shared memory if we are using it if (useIPC) { shmdt(ipc); } // Now return return 0; }