Ticket #107: gunnar_7_9.14b.diff
| File gunnar_7_9.14b.diff, 29.7 KB (added by gunnar, 4 years ago) |
|---|
-
doc/gtp-commands.texi
RCS file: /cvsroot/gnugo/gnugo/doc/gtp-commands.texi,v retrieving revision 1.28 diff -u -r1.28 gtp-commands.texi
762 762 @cindex analyze_eyegraph 763 763 @item analyze_eyegraph: Compute an eyevalue and vital points for an eye graph 764 764 @verbatim 765 Arguments: Eyeshape encoded in string 765 Arguments: Eyeshape encoded in string OR two integers followed by eyeshape 766 766 Fails: Bad eyeshape, analysis failed 767 767 Returns: Eyevalue, vital points 768 768 @end verbatim -
engine/liberty.h
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v retrieving revision 1.258 diff -u -r1.258 liberty.h
664 664 int max_eye_value(int pos); 665 665 void test_eyeshape(int eyesize, int *eye_vertices); 666 666 int analyze_eyegraph(const char *coded_eyegraph, struct eyevalue *value, 667 char *analyzed_eyegraph); 667 char *analyzed_eyegraph, int outer_liberties, 668 int ko_threats); 668 669 669 670 670 671 /* debugging support */ -
engine/optics.c
RCS file: /cvsroot/gnugo/gnugo/engine/optics.c,v retrieving revision 1.105 diff -u -r1.105 optics.c
2657 2691 * 3 - result has been computed and was a success (1) 2658 2692 */ 2659 2693 2694 /* Types of vertices under consideration. */ 2695 #define REGULAR 0 2696 #define OUTER_LIBERTY 1 2697 #define EXTRA_EYE 2 2698 #define KO_THREAT 3 2699 2700 #define MAX_OUTER_LIBERTIES 4 2701 #define MAX_KO_THREATS 4 2702 2703 struct vertex_data { 2704 int pos[MAX_BOARD]; 2705 int type[MAX_BOARD]; 2706 int num; 2707 int ko_threat_pos[MAX_KO_THREATS]; 2708 int num_ko_threats; 2709 int num_ordinary; 2710 int komaster; 2711 int extra_eye_pos; 2712 int string; 2713 }; 2714 2660 2715 /* Like trymove() except that it does a superko check. This does, 2661 * however, only disallow repetition (besides simple ko) if the move 2662 * does not capture any stones. 2716 * however, only disallow repetition (besides simple ko) for the 2717 * attacker. 2718 * 2719 * In order to cope with bent four in the corner, white is given one 2720 * free virtual ko threat, which black can eliminate by spending a 2721 * move playing on the "ko threat vertex". This has the side effect 2722 * that white wins all direct kos, which is mostly okay until ko 2723 * dependent eye values are implemented. It can, however, cause attack 2724 * and defense points dependent on ko to be recommended together with 2725 * non-ko vital points. 2663 2726 */ 2727 2728 static int forced_ko_threat_stackp[MAX_KO_THREATS]; 2729 static int num_active_ko_threats = 0; 2730 2664 2731 static int 2665 eyegraph_trymove(int pos, int color, const char *message, int str) 2732 eyegraph_trymove(int pos, int color, const char *message, int str, 2733 struct vertex_data *vertices) 2666 2734 { 2667 2735 static Hash_data remembered_board_hashes[MAXSTACK]; 2668 2736 int k; 2669 int does_capture = does_capture_something(pos, color);2670 2737 2671 2738 remembered_board_hashes[stackp] = board_hash; 2672 2673 if (!trymove(pos, color, message, str))2674 return 0;2675 2739 2676 if (does_capture) 2740 if (!trymove(pos, color, message, str)) { 2741 int ko_threat_pos = NO_MOVE; 2742 2743 if (!vertices) 2744 return 0; 2745 2746 if (color != vertices->komaster 2747 || is_suicide(pos, color)) 2748 return 0; 2749 2750 for (k = 0; k < vertices->num_ko_threats; k++) 2751 if (board[vertices->ko_threat_pos[k]] == EMPTY) { 2752 ko_threat_pos = vertices->ko_threat_pos[k]; 2753 break; 2754 } 2755 2756 if (ko_threat_pos != NO_MOVE) { 2757 trymove(ko_threat_pos, BLACK, "making/answering virtual ko threat", str); 2758 forced_ko_threat_stackp[num_active_ko_threats++] = stackp; 2759 trymove(pos, color, message, str); 2760 } 2761 else 2762 return 0; 2763 } 2764 2765 if (color == WHITE) 2677 2766 return 1; 2678 2767 2679 2768 for (k = 0; k < stackp; k++) … … 2685 2774 return 1; 2686 2775 } 2687 2776 2777 static void 2778 eyegraph_popgo(void) 2779 { 2780 popgo(); 2781 2782 if (num_active_ko_threats > 0 2783 && forced_ko_threat_stackp[num_active_ko_threats - 1] == stackp) { 2784 popgo(); 2785 num_active_ko_threats--; 2786 } 2787 } 2788 2789 /* Has the vertex a neighbor which is connected to an invincible black 2790 * string? 2791 */ 2688 2792 static int 2689 2793 eyegraph_is_margin_or_outer_liberty(int vertex) 2690 2794 { … … 2711 2815 } 2712 2816 2713 2817 static int 2714 eyegraph_order_moves(int num_vertices, int *vertices, int color_to_move, int *moves) 2818 eyegraph_order_moves(struct vertex_data *vertices, int color_to_move, 2819 int *moves) 2715 2820 { 2716 2821 int num_moves = 0; 2717 2822 int scores[BOARDMAX]; … … 2720 2825 int k; 2721 2826 int r; 2722 2827 2723 for (k = 0; k < num_vertices; k++) {2724 if ( k >= num_vertices - 3) {2828 for (k = 0; k < vertices->num; k++) { 2829 if (vertices->type[k] != REGULAR) { 2725 2830 /* Never useful for white to fill in outer liberties or a second eye. */ 2726 2831 if (color_to_move == WHITE) 2727 2832 break; 2728 /* No use playing the second outer liberty before the first one. */ 2729 if (k == num_vertices - 2 && board[vertices[num_vertices - 3]] == EMPTY) 2833 /* No use playing a later outer liberty before the previous one. */ 2834 if (vertices->type[k] == OUTER_LIBERTY 2835 && vertices->type[k - 1] == OUTER_LIBERTY 2836 && board[vertices->pos[k - 1]] == EMPTY) 2730 2837 continue; 2731 2838 } 2732 2839 2733 move = vertices [k];2840 move = vertices->pos[k]; 2734 2841 score = 0; 2735 2842 2736 2843 if (board[move] != EMPTY) 2737 2844 continue; 2738 2845 2739 if (eyegraph_is_margin_or_outer_liberty(move)) {2740 if ( k < num_vertices - 3)2846 if (eyegraph_is_margin_or_outer_liberty(move)) 2847 if (vertices->type[k] == REGULAR) 2741 2848 score = 5; /* margin */ 2742 else2743 score = -10; /* outer liberty */2744 }2745 2849 2746 2850 if (accuratelib(move, color_to_move, 2, NULL) == 1) 2747 2851 score -= 3; … … 2843 2947 return (result); \ 2844 2948 } while (0); 2845 2949 2846 static int tactical_life_defend(int str, int num_vertices, int*vertices,2950 static int tactical_life_defend(int str, struct vertex_data *vertices, 2847 2951 unsigned char *results); 2848 2952 2849 2953 /* Determine whether black can capture all white stones. */ 2850 2954 static int 2851 tactical_life_attack(int str, int num_vertices, int*vertices,2955 tactical_life_attack(int str, struct vertex_data *vertices, 2852 2956 unsigned char *results) 2853 2957 { 2854 2958 int k; … … 2859 2963 int moves[BOARDMAX]; 2860 2964 2861 2965 /* Compute hash value to index the result cache with. */ 2862 for (k = 0; k < num_vertices; k++) {2966 for (k = 0; k < vertices->num; k++) { 2863 2967 hash *= 3; 2864 hash += board[vertices [k]];2968 hash += board[vertices->pos[k]]; 2865 2969 } 2866 2970 hash *= 2; 2867 2971 hash += (board_ko_pos != NO_MOVE); … … 2885 2989 results[hash] |= 1; 2886 2990 2887 2991 /* Try to play on all relevant vertices. */ 2888 num_moves = eyegraph_order_moves(num_vertices, vertices, 2889 OTHER_COLOR(board[str]), moves); 2992 num_moves = eyegraph_order_moves(vertices, OTHER_COLOR(board[str]), moves); 2890 2993 for (k = 0; k < num_moves; k++) { 2891 2994 int move = moves[k]; 2892 2995 if (eyegraph_trymove(move, OTHER_COLOR(board[str]), 2893 "tactical_life_attack", str)) { 2996 "tactical_life_attack", str, 2997 vertices)) { 2894 2998 /* We were successful if the white stones were captured or if no 2895 2999 * defense can be found. 2896 3000 */ 2897 3001 if (board[str] == EMPTY) 2898 3002 result = 1; 2899 3003 else 2900 result = !tactical_life_defend(str, num_vertices,vertices, results);3004 result = !tactical_life_defend(str, vertices, results); 2901 3005 2902 popgo();3006 eyegraph_popgo(); 2903 3007 2904 3008 if (result == 1) { 2905 3009 /* Store the result (success) in the cache. */ … … 2916 3020 2917 3021 /* Determine whether white can live with all stones. */ 2918 3022 static int 2919 tactical_life_defend(int str, int num_vertices, int*vertices,3023 tactical_life_defend(int str, struct vertex_data *vertices, 2920 3024 unsigned char *results) 2921 3025 { 2922 3026 int k; … … 2927 3031 int moves[BOARDMAX]; 2928 3032 2929 3033 /* Compute hash value to index the result cache with. */ 2930 for (k = 0; k < num_vertices; k++) {3034 for (k = 0; k < vertices->num; k++) { 2931 3035 hash *= 3; 2932 ASSERT1(board[vertices [k]] <= 2, vertices[k]);2933 hash += board[vertices [k]];3036 ASSERT1(board[vertices->pos[k]] <= 2, vertices->pos[k]); 3037 hash += board[vertices->pos[k]]; 2934 3038 } 2935 3039 hash *= 2; 2936 3040 hash += (board_ko_pos != NO_MOVE); … … 2954 3058 results[hash] |= (1 << 2); 2955 3059 2956 3060 /* Try to play on all relevant vertices. */ 2957 num_moves = eyegraph_order_moves( num_vertices,vertices, board[str], moves);3061 num_moves = eyegraph_order_moves(vertices, board[str], moves); 2958 3062 for (k = 0; k < num_moves; k++) { 2959 3063 int move = moves[k]; 2960 3064 if ((!is_suicide(move, OTHER_COLOR(board[str])) 2961 3065 || does_capture_something(move, board[str])) 2962 && eyegraph_trymove(move, board[str], "tactical_life_defend", str)) { 3066 && eyegraph_trymove(move, board[str], "tactical_life_defend", str, 3067 vertices)) { 2963 3068 /* We were successful if no attack can be found. */ 2964 result = !tactical_life_attack(str, num_vertices,vertices, results);3069 result = !tactical_life_attack(str, vertices, results); 2965 3070 2966 popgo();3071 eyegraph_popgo(); 2967 3072 2968 3073 if (result == 1) { 2969 3074 /* Store the result (success) in the cache. */ … … 2974 3079 } 2975 3080 2976 3081 /* If no move worked, also try passing. */ 2977 if (!tactical_life_attack(str, num_vertices,vertices, results)) {3082 if (!tactical_life_attack(str, vertices, results)) { 2978 3083 /* Store the result (success) in the cache. */ 2979 3084 results[hash] = (results[hash] & (~12)) | (3 << 2); 2980 3085 EYEGRAPH_RETURN(1, "tactical_life_defend: win"); … … 2991 3096 * used or filled in before starting reading. 2992 3097 */ 2993 3098 static void 2994 tactical_life(int have_eye, int num_vertices, int*vertices,3099 tactical_life(int have_eye, struct vertex_data *vertices, 2995 3100 int *attack_code, int *num_attacks, int *attack_points, 2996 3101 int *defense_code, int *num_defenses, int *defense_points, 2997 3102 unsigned char *results) … … 3007 3112 * vertex we test to determine whether the white stones have been 3008 3113 * captured. 3009 3114 */ 3010 str = POS(1, 0);3115 str = vertices->string; 3011 3116 3012 3117 if (board[str] == EMPTY) { 3013 3118 /* The stones have already been captured, too late to defend. */ … … 3020 3125 * suicide the white stones can be considered dead. 3021 3126 */ 3022 3127 if (!have_eye) { 3023 if (!eyegraph_trymove(POS(0, 0), WHITE, "tactical_life-A", NO_MOVE)) { 3128 if (!eyegraph_trymove(vertices->extra_eye_pos, WHITE, "tactical_life-A", 3129 NO_MOVE, NULL)) { 3024 3130 *attack_code = WIN; 3025 3131 *defense_code = 0; 3026 3132 return; … … 3033 3139 /* Call tactical_life_attack() and tactical_life_defend() to 3034 3140 * determine status. 3035 3141 */ 3036 if (tactical_life_attack(str, num_vertices,vertices, results)) {3142 if (tactical_life_attack(str, vertices, results)) { 3037 3143 *attack_code = WIN; 3038 if (tactical_life_defend(str, num_vertices,vertices, results))3144 if (tactical_life_defend(str, vertices, results)) 3039 3145 *defense_code = WIN; 3040 3146 } 3041 3147 else … … 3049 3155 if (*attack_code != 0 && *defense_code != 0) { 3050 3156 if (num_attacks != NULL && attack_points != NULL) { 3051 3157 *num_attacks = 0; 3052 num_moves = eyegraph_order_moves( num_vertices,vertices,3158 num_moves = eyegraph_order_moves(vertices, 3053 3159 OTHER_COLOR(board[str]), moves); 3054 3160 for (k = 0; k < num_moves; k++) { 3055 3161 int move = moves[k]; 3056 3162 if (eyegraph_trymove(move, OTHER_COLOR(board[str]), "tactical_life-B", 3057 str )) {3163 str, vertices)) { 3058 3164 if (board[str] == EMPTY 3059 || !tactical_life_defend(str, num_vertices,vertices, results))3165 || !tactical_life_defend(str, vertices, results)) 3060 3166 attack_points[(*num_attacks)++] = move; 3061 popgo();3167 eyegraph_popgo(); 3062 3168 } 3063 3169 } 3064 3170 } 3065 3171 3066 3172 if (num_defenses != NULL && defense_points != NULL) { 3067 3173 *num_defenses = 0; 3068 num_moves = eyegraph_order_moves(num_vertices, vertices, board[str], 3069 moves); 3174 num_moves = eyegraph_order_moves(vertices, board[str], moves); 3070 3175 for (k = 0; k < num_moves; k++) { 3071 3176 int move = moves[k]; 3072 if (eyegraph_trymove(move, board[str], "tactical_life-C", str)) { 3073 if (!tactical_life_attack(str, num_vertices, vertices, results)) 3177 if (eyegraph_trymove(move, board[str], "tactical_life-C", str, 3178 vertices)) { 3179 if (!tactical_life_attack(str, vertices, results)) 3074 3180 defense_points[(*num_defenses)++] = move; 3075 popgo();3181 eyegraph_popgo(); 3076 3182 } 3077 3183 } 3078 3184 } … … 3080 3186 3081 3187 /* Unfill the extra eye if we didn't use it. */ 3082 3188 if (!have_eye) 3083 popgo();3189 eyegraph_popgo(); 3084 3190 } 3085 3191 3086 3192 /* Determine the eye value of the eyespace for the big white group on … … 3095 3201 * need to recursively call ourselves after a move has been made. 3096 3202 */ 3097 3203 static void 3098 evaluate_eyespace(struct eyevalue *result, int num_vertices, int*vertices,3204 evaluate_eyespace(struct eyevalue *result, struct vertex_data *vertices, 3099 3205 int *num_vital_attacks, int *vital_attacks, 3100 3206 int *num_vital_defenses, int *vital_defenses, 3101 3207 unsigned char *tactical_life_results) … … 3123 3229 *num_vital_defenses = 0; 3124 3230 3125 3231 /* Determine tactical life without an extra eye. */ 3126 tactical_life(0, num_vertices,vertices,3232 tactical_life(0, vertices, 3127 3233 &attack_code, &num_attacks, attack_points, 3128 3234 &defense_code, &num_defenses, defense_points, 3129 3235 tactical_life_results); … … 3139 3245 if (sgf_dumptree) 3140 3246 sgftreeAddComment(sgf_dumptree, "Alive without extra eye.\n"); 3141 3247 3142 num_moves = eyegraph_order_moves( num_vertices,vertices, BLACK, moves);3248 num_moves = eyegraph_order_moves(vertices, BLACK, moves); 3143 3249 for (k = 0; k < num_moves; k++) { 3144 3250 int acode, dcode; 3145 3251 int move = moves[k]; 3146 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-A", NO_MOVE)) { 3147 tactical_life(0, num_vertices, vertices, &acode, NULL, NULL, 3252 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-A", NO_MOVE, 3253 vertices)) { 3254 tactical_life(0, vertices, &acode, NULL, NULL, 3148 3255 &dcode, NULL, NULL, tactical_life_results); 3149 3256 if (acode != 0) { 3150 tactical_life(1, num_vertices,vertices, &acode, NULL, NULL,3257 tactical_life(1, vertices, &acode, NULL, NULL, 3151 3258 &dcode, NULL, NULL, tactical_life_results); 3152 3259 if (acode != 0) { 3153 3260 if (a == 1) … … 3167 3274 sgftreeAddComment(sgf_dumptree, "Ko threat to remove one eye.\n"); 3168 3275 } 3169 3276 } 3170 popgo();3277 eyegraph_popgo(); 3171 3278 } 3172 3279 } 3173 3280 set_eyevalue(result, a, 2, 2, 2); … … 3186 3293 */ 3187 3294 if (sgf_dumptree) 3188 3295 sgftreeAddComment(sgf_dumptree, "Critical without extra eye.\n"); 3189 tactical_life(1, num_vertices,vertices,3296 tactical_life(1, vertices, 3190 3297 &attack_code2, &num_attacks2, attack_points2, 3191 3298 &defense_code2, NULL, NULL, tactical_life_results); 3192 3299 for (k = 0; k < num_defenses; k++) … … 3203 3310 int a = 1; 3204 3311 for (k = 0; k < num_attacks; k++) { 3205 3312 int move = attack_points[k]; 3206 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-B", NO_MOVE)) { 3207 evaluate_eyespace(&result2, num_vertices, vertices, 3313 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-B", NO_MOVE, 3314 vertices)) { 3315 evaluate_eyespace(&result2, vertices, 3208 3316 &num_vital_attacks2, vital_attacks2, 3209 3317 &num_vital_defenses2, vital_defenses2, 3210 3318 tactical_life_results); … … 3221 3329 } 3222 3330 else if (a == 1) 3223 3331 vital_attacks[(*num_vital_attacks)++] = move; 3224 popgo();3332 eyegraph_popgo(); 3225 3333 } 3226 3334 } 3227 3335 set_eyevalue(result, a, 1, 2, 2); … … 3241 3349 */ 3242 3350 if (sgf_dumptree) 3243 3351 sgftreeAddComment(sgf_dumptree, "Dead without extra eye.\n"); 3244 tactical_life(1, num_vertices,vertices,3352 tactical_life(1, vertices, 3245 3353 &attack_code, &num_attacks, attack_points, 3246 3354 &defense_code, &num_defenses, defense_points, 3247 3355 tactical_life_results); … … 3253 3361 int d = 1; 3254 3362 if (sgf_dumptree) 3255 3363 sgftreeAddComment(sgf_dumptree, "Alive with extra eye.\n"); 3256 num_moves = eyegraph_order_moves( num_vertices,vertices, BLACK, moves);3364 num_moves = eyegraph_order_moves(vertices, BLACK, moves); 3257 3365 for (k = 0; k < num_moves; k++) { 3258 3366 int acode, dcode; 3259 3367 int move = moves[k]; 3260 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-C", NO_MOVE)) { 3261 tactical_life(1, num_vertices, vertices, &acode, NULL, NULL, 3368 if (eyegraph_trymove(move, BLACK, "evaluate_eyespace-C", NO_MOVE, 3369 vertices)) { 3370 tactical_life(1, vertices, &acode, NULL, NULL, 3262 3371 &dcode, NULL, NULL, tactical_life_results); 3263 3372 if (acode != 0) { 3264 evaluate_eyespace(&result2, num_vertices,vertices,3373 evaluate_eyespace(&result2, vertices, 3265 3374 &num_vital_attacks2, vital_attacks2, 3266 3375 &num_vital_defenses2, vital_defenses2, 3267 3376 tactical_life_results); … … 3273 3382 sgftreeAddComment(sgf_dumptree, "Attacking ko threat.\n"); 3274 3383 } 3275 3384 } 3276 popgo();3385 eyegraph_popgo(); 3277 3386 } 3278 3387 } 3279 3388 3280 num_moves = eyegraph_order_moves( num_vertices,vertices, WHITE, moves);3389 num_moves = eyegraph_order_moves(vertices, WHITE, moves); 3281 3390 for (k = 0; k < num_moves; k++) { 3282 3391 int acode, dcode; 3283 3392 int move = moves[k]; 3284 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-D", NO_MOVE)) { 3285 tactical_life(0, num_vertices, vertices, &acode, NULL, NULL, 3393 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-D", NO_MOVE, 3394 vertices)) { 3395 tactical_life(0, vertices, &acode, NULL, NULL, 3286 3396 &dcode, NULL, NULL, tactical_life_results); 3287 3397 if (dcode != 0) { 3288 evaluate_eyespace(&result2, num_vertices,vertices,3398 evaluate_eyespace(&result2, vertices, 3289 3399 &num_vital_attacks2, vital_attacks2, 3290 3400 &num_vital_defenses2, vital_defenses2, 3291 3401 tactical_life_results); … … 3297 3407 sgftreeAddComment(sgf_dumptree, "Defending ko threat.\n"); 3298 3408 } 3299 3409 } 3300 popgo();3410 eyegraph_popgo(); 3301 3411 } 3302 3412 } 3303 3413 set_eyevalue(result, a, 1, 1, d); … … 3323 3433 vital_attacks[(*num_vital_attacks)++] = attack_points[k]; 3324 3434 for (k = 0; k < num_defenses; k++) { 3325 3435 int move = defense_points[k]; 3326 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-E", NO_MOVE)) { 3327 evaluate_eyespace(&result2, num_vertices, vertices, 3436 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-E", NO_MOVE, 3437 vertices)) { 3438 evaluate_eyespace(&result2, vertices, 3328 3439 &num_vital_attacks2, vital_attacks2, 3329 3440 &num_vital_defenses2, vital_defenses2, 3330 3441 tactical_life_results); … … 3341 3452 } 3342 3453 else if (d == 1) 3343 3454 vital_defenses[(*num_vital_defenses)++] = move; 3344 popgo();3455 eyegraph_popgo(); 3345 3456 } 3346 3457 } 3347 3458 set_eyevalue(result, 0, 0, 1, d); … … 3361 3472 int d = 0; 3362 3473 if (sgf_dumptree) 3363 3474 sgftreeAddComment(sgf_dumptree, "Dead with extra eye.\n"); 3364 num_moves = eyegraph_order_moves( num_vertices,vertices, WHITE, moves);3475 num_moves = eyegraph_order_moves(vertices, WHITE, moves); 3365 3476 for (k = 0; k < num_moves; k++) { 3366 3477 int acode, dcode; 3367 3478 int move = moves[k]; 3368 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-F", NO_MOVE)) { 3369 tactical_life(1, num_vertices, vertices, &acode, NULL, NULL, 3479 if (eyegraph_trymove(move, WHITE, "evaluate_eyespace-F", NO_MOVE, 3480 vertices)) { 3481 tactical_life(1, vertices, &acode, NULL, NULL, 3370 3482 &dcode, NULL, NULL, tactical_life_results); 3371 3483 if (dcode != 0) { 3372 tactical_life(0, num_vertices,vertices, &acode, NULL, NULL,3484 tactical_life(0, vertices, &acode, NULL, NULL, 3373 3485 &dcode, NULL, NULL, tactical_life_results); 3374 3486 if (dcode != 0) { 3375 3487 if (d == 1) … … 3390 3502 "Ko threat to make one eye.\n"); 3391 3503 } 3392 3504 } 3393 popgo();3505 eyegraph_popgo(); 3394 3506 } 3395 3507 } 3396 3508 set_eyevalue(result, 0, 0, 0, d); … … 3477 3589 * !.*. 3478 3590 * 3479 3591 * If the eye graph cannot be realized, 0 is returned, 1 otherwise. 3592 * 3593 * The parameter outer_liberties determines how many external 3594 * liberties will be attached, excluding the one which is sometimes 3595 * provided by a second eye. Up to five outer liberties can be provided. 3596 * 3597 * The parameter ko_threats tells how many ko_threats one of the 3598 * players is allowed to ignore. Positive values mean that the 3599 * defender is allowed to ignore ko threats and negative that the 3600 * attacker can do so. The other player is allowed to spend a move to 3601 * reduce this number, which is usually not the best thing to do with 3602 * a move but allows a correct understanding of the bent four in the 3603 * corner shapes. At most 4 ignored ko threats are considered. 3480 3604 */ 3481 3605 int 3482 3606 analyze_eyegraph(const char *coded_eyegraph, struct eyevalue *value, 3483 char *analyzed_eyegraph) 3607 char *analyzed_eyegraph, int outer_liberties, 3608 int ko_threats) 3484 3609 { 3485 3610 int k; 3486 3611 int i, j; … … 3488 3613 int mx[BOARDMAX]; 3489 3614 char mg[BOARDMAX]; 3490 3615 int pos; 3616 int corner; 3617 int up; 3618 int right; 3491 3619 3492 3620 int num_vital_attacks; 3493 3621 int vital_attacks[BOARDMAX]; /* Way larger than necessary. */ … … 3503 3631 int num_margins; 3504 3632 int margins[BOARDMAX]; /* Way larger than necessary. */ 3505 3633 3506 int num_vertices; 3507 int vertices[BOARDMAX]; /* Way larger than necessary. */ 3508 3634 struct vertex_data vertices; 3635 3509 3636 int table_size; 3510 3637 unsigned char *tactical_life_results; 3511 3638 3512 3639 if (0) 3513 3640 gprintf("Analyze eyegraph %s\n", coded_eyegraph); 3641 3642 gg_assert(outer_liberties >= 0 && outer_liberties <= 5); 3643 gg_assert(ko_threats >= -4 && ko_threats <= 4); 3644 3645 if (ko_threats > 0) 3646 vertices.komaster = WHITE; 3647 else if (ko_threats == 0) 3648 vertices.komaster = EMPTY; 3649 else { 3650 vertices.komaster = BLACK; 3651 ko_threats = -ko_threats; 3652 } 3514 3653 3515 3654 /* Mark the eyespace in the mx array. We construct the position in 3516 3655 * the mx array and copy it to the actual board later. … … 3530 3669 for (k = 0; k < (int) strlen(coded_eyegraph); k++) { 3531 3670 if (coded_eyegraph[k] == '\n') 3532 3671 continue; 3672 if (coded_eyegraph[k] == ' ') 3673 continue; 3674 if (coded_eyegraph[k] == '\t') 3675 continue; 3533 3676 if (coded_eyegraph[k] == '%') { 3534 3677 num_rows++; 3535 3678 if (current_width > maxwidth) … … 3549 3692 3550 3693 /* Cut out the eyespace from the solid white string. */ 3551 3694 num_margins = 0; 3552 num_vertices= 0;3695 vertices.num = 0; 3553 3696 3554 3697 if (horizontal_edge == 0) 3555 3698 mini = -1; … … 3571 3714 char c = coded_eyegraph[k]; 3572 3715 if (c == '\n') 3573 3716 continue; 3717 if (c == ' ') 3718 continue; 3719 if (c == '\t') 3720 continue; 3574 3721 if (c == '%') { 3575 3722 i++; 3576 3723 j = minj - 1; … … 3583 3730 if (c == '!' || c == '@' || c == '(' || c == ')' || c == '$') 3584 3731 margins[num_margins++] = POS(i, j); 3585 3732 if (c != '|' && c != '-' && c != '+' && c != '%' 3586 && ON_BOARD(POS(i, j)) && mx[POS(i, j)] != WHITE) 3587 vertices[num_vertices++] = POS(i, j); 3733 && ON_BOARD(POS(i, j)) && mx[POS(i, j)] != WHITE) { 3734 vertices.type[vertices.num] = REGULAR; 3735 vertices.pos[vertices.num++] = POS(i, j); 3736 } 3588 3737 j++; 3589 3738 } 3590 3739 3591 /* Add an invincible black group in the lower left plus two outer 3592 * liberties for the white string. However, if the eyespace is 3593 * placed in or near the lower left corner, we put this group in the 3594 * upper right instead. 3740 vertices.num_ordinary = vertices.num; 3741 3742 /* Add an invincible black group in the lower left corner plus outer 3743 * liberties for the white string and space for virtual ko threats. 3744 * However, if the eyespace is placed in or near the lower left 3745 * corner, we put this group in the upper right instead. 3746 * 3747 * |aaaaa 3748 * |XXXXX 3749 * |.X.X 3750 * |XXXXX 3751 * |bbbbX 3752 * +----- 3753 * 3754 * a - up to five outer liberties (empty if active, otherwise O) 3755 * b - up to four virtual ko threats (always empty) 3595 3756 */ 3596 pos = POS(board_size - 2, 1); 3757 corner = POS(board_size - 1, 0); 3758 up = DELTA(-1, 0); 3759 right = DELTA(0, 1); 3597 3760 if ((vertical_edge == 0 && horizontal_edge != 0) 3598 || (horizontal_edge > 0 && vertical_edge <= 0)) 3599 pos = POS(1, board_size - 2); 3600 mx[pos] = EMPTY; 3601 mx[NORTH(pos)] = BLACK; 3602 mx[NW(pos)] = BLACK; 3603 mx[NE(pos)] = EMPTY; 3604 mx[WEST(pos)] = BLACK; 3605 mx[EAST(pos)] = BLACK; 3606 mx[SW(pos)] = EMPTY; 3607 mx[SOUTH(pos)] = BLACK; 3608 mx[SE(pos)] = BLACK; 3609 if (ON_BOARD(NN(pos))) 3610 mx[NN(pos)] = EMPTY; 3611 else 3612 mx[SS(pos)] = EMPTY; 3613 3614 /* Add the two outer liberties in the lower left or upper right to 3615 * the list of vertices. 3761 || (horizontal_edge > 0 && vertical_edge <= 0)) { 3762 corner = POS(0, board_size - 1); 3763 up = DELTA(1, 0); 3764 right = DELTA(0, -1); 3765 } 3766 3767 #define LOCAL_COORD(i, j) corner + i * up + j * right 3768 3769 mx[LOCAL_COORD(0, 4)] = BLACK; 3770 mx[LOCAL_COORD(1, 0)] = BLACK; 3771 mx[LOCAL_COORD(1, 1)] = BLACK; 3772 mx[LOCAL_COORD(1, 2)] = BLACK; 3773 mx[LOCAL_COORD(1, 3)] = BLACK; 3774 mx[LOCAL_COORD(1, 4)] = BLACK; 3775 mx[LOCAL_COORD(2, 1)] = BLACK; 3776 mx[LOCAL_COORD(2, 3)] = BLACK; 3777 mx[LOCAL_COORD(3, 0)] = BLACK; 3778 mx[LOCAL_COORD(3, 1)] = BLACK; 3779 mx[LOCAL_COORD(3, 2)] = BLACK; 3780 mx[LOCAL_COORD(3, 3)] = BLACK; 3781 mx[LOCAL_COORD(3, 4)] = BLACK; 3782 mx[LOCAL_COORD(2, 0)] = EMPTY; 3783 mx[LOCAL_COORD(2, 2)] = EMPTY; 3784 3785 /* Virtual ko threat points. */ 3786 mx[LOCAL_COORD(0, 0)] = EMPTY; 3787 mx[LOCAL_COORD(0, 1)] = EMPTY; 3788 mx[LOCAL_COORD(0, 2)] = EMPTY; 3789 mx[LOCAL_COORD(0, 3)] = EMPTY; 3790 3791 vertices.num_ko_threats = 0; 3792 for (k = 0; k < ko_threats; k++) { 3793 vertices.type[vertices.num] = KO_THREAT; 3794 vertices.pos[vertices.num++] = LOCAL_COORD(0, k); 3795 vertices.ko_threat_pos[vertices.num_ko_threats++] = LOCAL_COORD(0, k); 3796 } 3797 3798 /* Outer liberties. */ 3799 for (k = 0; k < outer_liberties; k++) { 3800 vertices.type[vertices.num] = OUTER_LIBERTY; 3801 vertices.pos[vertices.num++] = LOCAL_COORD(4, k); 3802 mx[LOCAL_COORD(4, k)] = EMPTY; 3803 } 3804 3805 /* Add an extra eye in the upper left corner unless it is occupied. 3806 * In that case place the extra eye in the lower right instead. 3807 * Also pick up a vertex belonging to the large white string. 3616 3808 */ 3617 if ( ON_BOARD(NN(pos))) {3618 vertices [num_vertices++] = NE(pos);3619 vertices [num_vertices++] = NN(pos);3809 if (vertical_edge != 0 || horizontal_edge != 0) { 3810 vertices.extra_eye_pos = POS(0, 0); 3811 vertices.string = POS(1, 0); 3620 3812 } 3621 3813 else { 3622 vertices [num_vertices++] = SW(pos);3623 vertices [num_vertices++] = SS(pos);3814 vertices.extra_eye_pos = POS(board_size - 1, board_size - 1); 3815 vertices.string = POS(board_size - 2, board_size - 1); 3624 3816 } 3625 3626 /* Add an extra eye in the upper left corner. */3627 mx[POS(0, 0)] = EMPTY;3628 vertices [num_vertices++] = POS(0, 0);3817 3818 mx[vertices.extra_eye_pos] = EMPTY; 3819 vertices.type[vertices.num] = EXTRA_EYE; 3820 vertices.pos[vertices.num++] = vertices.extra_eye_pos; 3629 3821 3630 3822 if (!add_margins(num_margins, margins, mx)) 3631 3823 return 0; … … 3647 3839 * the playable vertices. 3648 3840 */ 3649 3841 for (pos = BOARDMIN; pos < BOARDMAX; pos++) 3650 if (board[pos] == WHITE && !same_string(pos, POS(1, 0))) { 3651 vertices[num_vertices] = vertices[num_vertices - 1]; 3652 vertices[num_vertices - 1] = vertices[num_vertices - 2]; 3653 vertices[num_vertices - 2] = vertices[num_vertices - 3]; 3654 vertices[num_vertices - 3] = pos; 3655 num_vertices++; 3842 if (board[pos] == WHITE && !same_string(pos, vertices.string)) { 3843 int k; 3844 for (k = vertices.num; vertices.type[k - 1] != REGULAR; k--) { 3845 vertices.type[k] = vertices.type[k - 1]; 3846 vertices.pos[k] = vertices.pos[k - 1]; 3847 } 3848 vertices.type[k] = REGULAR; 3849 vertices.pos[k] = pos; 3850 vertices.num++; 3656 3851 } 3657 3852 3658 3853 if (verbose) { 3659 3854 int k; 3660 3855 gprintf("\nPlayable vertices:\n"); 3661 for (k = 0; k < num_vertices; k++)3662 gprintf("%1m ", vertices[k]);3856 for (k = 0; k < vertices.num; k++) 3857 gprintf("%1m(%d) ", vertices.pos[k], vertices.type[k]); 3663 3858 gprintf("\n\n"); 3664 3859 } 3665 3860 3666 3861 /* Disable this test if you need to evaluate larger eyespaces, have 3667 3862 * no shortage of memory, and know what you're doing. 3668 3863 */ 3669 if ( num_vertices> 17) {3864 if (vertices.num > 17) { 3670 3865 gprintf("analyze_eyegraph: too large eyespace, %d vertices\n", 3671 num_vertices);3672 gg_assert( num_vertices<= 17);3866 vertices.num); 3867 gg_assert(vertices.num <= 17); 3673 3868 } 3674 3869 3675 /* The cache must have 2*3^ num_verticesentries. */3870 /* The cache must have 2*3^vertices.num entries. */ 3676 3871 table_size = 2; 3677 for (k = 0; k < num_vertices; k++)3872 for (k = 0; k < vertices.num; k++) 3678 3873 table_size *= 3; 3679 3874 3680 3875 /* Allocate memory for the cache. */ … … 3689 3884 sgffile_printboard(sgf_dumptree); 3690 3885 3691 3886 /* Evaluate the eyespace on the board. */ 3692 evaluate_eyespace(value, num_vertices,vertices,3887 evaluate_eyespace(value, &vertices, 3693 3888 &num_vital_attacks, vital_attacks, 3694 3889 &num_vital_defenses, vital_defenses, 3695 3890 tactical_life_results); … … 3708 3903 /* Encode the attack and defense points with symbols in the mg[] array. */ 3709 3904 memset(mg, ' ', sizeof(mg)); 3710 3905 3711 for (k = 0; k < num_vertices - 2; k++)3712 mg[vertices [k]] = (board[vertices[k]] == BLACK ? 'X' : '.');3906 for (k = 0; k < vertices.num_ordinary; k++) 3907 mg[vertices.pos[k]] = (board[vertices.pos[k]] == BLACK ? 'X' : '.'); 3713 3908 3714 3909 for (k = 0; k < num_margins; k++) 3715 3910 mg[margins[k]] = (mg[margins[k]] == 'X' ? '$' : '!'); -
interface/play_gtp.c
RCS file: /cvsroot/gnugo/gnugo/interface/play_gtp.c,v retrieving revision 1.181 diff -u -r1.181 play_gtp.c
3455 3455 3456 3456 3457 3457 /* Function: Compute an eyevalue and vital points for an eye graph 3458 * Arguments: Eyeshape encoded in string 3458 * Arguments: Eyeshape encoded in string OR two integers followed by eyeshape 3459 3459 * Fails: Bad eyeshape, analysis failed 3460 3460 * Returns: Eyevalue, vital points 3461 3461 */ … … 3463 3463 gtp_analyze_eyegraph(char *s) 3464 3464 { 3465 3465 struct eyevalue value; 3466 int outer_liberties; 3467 int ko_threats; 3468 int n = 0; 3466 3469 char analyzed_eyegraph[1024]; 3467 int result = analyze_eyegraph(s, &value, analyzed_eyegraph); 3470 int result; 3471 3472 if (sscanf(s, "%d %d %n", &outer_liberties, &ko_threats, &n) < 2) { 3473 outer_liberties = 4; 3474 ko_threats = 1; 3475 } 3476 3477 result = analyze_eyegraph(s + n, &value, analyzed_eyegraph, 3478 outer_liberties, ko_threats); 3468 3479 3469 3480 if (result == 0) 3470 3481 return gtp_failure("failed to analyze");
