Ticket #29: arend_7_7.2-large_scale_reorganization.diff

File arend_7_7.2-large_scale_reorganization.diff, 11.0 kB (added by arend, 3 years ago)

Reorganizes the large scale code, breaking it up into 3 smaller functions

  • engine/value_moves.c

    RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
    retrieving revision 1.151
    diff -u -p -r1.151 value_moves.c
     
    385385} 
    386386 
    387387 
    388 /* Test all the moves to see whether they can owl-attack on 
    389  * a large scale . Tested moves are 
     388 
     389/* Try whether the move at (pos) for (color) is also an owl attack on 
     390 * (target). (dist) is the distance to the dragon, and is used for a 
     391 * safety heuristic: distant moves are only accepted if they kill within 
     392 * few owl nodes. 
     393 */ 
     394static void 
     395try_large_scale_owl_attack(int pos, int color, int target, int dist) 
     396{ 
     397  int owl_nodes_before; 
     398  int owl_nodes_used; 
     399  int old_node_limit; 
     400  int new_node_limit; 
     401  int kworm = NO_MOVE; 
     402  int acode; 
     403  int save_verbose = verbose; 
     404   
     405  ASSERT1(board[target] == OTHER_COLOR(color), pos); 
     406  ASSERT1(!owl_attack_move_reason_known(pos, target), pos); 
     407  DEBUG(DEBUG_LARGE_SCALE, "Trying large scale move %1m on %1m\n", pos, target); 
     408   
     409  /* To avoid horizon effects, we temporarily increase  
     410   * the depth values to find the large scale attacks. 
     411   */ 
     412  increase_depth_values();  
     413   
     414  /* To reduce the amount of aji allowed for large scale 
     415   * attacks, we reduce the owl limit to 350 nodes for 
     416   * attacks at distance <= 1, and 150 nodes for attacks at 
     417   * distance >= 2. 
     418   */ 
     419  if (dist <= 1) 
     420    new_node_limit = gg_min(350, owl_node_limit); 
     421  else 
     422    new_node_limit = gg_min(150, owl_node_limit); 
     423  change_owl_node_limit(new_node_limit, &old_node_limit);  
     424 
     425  if (verbose > 0) 
     426    verbose--; 
     427 
     428  owl_nodes_before = get_owl_node_counter();  
     429  acode = owl_does_attack(pos, target, &kworm); 
     430  owl_nodes_used = get_owl_node_counter() - owl_nodes_before; 
     431   
     432  if (acode >= DRAGON2(target).owl_attack_code 
     433      && acode == WIN) { 
     434    add_owl_attack_move(pos, target, kworm, acode); 
     435    DEBUG(DEBUG_LARGE_SCALE | DEBUG_MOVE_REASONS, 
     436          "Move at %1m owl-attacks %1m on a large scale(%s).\n",  
     437          pos, target, result_to_string(acode)); 
     438  } 
     439  else 
     440    DEBUG(DEBUG_LARGE_SCALE, 
     441          "Move at %1m isn't a clean large scale attack on %1m (%s).\n", 
     442          pos, target, result_to_string(acode)); 
     443   
     444  DEBUG(DEBUG_LARGE_SCALE, "  owl nodes used = %d, dist = %d\n",  
     445        owl_nodes_used, dist); 
     446  /* Restore settings. */ 
     447  verbose = save_verbose; 
     448  change_owl_node_limit(old_node_limit, NULL); 
     449  decrease_depth_values();  
     450} 
     451 
     452 
     453#define MAXIMUM_LARGE_SCALE_DIST        3 
     454 
     455/* Test all the moves to see whether they can owl-attack a specific 
     456 * dragon on a large scale . Tested moves are 
    390457 * 1. Moves that already have a move reason.  
    391  * 2. Are not too far away from a small critical dragon (<= 6 stones).  
    392  *    The distance used is the Manhatan distance, and the maximum  
    393  *    distance is currently 3. 
     458 * 2. Are not too far away. 
     459 *    The distance used is the Manhattan distance, and the maximum  
     460 *    distance is MAXIMUM_LARGE_SCALE_DIST. 
    394461 */ 
    395462static void 
    396 find_large_scale_owl_attack_moves(int color) 
     463find_large_scale_owl_attacks_on_dragon(int color, int target) 
    397464{ 
    398   int pos; 
    399   int target; 
    400465  int x, y; 
    401   int dx, dy; 
    402   int N = 0; /* number of critical dragons found */ 
    403   int k; 
    404   int unstable_dragons[MAX_WORMS]; 
    405   int x_min_dragon[MAX_WORMS]; 
    406   int x_max_dragon[MAX_WORMS]; 
    407   int y_min_dragon[MAX_WORMS]; 
    408   int y_max_dragon[MAX_WORMS]; 
    409   int maximum_distance = 3;  /* maximum Manhatan distance tried */ 
     466  int x_min = board_size; 
     467  int x_max = 0; 
     468  int y_min = board_size; 
     469  int y_max = 0; 
    410470  int dist; 
    411471  int other = OTHER_COLOR(color); 
     472 
     473  ASSERT1(board[target] == other, target); 
    412474   
    413   if (debug & DEBUG_LARGE_SCALE) 
    414     gprintf("\nTrying to find large scale attack moves.\n"); 
    415      
    416   /* Identify the unstable dragons and store them in a list. */ 
    417   for (pos = BOARDMIN; pos < BOARDMAX; pos++) { 
    418     if (IS_STONE(board[pos])  
    419         && dragon[pos].origin == pos 
    420         && board[pos] == other)  
    421       if (dragon[pos].status == CRITICAL 
    422           || DRAGON2(pos).owl_status == CRITICAL) { 
    423          
    424         unstable_dragons[N] = pos; 
    425          
    426         if (debug & DEBUG_LARGE_SCALE) 
    427           gprintf("Small critical dragon found at %1m\n", pos); 
    428          
    429         /* Find the physical extension of the dragon, and remember it 
    430          * FIXME : probably there should be a better place to calculate 
    431          * them, maybe a new field in the dragon2 array ? 
    432          */ 
    433         x = I(pos); 
    434         y = J(pos); 
    435         x_min_dragon[N] = x_max_dragon[N] = x; 
    436         y_min_dragon[N] = y_max_dragon[N] = y; 
    437         for (dx = 0; dx < board_size; dx++) 
    438           for (dy = 0; dy < board_size; dy++) { 
    439              
    440             if (ON_BOARD2(dx, dy)  
    441                 && is_same_dragon(pos, POS(dx, dy))) { 
    442               if (dx < x_min_dragon[N])  
    443                 x_min_dragon[N] = dx; 
    444               if (dx > x_max_dragon[N])  
    445                 x_max_dragon[N] = dx; 
    446               if (dy < y_min_dragon[N])  
    447                 y_min_dragon[N] = dy; 
    448               if (dy > y_max_dragon[N])  
    449                 y_max_dragon[N] = dy; 
    450             } 
    451           } 
    452         N++; 
     475  /* Find the physical extension of the dragon. */ 
     476  for (x = 0; x < board_size; x++) 
     477    for (y = 0; y < board_size; y++) { 
     478      if (is_same_dragon(target, POS(x, y))) { 
     479        if (x < x_min) 
     480          x_min = x; 
     481        if (x > x_max) 
     482          x_max = x; 
     483        if (y < y_min) 
     484          y_min = y; 
     485        if (y > y_max) 
     486          y_max = y; 
    453487      } 
    454   } 
    455    
    456   /* For each unstable dragon, try to find large scale attacks. 
     488    } 
     489 
     490  ASSERT1(x_min <= x_max && y_min <= y_max, target); 
     491 
     492  /* Try to find large scale attacks. 
    457493   * We do this by first trying to find attacks at dist = 0, then 
    458    * dist = 1, etc., up to maximum_distance. 
     494   * dist = 1, etc., up to MAXIMUM_LARGE_SCALE_DIST. 
    459495   */ 
    460   for (k = 0; k < N; k++) 
    461     for (dist = 0; dist <= maximum_distance; dist++) 
    462       for (x = x_min_dragon[k]-dist; x <= x_max_dragon[k]+dist; x++) 
    463         for (y = y_min_dragon[k]-dist; y <= y_max_dragon[k]+dist; y++) { 
    464           target = unstable_dragons[k]; 
    465           pos = POS(x, y); 
    466            
    467           if (ON_BOARD2(x, y) && ON_BOARD1(pos) && (board[pos] == EMPTY)) { 
    468             int a, b; 
    469             a = abs(x - x_min_dragon[k]); 
    470             b = abs(x - x_max_dragon[k]); 
    471             dx = gg_min(a, b); 
    472             a = abs(y - y_min_dragon[k]); 
    473             b = abs(y - y_max_dragon[k]); 
    474             dy = gg_min(a, b); 
    475              
    476             if (gg_max(dx, dy) == dist) { /* maximum Manhatan distance */ 
    477               int has_move_reasons = 0; 
    478               int worth_trying = 0; 
    479                
    480               /* See if that move has other move reasons */ 
    481               has_move_reasons = 0; 
    482               for (a = 0; a < MAX_REASONS; a++) { 
    483                 int r = move[pos].reason[a]; 
    484                 if (r < 0) 
    485                   break; 
    486                  
    487                 has_move_reasons = 1; 
    488               } 
    489                
    490                
    491               /* We try all large scale attacks on small dragons (and  
    492                * only moves with other move reason). 
    493                */ 
    494               if (board[target] == other) 
    495                 worth_trying = (dragon[target].size <= 6 
    496                                 && has_move_reasons); 
    497                
    498               if (worth_trying) { 
    499                 int owl_nodes_before; 
    500                 int owl_nodes_used; 
    501                 int old_node_limit; 
    502                 int new_node_limit; 
    503                  
    504                 if (debug & DEBUG_LARGE_SCALE) 
    505                   gprintf("Trying large scale move %1m on %1m\n", pos, target); 
    506                  
    507                 /* To avoid horizon effects, we temporarily increase  
    508                  * the depth values to find the large scale attacks. 
    509                  */ 
    510                 increase_depth_values();  
    511                  
    512                 /* To reduce the amount of aji allowed for large scale 
    513                  * attacks, we reduce the owl limit to 350 nodes for 
    514                  * attacks at distance <= 1, and 150 nodes for attacks at 
    515                  * distance >= 2. 
    516                  */ 
    517                 if (dist <= 1) 
    518                   new_node_limit = gg_min(350, owl_node_limit); 
    519                 else 
    520                   new_node_limit = gg_min(150, owl_node_limit); 
    521                 change_owl_node_limit(new_node_limit, &old_node_limit);  
    522                  
    523                 /* Try large scale killing moves on opponent's stones. */ 
    524                 owl_nodes_before = get_owl_node_counter();  
    525                 if (board[target] == other 
    526                     && !owl_attack_move_reason_known(pos, target)) { 
    527                   int kworm = NO_MOVE; 
    528                   int acode; 
    529                   int save_verbose = verbose; 
    530                   if (verbose > 0) 
    531                     verbose--; 
    532  
    533                   acode = owl_does_attack(pos, target, &kworm); 
    534                    
    535                   owl_nodes_used = get_owl_node_counter() - owl_nodes_before; 
    536                    
    537                   if (acode >= DRAGON2(target).owl_attack_code 
    538                       && acode == WIN) { 
    539                     add_owl_attack_move(pos, target, kworm, acode); 
    540                     if (debug & DEBUG_LARGE_SCALE) 
    541                       gprintf("Move at %1m owl-attacks %1m on a large scale(%s).\n",  
    542                               pos, target, result_to_string(acode)); 
    543                   } 
    544                   else if (debug & DEBUG_LARGE_SCALE) 
    545                     gprintf("Move at %1m isn't a clean large scale attack on %1m (%s).\n", pos, target, result_to_string(acode)); 
    546                    
    547                   if (debug & DEBUG_LARGE_SCALE) 
    548                     gprintf("  owl nodes used = %d, dist = %d\n",  
    549                             owl_nodes_used, dist); 
    550                   verbose = save_verbose; 
    551                 } 
    552                  
    553                 /* Restore owl node limit */ 
    554                 change_owl_node_limit(old_node_limit, NULL); 
    555                  
    556                 /* Restore the depth values */ 
    557                 decrease_depth_values();  
    558               } 
    559             } 
    560           } 
    561         }        
     496  for (dist = 0; dist <= MAXIMUM_LARGE_SCALE_DIST; dist++) 
     497    for (x = gg_max(x_min - dist, 0); 
     498         x <= gg_min(x_max + dist, board_size - 1); x++) 
     499      for (y = gg_max(y_min - dist, 0); 
     500           y <= gg_min(y_max + dist, board_size - 1); y++) { 
     501        int pos = POS(x, y); 
     502        ASSERT1(ON_BOARD2(x, y), pos); 
     503         
     504        if (board[pos] == EMPTY) { 
     505          int a, b, dx, dy; 
     506          a = abs(x - x_min); 
     507          b = abs(x - x_max); 
     508          dx = gg_min(a, b); 
     509          a = abs(y - y_min); 
     510          b = abs(y - y_max); 
     511          dy = gg_min(a, b); 
     512 
     513          if (gg_max(dx, dy) == dist   
     514              && move[pos].reason[0] >= 0 
     515              && !owl_attack_move_reason_known(pos, target)) 
     516            /* Maximum Manhatan distance, move reason known but no owl 
     517             * attack yet. 
     518             */ 
     519            try_large_scale_owl_attack(pos, color, target, dist); 
     520           
     521        } 
     522      } 
    562523} 
    563524 
     525 
     526/* Try large scale owl attacks against all enemy dragons that are 
     527 * small (size <= 6) and critical. 
     528 */ 
     529static void 
     530find_large_scale_owl_attack_moves(int color) 
     531{ 
     532  int d; 
     533 
     534  DEBUG(DEBUG_LARGE_SCALE, "\nTrying to find large scale attack moves.\n"); 
     535  for (d = 0; d < number_of_dragons; d++) { 
     536    int target = dragon2[d].origin; 
     537    if (dragon[target].color == OTHER_COLOR(color) 
     538        && dragon[target].size <= 6 
     539        && (dragon[target].status == CRITICAL 
     540            || dragon2[d].owl_status == CRITICAL)) { 
     541      DEBUG(DEBUG_LARGE_SCALE, "Small critical dragon found at %1m\n", target); 
     542      find_large_scale_owl_attacks_on_dragon(color, target); 
     543    } 
     544  } 
     545} 
    564546 
    565547/* Test certain moves to see whether they (too) can owl-attack or 
    566548 * defend an owl critical dragon. Tested moves are