w 2 l 1 sh 1 c lessons lessonsubjectbook week 1 lesson 1objects, names week 1 lesson 2statements,...
TRANSCRIPT
W 2 L 1 sh 1
C lessons
Lesson Subject Book
Week 1 lesson 1 Objects, names
Week 1 lesson 2 Statements, layout
Week 2 lesson 1 Functions, decomposition
Week 2 lesson 2 Recursion, minimax
Week 3 lesson 1 Memory, testing
Week 3 lesson 2 Fagan 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 Have a terminating condition 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 loopunsigned int add( unsigned int a, unsigned int b ){
while( b != 0 ){
a++;
b--;
}
return a;
}
Multi-point recursion (in general) can notint 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 < 2200.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
Game Typical branching factor
Tic-Tac-Toe 4
Connect-4 6
Reversi 8
Checkers 10
Chess 40
Go 300
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? When neither side can move, count the pieces, decide
whether it is a draw, win, or loss. Otherwise ….
Count the pieces Mobility: the number of moves I can choose from Preferred fields:
Corners are very good Next-to-corner is very bad (unless you have the corner) Other border fields are moderately good 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.