1 / 35

2D1350 Programmeringsparadigm

2D1350 Programmeringsparadigm. Pointers Arrays Structures Artificial intelligence and game playing Lab assignment. Games as Search Problems. The behavior / actions of the opponent are unpredictable, therefore search for a “worst-case”-plan.

mac
Download Presentation

2D1350 Programmeringsparadigm

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 2D1350 Programmeringsparadigm • Pointers • Arrays • Structures • Artificial intelligence and game playing • Lab assignment

  2. Games as Search Problems • The behavior / actions of the opponent are unpredictable, therefore search for a “worst-case”-plan. • Time limit, therefore complete search is not feasible and an approximation is needed • Algorithm for perfect play (van Neumann 1944) • Finite horizon, approximate evaluation (Zuse 1945, Shannon 1950, Samuel 1952) • Pruning search tree (McCarthy 1956)

  3. Types of Game

  4. Min-Max-Search • Optimal strategy for deterministic, perfect-information game • Idea: Choose move that results in position with highest min-max-value = best achievable payoff against best opponents play 5 Max: A3 A1 A2 Min: 3 5 2 A11 A13 A21 A23 A31 A33 A12 A22 A32 3 12 8 5 7 9 4 2 7

  5. Min-Max-Search Function MINMAX-DECISION(game state) returns a move for each move in PossibleMoves(game state) do value[move] <- MINIMAX-VALUE(apply(move, game state)) end return the move with the highest value[move] Function MINMAX-VALUE(game state) returns a utility value if TERMINAL-TEST(game state) then return UTILITY(game state) else if MAX is to move in game state return the highest MINMAX-VALUE of SUCCESSORS(game state) else return the lowest MINMAX-VALUE of SUCCESSORS(game state)

  6. Min-Max Properties • Complete: yes, if search tree is finite • Optimal : yes, if opponent plays optimal • Time complexity : O(bm) • Space complexity : O(bm) depth first search • Chess b~35 possible moves in each state, m~100 moves per game -> exact solution infeasible • Standard solution • cutoff test for search (e.g. depth limit) • evaluation function : approximates utility of board position

  7. Evaluation Scheme • For chess for example typically linear weighted sum of features • Utility(s) = w1 f1(s) + w2 f2(s) + …wn fn(s) w1=9 f1(s)= #white queens - #black queens w2=5 f2(s) = #white rooks - #black rooks etc.

  8. Cutting of Search • Min-Max-Search with Cut-Off requires • 1. CUTOFF criterion, usually based on search depth • 2. UTILITY function needs an evaluation scheme for non-terminal game states • Ply = one half-move (move by one player) • Chess: • 4-ply = novice • 8-ply = PC, human master • 12-ply = Deep Blue, Kasparov

  9. Min-Max-Search with Cut-Off Function MINMAX-DECISION(game) returns a move for each move in PossibleMoves(game state) do value[move] <- MINIMAX-VALUE(apply(move, game state)) end return the move with the highest value[move] Function MINMAX-VALUE(game state, depth) returns a utility value if CUTOFF-TEST(depth) or TERMINAL-TEST(game state) return UTILITY(game state) else if MAX is to move in game state return the highest MINMAX-VALUE(SUCCESSOR(game state),depth+1) else return the lowest MINMAX-VALUE(SUCCESSOR(game state), depth+1)

  10. Connect-4 • two player game • 7x6 rectangular board placed vertically • 21 red, 21 yellow tokens • players alternate by dropping a token into one of the seven columns, the token falls down to the lowest unoccupied square • a player wins if she connects four token vertically, horizontally or diagonally • if the board is filled (42 tokens played) and no player has aligned four tokens the game ends in a draw

  11. Connect-4 win for red win for yellow draw

  12. Connect-4 Utility Function • Odd square: is a square belonging to an odd row (1,3,5) • Even square: is a square belonging to an even row (2,4,6) • Threats: A threat is a group of three tokens of the same color which has the fourth square empty and also the square below the empty square is empty • Odd threat: is a threat in which the empty square is odd • Even threat: is a threat in which the empty square is even • If red (moves first) has an odd threat and black cannot connect four tokens anywhere else red will win. • If black (moves second) has an even threat and black cannot connect four tokens anywhere else black will win. • At the beginning of the game it is advantageous to place tokens in the central columns.

  13. Lab Assignment • Code for connect-4 available in game.h and game.c • Copy files game.h, game.c, Makefile into your local directory • To add gcc to your list of modules type module add gcc/3.1 or add this line to .modules • To compile game.c into executable type make

  14. Lab Assignment • Design and implement a game playing program for the deterministic two player game Connect-4 • Features • The program should be able to play against itself or a human opponent. • The program should visualize the evolution of the game and print out its own estimate of the utility of the current game state. • The program should determine who won or if the game ended in a draw • Implement the min-max-search algorithm • Implement a proper utility function for Connect-4 • Test the program by letting it play against itself and against a human opponent

  15. Connect-4 Game State #define ROWS 6 /* number of rows in connect-4 */ #define COLS 7 /* number of columns in connect-4 */ #define RED -1 /* value for red tokens and red player */ #define BLACK 1 /* value for black tokens and black player */ struct Game { int board[ROWS][COLS]; /* -1 token red player, 1 token black player, 0 empty square */ int currentplayer; /* -1 red player, 1 black player */ int tokensonboard; /* counts the number of tokens on the board */ };

  16. Connect-4 Move struct Move { int row; /* row coordinate of square */ int col; /* column coordinate of square */ int token; /* -1 red token, 1 black token */ };

  17. void InitGame() void InitGame(struct Game *game) /* pointer reference to game state */ { int i; int j; for (i=0; i < ROWS; i++) for (j=0; j < COLS; j++) (*game).board[i][j]=0; /* empty board */ (*game).currentplayer=RED; /* red player to start game */ (*game).tokensonboard=0; };

  18. void MakeMove() void MakeMove(struct Game *game, struct Move move) { #if DEBUG assert((*game).board[move.row][move.col]==0); /* assert square is empty */ if (move.row>0) assert((*game).board[move.row-1][move.col]!=0); /* assert square below is occupied */ assert((*game).currentplayer==move.token); /* assert correct player moves */ #endif (*game).board[move.row][move.col]=move.token; /* place token at square */ (*game).currentplayer*=-1; /* switch player */ (*game).tokensonboard++; /* increment number of tokens on board */ }

  19. void UndoMove() void UndoMove(struct Game *game, struct Move move) { #if DEBUG assert((*game).board[move.row][move.col]!=0); /* assert square is occupied */ if (move.row<ROWS-1) assert((*game).board[move.row+1][move.col]!=0); /* assert square above is empty */ assert((*game).currentplayer!=move.token); /* assert correct player moves */ #endif (*game).board[move.row][move.col]=0; /* remove token from square */ (*game).currentplayer*=-1; /* switch player */ (*game).tokensonboard--; /* decrement number of tokens on board */ }

  20. int Win() int Win(struct Game *game, int player) { int i; int j; for (j=0;j<COLS;j++) for(i=0;i<ROWS-3;i++) /* check for group of four vertical tokens */ { int count=0; /* counts number of consecutive tokens */ while((count < 4) && ((*game).board[i+count][j]==player)) /* check if token is owned by player and not 4 tokens yet */ count++; if (count==4) /* four tokens in column */ return 1; /* win for player*/ } … /* check for horizontal and diagonal groups of four */

  21. int Win() for (j=0;j<COLS-3;j++) for(i=0;i<ROWS;i++) /* check for group of four horizontal four tokens */ { int count=0; /* counts number of consecutive tokens */ while((count < 4) && ((*game).board[i][j+count]==player)) /* check if token is owned by player and not 4 tokens yet */ count++; if (count==4) /* four tokens in a row */ return 1; /* win for player */ }

  22. int Win() for (j=0;j<COLS-3;j++) for(i=0;i<ROWS-3;i++) /* check for four tokens in an upward diagonal */ { int count=0; /* counts number of consecutive tokens */ while((count < 4) && ((*game).board[i+count][j+count]==player)) /* check if token is owned by player and not 4 tokens yet */ count++; if (count==4) /* four tokens in a diagonal */ return 1; /* win for player */ }

  23. int Win() for (j=0;j<COLS-3;j++) for(i=3;i<ROWS;i++) /* check for four tokens in a downward diagonal */ { int count=0; /* counts number of consecutive tokens */ while((count < 4) && ((*game).board[i-count][j+count]==player)) /* check if token is owned by player and not 4 tokens yet */ count++; if (count==4) /* four tokens in a diagonal */ return 1; /* win for player */ } return 0; /* no win for player */ }

  24. int Draw() int Draw(struct Game *game) { if ((*game).tokensonboard<42) return 0; else return (!Win(game,RED) && !Win(game,BLACK)); }

  25. int Row() int Row(struct Game *game, int col) /* computes the row on which token ends when dropped in column col */ { int row=0; while((row<ROWS) && (*game).board[row][col]!=0) row++; return row; }

  26. void PossibleMoves() void PossibleMoves(struct Game *game, int *number_of_moves, struct Move moves[]) /* computes the possible moves , number_of_moves returns the number of available moves, moves[] contains array of moves */ { int i; *number_of_moves=0; for (i=0;i<COLS;i++) { int row=Row(game,i); /* computes first empty square in col i */ if (row<ROWS) /* column has an empty square */ { moves[*number_of_moves].row=row; moves[*number_of_moves].col=i; moves[*number_of_moves].token=(*game).currentplayer; (*number_of_moves)++; } } }

  27. int Utility() int Utility(struct Game *game) { if (Draw(game)) return 0; if (Win(game,RED)) return 1000; /* maximum utility for winning */ if (Win(game,BLACK)) return -1000; /* minimum utility for loosing */ /* non-terminal game state */ /* HERE GOES YOUR CODE TO COMPUTE UTILITY OF NON-TERMINAL BOARD STATES */ return 0; }

  28. Input / Output Functions void DisplayBoard(struct Game *game); /* print board state on screen */ void DisplayMove(struct Move move); /* print move on screen */ void EnterMove(struct Move *move, struct Game *game); /* reads in a move from the keyboard */

  29. int main() int main(int argc, char *argv[]) { int i; struct Game game; /* variable to store the game state */ struct Move moves[COLS]; /* array to store possible moves */ int number_of_moves; int playagainsthuman=0; /* computer plays against itself (0) or against human (1) */ …

  30. int main() for (i=1; i<argc; i++) /* iterate through all command line arguments */ { if(strcmp(argv[i],"-p")==0) /* if command line argument -p human opponent */ { playagainsthuman=1; printf("Human player plays black\n"); } if(strcmp(argv[i],"-h")==0) /* if command line argument -h print help */ { printf("game [-p] [-h]\n-p for play against human player\n-h for help\n"); return 0; /* quit program */ } }

  31. int main() InitGame(&game); /* set up board */ while( !Draw(&game) && !Win(&game,RED) && !Win(&game,BLACK)) /* no draw or win */ { int rand; struct Move move; DisplayBoard(&game); /* display board state */ PossibleMoves(&game,&number_of_moves,moves); /* calculate available moves */ rand = (int) (drand48()*number_of_moves); /* pick a random move */ MakeMove(&game,moves[rand]); /* make move */ DisplayMove(moves[rand]); /* display move */ …

  32. int main() if (playagainsthuman) /* play against human opponent */ { DisplayBoard(&game); /* show board state after computer moved */ if (!Draw(&game) && !Win(&game,RED)) /* no draw and no computer win */ { EnterMove(&move,&game); /* human player enters her move */ MakeMove(&game,move); /* make move */ } } /* end of human player play */ } /* end of while not draw or win */

  33. int main() DisplayBoard(&game); /* display board state */ if (Draw(&game)) printf("the game ended in a draw\n"); if (Win(&game, RED)) printf("player red won the game\n"); if (Win(&game, BLACK)) printf("player black won the game\n"); return 0; } /* end of main */

  34. Makefile OBJS = game.o # for gcc compiler .... CC = gcc CFLAGS = -g -Wall #naming executable EXEC = game all: $(EXEC) %.o:%.c $(CC) $(CFLAGS) -c $< $(EXEC): $(OBJS) $(CC) -o $@ $(OBJS)

  35. Question of the Day • Draw a closed path of four straight lines that connects all nine dots.

More Related