Skip to content

Commit c5d146e

Browse files
committed
Add ratio minimum empty intersection and better ratio thresholds to unsettled stone clearer
1 parent bc86e95 commit c5d146e

File tree

9 files changed

+286
-37
lines changed

9 files changed

+286
-37
lines changed

Makefile

+4-2
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ publish push: publish_npm publish_docs upload_to_cdn notify
4141

4242
beta: beta_npm upload_to_cdn
4343

44-
beta_npm: build
44+
beta_npm: build publish-beta
45+
46+
publish-beta:
47+
make -C engine/ publish-beta
4548
yarn publish --tag beta ./
46-
cd engine; yarn publish --tag beta ./
4749

4850
notify:
4951
MSG=`git log -1 --pretty="%B" | sed s/\"//g | sed s/\'//g `; \

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ To import into an application targeting the web:
1616
import { ... } from "goban";
1717
```
1818

19-
To import into an application targeting node:
19+
To import into an application targeting node, use the [goban-engine](https://www.npmjs.com/package/goban-engine) package:
2020

2121
```
22-
import { ... } from "goban/lib/engine";
22+
import { ... } from "goban-engine";
2323
```
2424

2525
# Documentation

engine/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ all:
44
@echo "To publish use make [publish|publish-beta]"
55

66
publish-beta:
7-
yarn publish --tag beta ./
7+
yarn publish --no-git-tag-version --tag beta ./

engine/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "goban-engine",
3-
"version": "0.8.1-beta.2",
3+
"version": "0.8.1-beta.3",
44
"description": "",
55
"main": "goban-engine.js",
66
"types": "goban-engine.d.ts",

src/engine/autoscore.ts

+89-31
Original file line numberDiff line numberDiff line change
@@ -408,11 +408,16 @@ export function autoscore(
408408
let amount_of_territory = 0;
409409
let number_of_possible_eyes = 0; // could be false eyes, but we'll count them at this stage
410410
group.foreachNeighboringEmptyString((empty_intersections) => {
411+
/*
411412
const { x, y } = empty_intersections.intersections[0];
412413
stage_log(
413-
`Group at ${encodePrettyXCoordinate(x)}${height - y} with color
414-
${group.color} has ${empty_intersections.intersections.length} empty intersections and is territory = ${empty_intersections.is_territory}`,
414+
`Group at ${encodePrettyXCoordinate(x)}${height - y} with color ${
415+
group.color
416+
} has ${
417+
empty_intersections.intersections.length
418+
} empty intersections and is territory = ${empty_intersections.is_territory}`,
415419
);
420+
*/
416421
if (empty_intersections.is_territory) {
417422
number_of_possible_eyes++;
418423
amount_of_territory += empty_intersections.intersections.length;
@@ -460,16 +465,16 @@ export function autoscore(
460465
* Consider unsettled groups. Count the unsettled stones along with
461466
* their neighboring stones
462467
*/
463-
const groups = new StoneStringBuilder(
468+
const unsettled_intersection_groups = new StoneStringBuilder(
464469
new BoardState({
465470
board: is_settled,
466471
removal: makeMatrix(width, height, false),
467472
}),
468473
);
469474

470-
debug_groups("Initial groups", groups);
475+
debug_groups("Settlement intersection groups", unsettled_intersection_groups);
471476

472-
groups.foreachGroup((group) => {
477+
unsettled_intersection_groups.foreachGroup((group) => {
473478
// if this group is a settled group, ignore it, we don't care about those
474479
const pt = group.intersections[0];
475480
if (is_settled[pt.y][pt.x]) {
@@ -488,8 +493,12 @@ export function autoscore(
488493
0, // white
489494
];
490495
let total_ownership_estimate = 0;
496+
let total_ownership_tally = 0;
491497

492498
const already_tallied = makeMatrix(width, height, 0);
499+
let tally_ct = 0;
500+
501+
/** Tallies the surrounding stones */
493502
function tally_edge(x: number, y: number) {
494503
if (x < 0 || x >= width || y < 0 || y >= height) {
495504
return;
@@ -511,54 +520,103 @@ export function autoscore(
511520
tally_edge(x + 1, y);
512521
tally_edge(x, y - 1);
513522
tally_edge(x, y + 1);
514-
515-
total_ownership_estimate +=
516-
black_plays_first_ownership[y][x] + white_plays_first_ownership[y][x];
523+
total_ownership_estimate += average_ownership[y][x];
524+
tally_ct += 1;
525+
526+
total_ownership_tally +=
527+
board[y][x] === JGOFNumericPlayerColor.BLACK
528+
? 1
529+
: board[y][x] === JGOFNumericPlayerColor.WHITE
530+
? -1
531+
: 0;
517532
});
518533

519-
const average_color_estimate = total_ownership_estimate / group.intersections.length;
534+
//const average_color_estimate =
535+
// total_ownership_estimate / (group.intersections.length * 2);
536+
//const average_color_estimate = total_ownership_estimate / tally_ct;
537+
const average_color_estimate = total_ownership_tally / tally_ct;
520538

521539
let color_judgement: JGOFNumericPlayerColor;
522540

541+
// We need to have a lot of empty intersections compared to the
542+
// stones we're considering in order for this to usually make sense
543+
const required_empty_intersections = 8;
544+
const ratio_threshold = 1.5; // if one color has 1.5 times the stones of the other
545+
546+
if (contained[0] < required_empty_intersections) {
547+
const { x, y } = group.intersections[0];
548+
stage_log(
549+
`${encodePrettyXCoordinate(x)}${height - y} Not enough empty intersections to judge color ${contained}`,
550+
);
551+
return;
552+
}
553+
554+
const pretty_coord =
555+
encodePrettyXCoordinate(group.intersections[0].x) +
556+
(height - group.intersections[0].y);
557+
523558
const total = [
524559
surrounding[0] + contained[0],
525560
surrounding[1] + contained[1],
526561
surrounding[2] + contained[2],
527562
];
528563
if (average_color_estimate > 0.5) {
564+
stage_log(
565+
`${pretty_coord} Average color estimate is black (${average_color_estimate})`,
566+
);
529567
color_judgement = JGOFNumericPlayerColor.BLACK;
530-
} else if (total_ownership_estimate < -0.5) {
568+
} else if (average_color_estimate < -0.5) {
569+
stage_log(
570+
`${pretty_coord} Average color estimate is white (${average_color_estimate})`,
571+
);
531572
color_judgement = JGOFNumericPlayerColor.WHITE;
532573
} else {
533-
if (total[JGOFNumericPlayerColor.BLACK] > total[JGOFNumericPlayerColor.WHITE]) {
574+
if (
575+
total[JGOFNumericPlayerColor.BLACK] >
576+
total[JGOFNumericPlayerColor.WHITE] * ratio_threshold
577+
) {
534578
color_judgement = JGOFNumericPlayerColor.BLACK;
579+
stage_log(
580+
`${pretty_coord} Average color estimate is black (${
581+
total[JGOFNumericPlayerColor.BLACK]
582+
} black stones vs ${total[JGOFNumericPlayerColor.WHITE]})`,
583+
);
535584
} else if (
536-
total[JGOFNumericPlayerColor.WHITE] > total[JGOFNumericPlayerColor.BLACK]
585+
total[JGOFNumericPlayerColor.WHITE] >
586+
total[JGOFNumericPlayerColor.BLACK] * ratio_threshold
537587
) {
588+
stage_log(
589+
`${pretty_coord} Average color estimate is white (${
590+
total[JGOFNumericPlayerColor.WHITE]
591+
} white stones vs ${total[JGOFNumericPlayerColor.BLACK]})`,
592+
);
538593
color_judgement = JGOFNumericPlayerColor.WHITE;
539594
} else {
540595
color_judgement = JGOFNumericPlayerColor.EMPTY;
596+
stage_log(`${pretty_coord} Average color estimate is empty`);
541597
}
542598
}
543599

544-
group.map((point) => {
545-
const x = point.x;
546-
const y = point.y;
547-
if (board[y][x] && board[y][x] !== color_judgement) {
548-
const stone_color =
549-
board[y][x] === JGOFNumericPlayerColor.BLACK ? "black" : "white";
550-
const judgement_color =
551-
color_judgement === JGOFNumericPlayerColor.BLACK ? "black" : "white";
552-
553-
remove(
554-
x,
555-
y,
556-
`clearing unsettled ${stone_color} stones within assumed ${judgement_color} territory `,
557-
);
558-
is_settled[y][x] = 1;
559-
settled[y][x] = color_judgement;
560-
}
561-
});
600+
if (color_judgement !== JGOFNumericPlayerColor.EMPTY) {
601+
group.map((point) => {
602+
const x = point.x;
603+
const y = point.y;
604+
if (board[y][x] && board[y][x] !== color_judgement) {
605+
const stone_color =
606+
board[y][x] === JGOFNumericPlayerColor.BLACK ? "black" : "white";
607+
const judgement_color =
608+
color_judgement === JGOFNumericPlayerColor.BLACK ? "black" : "white";
609+
610+
remove(
611+
x,
612+
y,
613+
`clearing unsettled ${stone_color} stones within assumed ${judgement_color} territory `,
614+
);
615+
is_settled[y][x] = 1;
616+
settled[y][x] = color_judgement;
617+
}
618+
});
619+
}
562620
});
563621

564622
const removal_diff = removal.map((row, y) =>
@@ -774,7 +832,7 @@ export function autoscore(
774832
}
775833
//debug_boolean_board("Sealed", sealed, "s");
776834

777-
const print_final_ownership_string = false;
835+
const print_final_ownership_string = true;
778836
// aid while correcting and forming the test files
779837
if (print_final_ownership_string) {
780838
let ownership_string = '\n "correct_ownership": [\n';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"game_id": 17247,
3+
"board": [
4+
" ",
5+
"bb ",
6+
"Wbbbbb bbb ",
7+
"WWWWWWbbWbWb ",
8+
" WWWWWb ",
9+
"WW Wb ",
10+
"bbW Wb",
11+
"bW WWbbb WWb",
12+
"bWWbbbWW Wbb",
13+
"bbWWb Wb ",
14+
" bW W WWb ",
15+
"bWbbWW Wb b",
16+
" W bbW WWb "
17+
],
18+
"black": [
19+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
20+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
21+
[-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
22+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0],
23+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
24+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
25+
[ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
26+
[ 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
27+
[ 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
28+
[ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
29+
[ 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
30+
[ 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
31+
[-0.1, -1.0, 0.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0]
32+
],
33+
"white": [
34+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
35+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
36+
[-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
37+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0],
38+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
39+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
40+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
41+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
42+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
43+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
44+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
45+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
46+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0]
47+
],
48+
"correct_ownership": [
49+
"BBBBBBBBBBBBB",
50+
"BBBBBBBBBBBBB",
51+
"WBBBBBBBBBBBB",
52+
"WWWWWWBBWBWBB",
53+
"WWWWWWWWWWWBB",
54+
"WWWWWWWWWWWBB",
55+
"BBWWWWWWWWWWB",
56+
"BWWWWWWWWWWWB",
57+
"BWWWWWWWWWWBB",
58+
"BBWWWWWWWWWBB",
59+
" BWWWWWWWBBB",
60+
"BWBBWWWWWWBBB",
61+
" W BBWWWWWWBB"
62+
]
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"game_id": 17247,
3+
"board": [
4+
" ",
5+
"bb ",
6+
"Wbbbbb bbb ",
7+
"WWWWWWbbWbWb ",
8+
" WWWWWb ",
9+
"WW Wb ",
10+
"bbW Wb",
11+
"bW WWbbb WWb",
12+
"bWWbbbWW Wbb",
13+
"bbWWb Wb ",
14+
" bbW W WWb ",
15+
" WbbWW Wb b",
16+
" bbW WWb "
17+
],
18+
"black": [
19+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
20+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
21+
[-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
22+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0],
23+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
24+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
25+
[ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
26+
[ 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
27+
[ 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
28+
[ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
29+
[ 0.5, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
30+
[-0.0, -0.8, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0],
31+
[ 0.2, 0.3, 0.6, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0]
32+
],
33+
"white": [
34+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
35+
[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
36+
[-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
37+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0],
38+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
39+
[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
40+
[ 0.9, 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
41+
[ 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0],
42+
[ 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
43+
[ 0.9, 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0],
44+
[ 0.5, 0.9, 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 0.9, 0.9, 1.0],
45+
[ 0.1, -0.8, 0.9, 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 0.9, 1.0],
46+
[-0.1, -0.2, 0.4, 0.9, 0.9, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0]
47+
],
48+
"correct_ownership": [
49+
"BBBBBBBBBBBBB",
50+
"BBBBBBBBBBBBB",
51+
"WBBBBBBBBBBBB",
52+
"WWWWWWBBWBWBB",
53+
"WWWWWWWWWWWBB",
54+
"WWWWWWWWWWWBB",
55+
"BBWWWWWWWWWWB",
56+
"BWWWWWWWWWWWB",
57+
"BWWWWWWWWWWBB",
58+
"BBWWWWWWWWWBB",
59+
" BBWWWWWWWBBB",
60+
" WBBWWWWWWBBB",
61+
" BBWWWWWWBB"
62+
]
63+
}

0 commit comments

Comments
 (0)