W 2 L 1 sh 1 C lessons LessonSubjectBook Week 1 lesson 1Objects, names Week 1 lesson 2Statements, layout Week 2 lesson 1Functions, decomposition Week 2 lesson 2Recursion, minimax Week 3 lesson 1Memory, testing Week 3 lesson 2Fagan inspection
W 2 L 1 sh 2 Recursion A function can call itself unsigned int add( unsigned int a, unsigned int b ){ if( b == 0 ){ return a ); } return add( ++a, --b ); } Useful recursion must n Have a terminating condition n Recurse to a simpler case (nearer to the terminating condition)
W 2 L 1 sh 3 Recursion – rewrite? One-point recursion can always be rewritten as a loop unsigned int add( unsigned int a, unsigned int b ){ while( b != 0 ){ a++; b--; } return a; } Multi-point recursion (in general) can not int lagest( node * node ){ int result = – MAXINT; if( node != NULL ){ result = maximum( result, node->value )); result = maximum( result, largest( node->left )); result = maximum( result, largest( node->right )); } return result; }
W 2 L 1 sh 4 Recursion – watch out for the stack! void flood_fill( int x, int y, int original, int fill ){ if( ! in_bounds( x, y ){ return; }; flood_fill_flood( x, y - 1, original, fill ); flood_fill_flood( x, y + 1, original, fill ); flood_fill_flood( x - 1, y, original, fill ); flood_fill_flood( x + 1, y, original, fill ); } The DS screen is (only) 256x192. I had to limit the recursion depth to < Note: 2200 still crashes on the real NDS
W 2 L 1 sh 5 Game theory: minimax In a Which move should I select? Move 1; then my opponent can select Move 1.1 : I lose Move 1.2 : I win Move 2; then my opponent can select Move 2.1 : draw Move 2.2 : draw You opponent should minimize your result, from those minimums you should select the maximum.
W 2 L 1 sh 6 Recursive minimax int minimax( board b, side s ){ int result = worse than all possible results for s; for( all allowed moves m for side s ){ b1 = make_move( b, m ); outcome = minimax( b1, !s ); if( outcome is better for me than current result ){ result = outcome; } return result; } What is missing?
W 2 L 1 sh 7 Recursive minimax int minimax( board b, side s, int depth ){ if( depth int result = worse than all possible results for s; for( all allowed moves m for side s ){ b1 = make_move( b, m ); outcome = minimax( b1, !s, depth - 1 ); if( outcome is better for me than current result ){ result = outcome; } return result; }
W 2 L 1 sh 8 Branching factor A move by one side is often called a ply. A move from by one side, followed by a move by the other side is called a full move. The number of possible moves by one side is called the branching factor. The branching factor determines how deep you can evaluate. Why?
W 2 L 1 sh 9 Typical branching factors GameTypical branching factor Tic-Tac-Toe4 Connect-46 Reversi8 Checkers10 Chess40 Go300 Humans are very good at evaluation only ‘good’ moves to a reasonable depth. Computers mainly rely on speed to evaluate (and remember) all moves (brute force method).
W 2 L 1 sh 10 Reversi board evaluation I see a situation on the board. How good its it for me? n When neither side can move, count the pieces, decide whether it is a draw, win, or loss. n Otherwise …. n Count the pieces n Mobility: the number of moves I can choose from n Preferred fields: n Corners are very good n Next-to-corner is very bad (unless you have the corner) n Other border fields are moderately good n Other next-to-border fields are moderately bad
W 2 L 1 sh 11 Reversi application week-2-2.zip Complete application Two nearly identical projects: PC and NDS Each side can be man or machine NDS version is ‘better’ for a human player (GUI) PC version is faster (better for machine-versus- machine)
W 2 L 1 sh 12 Reversi application - evaluators int evaluate_mobility( board b, int color ){ return reversi_board_n_moves( b, color ); } int evaluate_count( board b, int color ){ return reversi_board_count_color( b, color ) - reversi_board_count_color( b, reversi_opponent( color )); }
W 2 L 1 sh 13 Reversi application - main void show( board b, int color ){ reversi_board_print_lcd( b, color ); int i; for( i =0 ; i < 10; i++ ){ swiWaitForVBlank(); } int main( void ){ console_init_top(); (void) play_game( evaluate_mobility, 2, evaluate_count, 2, 1, show ); return 0; } void show( board b, int color ){} int main(int argc, char *argv[]){ (void) play_game( evaluate_mobility, 4, evaluate_count, 4, 1, show ); system( "PAUSE" ); return 0; }
W 2 L 1 sh 14 Assignment – for each V2TH05 group (1) Imagine that we are planning to write a reversi application. As part of the preparation phase we need some data. I want a short report (1-4 pages) with answers to the following questions: How do the two evaluators score against each other (at various evaluation depths)? Add a weighted-fields based evaluator and compare its performance against the other two. Evaluate the playing strength of one group member against various evaluators at various evaluation depths.
W 2 L 1 sh 15 Assignment – for each V2TH05 group (2) What is the speed factor between the NDS and a PC when running machine-against-machine? (Check the code, don’t put the NDS at a disadvantage!) The current application is deterministic: each run is the same. This makes it impossible to average a number of games to get a good idea of the strength of two evaluators How can this be changed? (Multiple answers possible. You don’t need to do it, imagine that you are pointing a colleague in the right direction). Try your weighted-fields evaluator against (at least) one other group.
W 2 L 1 sh 16 Assignment – for each V2TH05 group (3) Requirements for the document: 1. Either Dutch or English (but use only one language!). 2. Readable, no SMS or telegram style. 3. All questions must be answered and (when applicable) motivated. 4. Explain your weighted-fields evaluator.