import numpy as npimport os, json
os.makedirs("/work", exist_ok=True)
# All coefficients below are hand-designed, not learned.SOURCE = r'''import numpy as np
P = dict( capture=7.0, rescue=4.5, self_atari=10.0, eye=11.0, crowd=2.5, pass_bias=-2.0, friend_adj=0.15, enemy_adj=0.35, friend_diag=0.35, enemy_diag=0.10, friend_jump=0.65, enemy_jump=0.15, friend_knight=0.25, enemy_knight=0.05, seed_shared_liberty=1.0,)P.update(overrides)
W = [np.zeros((243 if k == 0 else 512, 512), np.float32) for k in range(6)]B = [np.zeros(512, np.float32) for _ in range(6)]OW = np.zeros((512, 82), np.float32)OB = np.zeros(82, np.float32)
def unit(ch, p): return ch * 81 + p
def points(p, offsets): r, c = divmod(p, 9) return [(r+dr)*9+c+dc for dr,dc in offsets if 0 <= r+dr < 9 and 0 <= c+dc < 9]
AD = [(1,0),(-1,0),(0,1),(0,-1)]DI = [(1,1),(1,-1),(-1,1),(-1,-1)]JU = [(2,0),(-2,0),(0,2),(0,-2)]KN = [(a,b) for a,b in [(1,2),(1,-2),(-1,2),(-1,-2),(2,1),(2,-1),(-2,1),(-2,-1)]]adj = [points(p, AD) for p in range(81)]diag = [points(p, DI) for p in range(81)]
def add(k, dest, src, value): W[k][src, dest] += value
def carry(k, ch, p): add(k, unit(ch,p), unit(ch,p), 1)
# First layer:# own, enemy, and two ReLUs per colour encoding 0/1 local liberties.# D-Z is exactly 1 for a stone with at most one local liberty.for p in range(81): add(0, unit(0,p), 3*p, 1) add(0, unit(1,p), 3*p+1, 1) for color, dch, zch in [(0,2,3),(1,4,5)]: for ch, coefficient in [(dch,2),(zch,1)]: dest = unit(ch,p) add(0, dest, 3*p+color, coefficient) B[0][dest] = -len(adj[p]) for q in adj[p]: add(0, dest, 3*q, 1) add(0, dest, 3*q+1, 1)
# Second layer adds conservative group-safety seeds:# a neighbouring stone with >=2 liberties makes the group safe;# adjacent stones each having a liberty provide distinct liberties.for p in range(81): carry(1,0,p) carry(1,1,p) for color, dch, zch in [(0,2,3),(1,4,5)]: for outch, subtract in [(dch,0),(zch,1)]: dest = unit(outch,p) add(1,dest,unit(dch,p),1) B[1][dest] = -subtract for q in adj[p]: # -4 * (stone - D + Z) add(1,dest,unit(color,q),-4) add(1,dest,unit(dch,q),4) add(1,dest,unit(zch,q),-4) # D-2Z is 1 for exactly one local liberty. add(1,dest,unit(dch,q),-P["seed_shared_liberty"]) add(1,dest,unit(zch,q),2*P["seed_shared_liberty"])
# Third layer caps danger at one and propagates group safety.# Channels become own, enemy, own-danger, enemy-danger, eye, bad-diagonal.for p in range(81): carry(2,0,p) carry(2,1,p) for color,dch,zch,outch in [(0,2,3,2),(1,4,5,3)]: dest = unit(outch,p) add(2,dest,unit(dch,p),1) add(2,dest,unit(zch,p),-1) for q in adj[p]: add(2,dest,unit(color,q),-1) add(2,dest,unit(dch,q),1) add(2,dest,unit(zch,q),-1) dest = unit(4,p) B[2][dest] = 1-len(adj[p]) for q in adj[p]: add(2,dest,unit(0,q),1) dest = unit(5,p) # An interior eye tolerates one hostile diagonal; an edge eye none. B[2][dest] = -1 if len(adj[p]) == 4 else 0 for q in diag[p]: add(2,dest,unit(1,q),1)
# Fourth layer: more group-safety propagation and true-eye recognition.for p in range(81): for ch in (0,1): carry(3,ch,p) for color,dch in [(0,2),(1,3)]: dest = unit(dch,p) add(3,dest,unit(dch,p),1) for q in adj[p]: add(3,dest,unit(color,q),-1) add(3,dest,unit(dch,q),1) add(3,unit(4,p),unit(4,p),1) add(3,unit(4,p),unit(5,p),-1) add(3,unit(5,p),unit(4,p),1)
# Fifth layer: final safety propagation, preserving eye features.for p in range(81): for ch in (0,1,4,5): carry(4,ch,p) for color,dch in [(0,2),(1,3)]: dest = unit(dch,p) add(4,dest,unit(dch,p),1) for q in adj[p]: add(4,dest,unit(color,q),-1) add(4,dest,unit(dch,q),1)
# Sixth layer computes action features.for p in range(81): # Capture and rescue urgency. for q in adj[p]: add(5,unit(0,p),unit(3,q),1) add(5,unit(1,p),unit(2,q),1)
# Insufficient escape liberties, waived for captures. dest = unit(2,p) B[5][dest] = 2-len(adj[p]) for q in adj[p]: add(5,dest,unit(0,q),1) add(5,dest,unit(1,q),1) add(5,dest,unit(0,q),-1.5) add(5,dest,unit(2,q),1.5) add(5,dest,unit(3,q),-2)
add(5,unit(3,p),unit(4,p),1)
# Discourage dense, redundant own-stone shapes. dest = unit(4,p) B[5][dest] = -2 for q in adj[p]: add(5,dest,unit(0,q),1) for q in diag[p]: add(5,dest,unit(0,q),0.5)
# A positive offset permits a signed linear positional feature. dest = unit(5,p) B[5][dest] = 20 for offsets, ownkey, enemykey in [ (AD,"friend_adj","enemy_adj"), (DI,"friend_diag","enemy_diag"), (JU,"friend_jump","enemy_jump"), (KN,"friend_knight","enemy_knight"), ]: for q in points(p,offsets): add(5,dest,unit(0,q),P[ownkey]) add(5,dest,unit(1,q),P[enemykey]) add(5,dest,unit(5,p),-1.5)
for ch,coef in enumerate([ P["capture"], P["rescue"], -P["self_atari"], -P["eye"], -P["crowd"], 1.0 ]): OW[unit(ch,p),p] = coef
r,c = divmod(p,9) edge = min(r,c,8-r,8-c) positional = [-0.9,0.1,0.75,0.65,0.65][edge] if (r,c) in [(2,2),(2,6),(6,2),(6,6),(4,4)]: positional += 0.35 OB[p] = -20 + positional
OB[81] = P["pass_bias"]
for k in range(6): save("L%d.W" % (k+1), W[k]) save("L%d.b" % (k+1), B[k])save("out.W", OW)save("out.b", OB)'''open("/work/design.py", "w").write(SOURCE)overrides = {}exec(SOURCE)print("Saved all 14 tensors. Hand-built liberty, capture, rescue, eye, and shape policy.")print("Parameters:", P)print("Saved tensors:", saved())Saved all 14 tensors. Hand-built liberty, capture, rescue, eye, and shape policy.Parameters: {'capture': 7.0, 'rescue': 4.5, 'self_atari': 10.0, 'eye': 11.0, 'crowd': 2.5, 'pass_bias': -2.0, 'friend_adj': 0.15, 'enemy_adj': 0.35, 'friend_diag': 0.35, 'enemy_diag': 0.1, 'friend_jump': 0.65, 'enemy_jump': 0.15, 'friend_knight': 0.25, 'enemy_knight': 0.05, 'seed_shared_liberty': 1.0}Saved tensors: ['L1.W', 'L1.b', 'L2.W', 'L2.b', 'L3.W', 'L3.b', 'L4.W', 'L4.b', 'L5.W', 'L5.b', 'L6.W', 'L6.b', 'out.W', 'out.b']{"games":{"strong":64,"weak":32,"random":32}}{"ok": true, "pass": 1, "kind": "games", "per_opponent": {"random": {"games": 32, "score": 1.0, "wins": 32, "losses": 0, "score_as_black": 1.0, "score_as_white": 1.0, "mean_margin": 57.65625, "mean_length": 104.6875, "stones_captured_per_game": 41.75, "stones_lost_per_game": 0.84375, "passes_per_game": 1.1875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 32, "end_repetition": 0, "end_move_limit": 0}, "strong": {"games": 64, "score": 0.375, "wins": 24, "losses": 40, "score_as_black": 0.3125, "score_as_white": 0.4375, "mean_margin": 6.25, "mean_length": 103.8125, "stones_captured_per_game": 18.640625, "stones_lost_per_game": 20.140625, "passes_per_game": 2.796875, "games_with_a_pass_before_move_60": 2, "end_two_passes": 59, "end_repetition": 5, "end_move_limit": 0}, "weak": {"games": 32, "score": 0.65625, "wins": 21, "losses": 11, "score_as_black": 0.625, "score_as_white": 0.6875, "mean_margin": 31.96875, "mean_length": 109.03125, "stones_captured_per_game": 31.4375, "stones_lost_per_game": 14.34375, "passes_per_game": 2.40625, "games_with_a_pass_before_move_60": 0, "end_two_passes": 31, "end_repetition": 0, "end_move_limit": 1}}, "files": "/work/pass_1/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json, numpy as npg=json.load(open("/work/pass_1/games.json"))print(type(g))if isinstance(g,dict): print(g.keys())else: print("Games",len(g)) print(json.dumps(g[0],indent=1)[:10000])<class 'list'>Games 128{ "game": 0, "opponent": "random", "net_color": "black", "result": 1, "margin": 73.5, "end": "two passes", "stones_captured_by_net": 69, "stones_lost_by_net": 0, "moves": [ { "ply": 0, "by": "net", "move": 67, "top5": [ [ 20, 0.0316 ], [ 24, 0.0316 ], [ 56, 0.0316 ], [ 60, 0.0316 ], [ 40, 0.0286 ] ] }, { "ply": 1, "by": "opponent", "move": 65 }, { "ply": 2, "by": "net", "move": 57, "top5": [ [ 56, 0.0518 ], [ 60, 0.0365 ], [ 49, 0.0347 ], [ 57, 0.0314 ], [ 20, 0.0284 ] ] }, { "ply": 3, "by": "opponent", "move": 3 }, { "ply": 4, "by": "net", "move": 24, "top5": [ [ 56, 0.0538 ], [ 59, 0.0487 ], [ 49, 0.044 ], [ 60, 0.0326 ], [ 39, 0.031 ] ] }, { "ply": 5, "by": "opponent", "move": 59 }, { "ply": 6, "by": "net", "move": 29, "top5": [ [ 56, 0.05 ], [ 49, 0.0453 ], [ 60, 0.0431 ], [ 50, 0.0353 ], [ 22, 0.0335 ] ] }, { "ply": 7, "by": "opponent", "move": 63 }, { "ply": 8, "by": "net", "move": 20, "top5": [ [ 47, 0.047 ], [ 56, 0.047 ], [ 49, 0.0404 ], [ 22, 0.0384 ], [ 60, 0.0384 ] ] }, { "ply": 9, "by": "opponent", "move": 4 }, { "ply": 10, "by": "net", "move": 41, "top5": [ [ 22, 0.0764 ], [ 39, 0.0419 ], [ 47, 0.0419 ], [ 56, 0.0419 ], [ 31, 0.0379 ] ] }, { "ply": 11, "by": "opponent", "move": 72 }, { "ply": 12, "by": "net", "move": 39, "top5": [ [ 22, 0.0841 ], [ 39, 0.0689 ], [ 31, 0.0462 ], [ 49, 0.0439 ], [ 60, 0.0378 ] ] }, { "ply": 13, "by": "opponent", "move": 0 }, { "ply": 14, "by": "net", "move": 50, "top5": [ [ 22, 0.1 ], [ 31, 0.0606 ], [ 49, 0.0577 ], [ 47, 0.0472 ], [ 56, 0.0427 ] ] }, { "ply": 15, "by": "opponent", "move": 17 }, { "ply": 16, "by": "net", "move": 22, "top5": [ [ 22, 0.0985 ], [ 31, 0.0767 ], [ 48, 0.0568 ], [ 60, 0.0489 ], [ 47, 0.0465 ] ] }, { "ply": 17, "by": "opponent", "move": 42 }, { "ply": 18, "by": "net", "move": 31, "top5": [ [ 31, 0.0974 ], [ 32, 0.0621 ], [ 60, 0.0591 ], [ 48, 0.0591 ], [ 47, 0.0484 ] ] }, { "ply": 19, "by": "opponent", "move": 34 }, { "ply": 20, "by": "net", "move": 48, "top5": [ [ 33, 0.1196 ], [ 48, 0.0802 ], [ 60, 0.0625 ], [ 47, 0.0511 ], [ 38, 0.0486 ] ] }, { "ply": 21, "by": "opponent", "move": 44 }, { "ply": 22, "by": "net", "move": 47, "top5": [ [ 33, 0.1443 ], [ 56, 0.0753 ], [ 60, 0.0717 ], [ 47, 0.0682 ], [ 13, 0.0393 ] ] }, { "ply": 23, "by": "opponent", "move": 10 }, { "ply": 24, "by": "net", "move": 79, "top5": [ [ 33, 0.1571 ], [ 60, 0.078 ], [ 37, 0.0473 ], [ 12, 0.045 ], [ 13, 0.0428 ] ] }, { "ply": 25, "by": "opponent", "move": 16 }, { "ply": 26, "by": "net", "move": 60, "top5": [ [ 33, 0.1548 ], [ 60, 0.0939 ], [ 37, 0.0443 ], [ 12, 0.0422 ], [ 13, 0.0401 ] ] }, { "ply": 27, "by": "opponent", "move": 18 }, { "ply": 28, "by": "net", "move": 15, "top5": [ [ 33, 0.1629 ], [ 68, 0.0542 ], [ 37, 0.0491 ], [ 12, 0.0444 ], [ 13, 0.0422 ] ] }, { "ply": 29, "by": "opponent", "move": 13 }, { "ply": 30, "by": "net", "move": 69, "top5": [ [ 33, 0.2731 ], [ 12, 0.0551 ], [ 68, 0.0475 ], [ 37, 0.0429 ], [ 11, 0.0389 ] ] }, { "ply": 31, "by": "opponent", "move": 66 }, { "ply": 32, "by": "net", "move": 56, "top5": [ [ 33, 0.2826 ], [ 12, 0.0571 ], [ 37, 0.0444 ], [ 52, 0.0444 ], [ 11, 0.0402 ] ] }, { "ply": 33, "by": "opponent", "move": 28 }, { "ply": 34, "by": "net", "move": 55, "top5": [ [ 33, 0.2709 ], [ 37, 0.0776 ], [ 12, 0.0547 ], [ 46, 0.0547 ], [ 58, 0.0448 ] ] }, { "ply": 35, "by": "opponent", "move": 71 }, { "ply": 36, "by": "net", "move": 12, "top5": [ [ 33, 0.265 ], [ 37, 0.1454 ], [ 12, 0.0535 ], [ 52, 0.0438 ], [ 64, 0.0438 ] ] }, { "ply": 37, "by": "opponent", "move": 36 }, { "ply": 38, "by": "net", "move": 37, "top5": [ [ 33, 0.2518 ], [ 37, 0.1961 ], [ 14, 0.0653 ], [ 11, 0.0438 ], [ 52, 0.0416 ] ] }, { "ply": 39, "by": "opponent", "move": 40 }, { "ply": 40, "by": "net", "move": 49, "top5": [ [ 49, 0.9625 ], [ 33, 0.0124 ], [ 14, 0.0031 ], [ 58, 0.0023 ], [ 11, 0.0021 ] ] }, { "ply": 41, "by": "opponent", "move": 73 }, { "ply": 42, "by": "net", "move": 33, "top5": [ [ 33, 0.3596 ], [ 14, 0.0932 ], [ 11, 0.0625 ], [ 52, 0.0594 ], [ 51, 0.0565 ] ] }, { "ply": 43, "by": "opponent", "move": 9 }, { "ply": 44, "by": "net", "move": 6, "top5": [ [ 14, 0.1613 ], [ 51, 0.1459 ], [ 52, 0.1028 ], [ 11, 0.0978 ], [ 25, 0.0656 ] ] }, { "ply": 45, "by": "opponent", "move": 23 }, { "ply": 46, "by": "net", "move": 11, "top5": [ [ 51, 0.1527 ], [ 52, 0.1076 ], [ 11, 0.1023 ], [ 25, 0.1023 ], [ 14, 0.0973 ] ] }, { "ply": 47, "by": "opponent", "move": 62 }, { "ply": 48, "by": "net", "move": 14, "top5": [ [ 51, 0.1746 ], [ 52, 0.1294 ], [ 25, 0.1113 ], [ 14, 0.1059 ], [ 61, 0.1059 ] ] }, { "ply": 49, "by": "opponent", "move": 80 }, { "ply": 50, "by": "net", "move": 32, "top5": [ [ 32, 0.8954 ], [ 51, 0.02 ], [ 25, 0.0164 ], [ 52, 0.0148 ], [ 61, 0.0128 ] ] }, { "ply": 51, "by": "opponent", "move": 52 }, { "ply": 52, "by": "net", "move": 25, "top5": [ [ 51, 0.32 ], [ 25, 0.1589 ], [ 61, 0.1589 ], [ 68, 0.0479 ], [ 45, 0.0412 ] ] }, { "ply": 53, "by": "opponent", "move": 45 }, { "ply": 54, "by": "net", "move": 77, "top5": [ [ 51, 0.4059 ], [ 61, 0.2016 ], [ 68, 0.0607 ], [ 7, 0.0497 ], [ 2, 0.045 ] ] }, { "ply": 55, "by": "opponent", "move": 26 }, { "ply": 56, "by": "net", "move": 2, "top5": [ [ 51, 0.458 ], [ 61, 0.2275 ], [ 75, 0.0837 ], [ 7, 0.059 ], [ 2, 0.0508 ] ] }, { "ply": 57, "by": "opponent", "move": 7 }, { "ply": 58, "by": "net", "move": 5, "top5": [ [ 5, 0.9569 ], [ 51, 0.0225 ], [ 61, 0.0112 ], [ 75, 0.0041 ], [ 70, 0.0014 ] ] }, { "ply": 59, "by": "opponent", "move": 1 }, { "ply": 60, "by": "net", "move": 4, "top5": [ [ 51, 0.4149 ], [ 61, 0.206 ], [ 4, 0.1687 ], [ 75, 0.0758 ], [ 70, 0.0252 ] ] }, { "ply": 61, "by": "opponent", "move": 8 }, { "ply": 62, "by": "net", "move": 35, "top5": [ [ 35, 0.9914 ], [ 51, 0.0045 ], [ 61, 0.0022 ], [ 75, 0.0008 ], [ 70, 0.0003 ] ] }, { "ply": 63, "by": "opponent", "move": 19 }, { "ply": 64, "by": "net", "move": 43, "top5": [ [ 43, 0.9975 ], [ 26, 0.0019 ], [ 51, 0.0003 ], [ 61, 0.0001 ], [ 75, 0.0 ] ] }, { "ply": 65, "by": "opponent", "move": 53 }, import json, numpy as npgames=json.load(open("/work/pass_1/games.json"))boards=np.load("/work/pass_1/boards.npy")AD=[[(r+dr)*9+c+dc for dr,dc in [(1,0),(-1,0),(0,1),(0,-1)] if 0<=r+dr<9 and 0<=c+dc<9] for r in range(9) for c in range(9)]def groups(b): seen=set(); out=[] for p in range(81): if not b[p] or p in seen: continue col=int(b[p]); stack=[p]; stones=set([p]); libs=set(); seen.add(p) while stack: u=stack.pop() for v in AD[u]: if b[v]==0: libs.add(v) elif b[v]==col and v not in seen: seen.add(v); stones.add(v); stack.append(v) out.append((col,stones,libs)) return outdef show(b): return "\n".join("".join(".XO"[{0:0,1:1,-1:2}[int(v)]] for v in b[r*9:(r+1)*9]) for r in range(9))open("/work/analysis_helpers.py","w").write('import numpy as np\nAD='+repr(AD)+'\n'+ '''def groups(b): seen=set(); out=[] for p in range(81): if not b[p] or p in seen: continue col=int(b[p]); stack=[p]; stones={p}; libs=set(); seen.add(p) while stack: u=stack.pop() for v in AD[u]: if b[v]==0: libs.add(v) elif b[v]==col and v not in seen: seen.add(v); stones.add(v); stack.append(v) out.append((col,stones,libs)) return outdef show(b): return "\\n".join("".join({0:".",1:"X",-1:"O"}[int(v)] for v in b[r*9:(r+1)*9]) for r in range(9))''')losses=[(i,g) for i,g in enumerate(games) if g["opponent"]=="strong" and g["result"]<0]for i,g in losses[:5]: print("\nGAME",i,"net",g["net_color"],"margin",g["margin"],"end",g["end"]) col=1 if g["net_color"]=="black" else -1 events=[] for t,m in enumerate(g["moves"]): if t==0 or m["by"]!="opponent": continue lost=int(np.sum(boards[i,t-1]==col)-np.sum(boards[i,t]==col)) if lost>=4: events.append((lost,t)) for lost,t in sorted(events,reverse=True)[:2]: print("LOST",lost,"at",t,"opponent move",g["moves"][t]["move"]) s=max(0,t-3) print("Board before own move",s+1,"\n"+show(boards[i,s])) print("Sequence",g["moves"][s+1:t+1]) print("Own groups then",[(len(st),sorted(li)) for c,st,li in groups(boards[i,s]) if c==col])
GAME 32 net black margin -8.5 end two passesLOST 4 at 67 opponent move 73Board before own move 65 ......O...X.X.XXXXX.X.X.XOX.X.XOXXOXX.XXOOXOOOXOOOOOOOOOOO.OXXOOXXOXO.OXX..O.O.X.Sequence [{'ply': 65, 'by': 'opponent', 'move': 80}, {'ply': 66, 'by': 'net', 'move': 74, 'top5': [[73, 0.5986], [74, 0.06], [7, 0.0571], [5, 0.0445], [4, 0.0402]]}, {'ply': 67, 'by': 'opponent', 'move': 73}]Own groups then [(1, [1, 9, 11, 19]), (1, [3, 11, 13, 21]), (10, [5, 7, 8, 13, 23]), (1, [9, 19, 27]), (1, [11, 19, 21, 29]), (1, [13, 21, 23]), (1, [19, 27, 29, 37]), (3, [21, 29, 37]), (1, [27, 37]), (1, [37]), (2, [69]), (2, [73, 74]), (1, [58, 76]), (1, [80]), (1, [73]), (1, [78, 80])]
GAME 33 net black margin -24.5 end two passesLOST 14 at 71 opponent move 3Board before own move 69 X.O.XXXO...XOXOXOOX.X.XOXOOXX.OXOXOOX.XXOOXOOXXOXOXXXO.XOXOXOOOXXOOOO.OO.XO..O...Sequence [{'ply': 69, 'by': 'opponent', 'move': 21}, {'ply': 70, 'by': 'net', 'move': 78, 'top5': [[29, 0.3312], [9, 0.2112], [10, 0.2112], [1, 0.0997], [78, 0.0739]]}, {'ply': 71, 'by': 'opponent', 'move': 3}]Own groups then [(1, [1, 9]), (14, [3, 21]), (2, [10, 19, 21, 29]), (10, [9, 19, 29, 37, 54, 72]), (4, [29, 37])]LOST 4 at 59 opponent move 77Board before own move 57 X.O.XXXO...XOXOXO.X.X.XOXOO.X..XOXOO..XXOOXOO.X.XOXXXO..OXOXOOOXX.OOOXOO..O...XX.Sequence [{'ply': 57, 'by': 'opponent', 'move': 65}, {'ply': 58, 'by': 'net', 'move': 80, 'top5': [[80, 0.9866], [77, 0.0019], [76, 0.0016], [55, 0.0013], [36, 0.0012]]}, {'ply': 59, 'by': 'opponent', 'move': 77}]Own groups then [(1, [1, 9]), (14, [3, 21, 30]), (2, [10, 19, 21, 29]), (1, [9, 19, 27]), (1, [19, 27, 29, 37]), (4, [29, 30, 37, 47]), (1, [37, 45, 47, 55]), (2, [54, 55, 65, 72, 73]), (3, [77, 80])]
GAME 34 net black margin -17.5 end two passesLOST 7 at 61 opponent move 7Board before own move 59 X.X.XOX.....OXOXOOX.XXOOXOOX.X.XOXXX.XXXOOOXO...XOOOO...XXXXX.O.OOOOOOX....O.O.X.Sequence [{'ply': 59, 'by': 'opponent', 'move': 53}, {'ply': 60, 'by': 'net', 'move': 46, 'top5': [[61, 0.3527], [46, 0.1666], [55, 0.1298], [10, 0.1117], [11, 0.0712]]}, {'ply': 61, 'by': 'opponent', 'move': 7}]Own groups then [(1, [1, 9]), (1, [1, 3, 11]), (2, [3]), (7, [7]), (2, [9, 19, 28, 36]), (12, [11, 19, 28, 30, 36, 46, 47, 55, 61]), (1, [30]), (2, [61, 71, 78, 80])]
GAME 35 net black margin -26.5 end two passesLOST 8 at 93 opponent move 36Board before own move 91 .O.OOOOO.OOOOOOO.O.OXOXXXOXXOXOX.XXX.XXOOXX.XXOXOOOXX..OXXOXX.XOOOOOOXXX.XXO.OOO.Sequence [{'ply': 91, 'by': 'opponent', 'move': 54}, {'ply': 92, 'by': 'net', 'move': 16, 'top5': [[16, 0.9999], [36, 0.0001], [81, 0.0], [18, 0.0], [80, 0.0]]}, {'ply': 93, 'by': 'opponent', 'move': 36}]Own groups then [(7, [36]), (19, [32, 43, 53, 61, 80]), (1, [18, 36]), (1, [36, 54]), (2, [72])]LOST 7 at 73 opponent move 36Board before own move 71 .O.O.OOO.OOO.OOOX..OXOXXX.XXOXOX.XX..XXOOXX.XXOXOOOXX..OXXOXX.XO.OOOOXXX..XOXX.O.Sequence [{'ply': 71, 'by': 'opponent', 'move': 78}, {'ply': 72, 'by': 'net', 'move': 73, 'top5': [[73, 0.9412], [36, 0.0446], [17, 0.0121], [81, 0.0013], [18, 0.0003]]}, {'ply': 73, 'by': 'opponent', 'move': 36}]Own groups then [(1, [17, 25]), (7, [36]), (16, [25, 32, 35, 43, 53, 61, 78, 80]), (1, [17, 25, 35]), (1, [18, 36]), (1, [35, 43, 53]), (1, [36, 54]), (1, [73]), (2, [78])]
GAME 36 net black margin -19.5 end two passesLOST 7 at 57 opponent move 3Board before own move 55 .OX.XO...X.XXXOO...OOOXOOX..XXOXOX.X..OOOXXX.XXO.X.XX..O.OOXX..X..XOX.O..........Sequence [{'ply': 55, 'by': 'opponent', 'move': 10}, {'ply': 56, 'by': 'net', 'move': 65, 'top5': [[64, 0.1578], [27, 0.091], [65, 0.091], [61, 0.0866], [16, 0.0709]]}, {'ply': 57, 'by': 'opponent', 'move': 3}]Own groups then [(7, [3, 10]), (1, [0, 10, 18]), (1, [16, 26, 34]), (2, [27, 37]), (9, [34, 44, 50, 53, 61, 69, 77]), (1, [26, 34, 44]), (2, [36, 37, 54]), (1, [48, 50]), (1, [54, 64, 72]), (1, [65, 75])]LOST 4 at 91 opponent move 2Board before own move 89 .O.O.O.X.XOXXXOOOOOOOOXOO.O.X.OOOXO.OOOOOXXXO..OXXXXXOOOOOOXXX.XXXXOXOO.X.X.XXO.XSequence [{'ply': 89, 'by': 'opponent', 'move': 4}, {'ply': 90, 'by': 'net', 'move': 71, 'top5': [[71, 0.4575], [75, 0.3938], [29, 0.0971], [81, 0.0278], [79, 0.0088]]}, {'ply': 91, 'by': 'opponent', 'move': 2}]Own groups then [(1, [6, 8]), (1, [0]), (4, [2, 4]), (1, [27, 29]), (15, [62, 75]), (6, [73, 75]), (1, [71, 79])]import shutilshutil.copyfile("/work/design.py","/work/design_v1.py")s=open("/work/design.py").read()start=s.index("# Second layer")end=s.index(" dest = unit(4,p)",start)s=s[:start]+r'''# Conservative safety seeds: never mark a genuinely atari group safe.# Channels 2/4 are binary danger; 3/5 detect adjacent liberty-bearing# stones, whose liberties must be distinct on the square grid.for p in range(81): carry(1,0,p) carry(1,1,p) for color,dch,zch in [(0,2,3),(1,4,5)]: dest=unit(dch,p) add(1,dest,unit(dch,p),1) add(1,dest,unit(zch,p),-1) for q in adj[p]: add(1,dest,unit(color,q),-1) add(1,dest,unit(dch,q),1) add(1,dest,unit(zch,q),-1) dest=unit(zch,p) B[1][dest]=-4 add(1,dest,unit(dch,p),4) add(1,dest,unit(zch,p),-8) for q in adj[p]: add(1,dest,unit(dch,q),1) add(1,dest,unit(zch,q),-2)
# Safety propagates through each connected string.for p in range(81): carry(2,0,p) carry(2,1,p) for color,dch,zch,outch in [(0,2,3,2),(1,4,5,3)]: dest=unit(outch,p) add(2,dest,unit(dch,p),1) add(2,dest,unit(zch,p),-1) for q in adj[p]: add(2,dest,unit(color,q),-1) add(2,dest,unit(dch,q),1) add(2,dest,unit(zch,q),-1)''' + s[end:]open("/work/design.py","w").write(s)overrides={}exec(s)print("Corrected conservative group-safety logic; other coefficients unchanged.")Corrected conservative group-safety logic; other coefficients unchanged.{"games":{"strong":80,"weak":48}}{"ok": true, "pass": 2, "kind": "games", "per_opponent": {"strong": {"games": 80, "score": 0.5249999761581421, "wins": 42, "losses": 38, "score_as_black": 0.42500001192092896, "score_as_white": 0.625, "mean_margin": 28.325000762939453, "mean_length": 111.85, "stones_captured_per_game": 47.5625, "stones_lost_per_game": 17.75, "passes_per_game": 2.475, "games_with_a_pass_before_move_60": 2, "end_two_passes": 68, "end_repetition": 8, "end_move_limit": 4}, "weak": {"games": 48, "score": 0.8125, "wins": 39, "losses": 9, "score_as_black": 0.75, "score_as_white": 0.875, "mean_margin": 65.5625, "mean_length": 118.54166666666667, "stones_captured_per_game": 70.29166666666667, "stones_lost_per_game": 4.895833333333333, "passes_per_game": 1.8958333333333333, "games_with_a_pass_before_move_60": 2, "end_two_passes": 43, "end_repetition": 5, "end_move_limit": 0}}, "files": "/work/pass_2/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}exec(open("/work/analysis_helpers.py").read())games=json.load(open("/work/pass_2/games.json"))boards=np.load("/work/pass_2/boards.npy")stats={}examples=[]for i,g in enumerate(games): col=1 if g["net_color"]=="black" else -1 for t,m in enumerate(g["moves"]): if m["by"]!="net": continue b=np.zeros(81,dtype=int) if t==0 else boards[i,t-1] gs=groups(b) endangered=[(len(st),next(iter(li))) for c,st,li in gs if c==col and len(li)==1] caps=[(len(st),next(iter(li))) for c,st,li in gs if c==-col and len(li)==1] if endangered and g["opponent"]=="strong": moved=m["move"]; biggest=max(endangered) if biggest[0]>=4 and moved!=biggest[1]: after=groups(boards[i,t]) still=[(len(st),list(li)) for c,st,li in after if c==col and len(li)==1 and biggest[1] in li] if still: examples.append((biggest[0],i,t,biggest,m["move"],m["top5"]))print("Missed large ataris",len(examples))for size,i,t,big,move,top in sorted(examples,reverse=True)[:10]: g=games[i] print("\nGame",i,g["net_color"],g["result"],"ply",t,"atari",big,"move",move,"top",top) print(show(boards[i,t-1])) print("groups",[(c,len(st),sorted(li)) for c,st,li in groups(boards[i,t-1]) if len(li)<=2])print("\nLoss endings:")from collections import Counterprint(Counter((g["opponent"],g["end"]) for g in games if g["result"]<0))Missed large ataris 274
Game 58 white -1 ply 79 atari (15, 77) move 78 top [[78, 0.6875], [80, 0.3089], [14, 0.0019], [36, 0.0017], [81, 0.0]].OXXX.X.XOXXX..XX.OOOXXXOX.OXXXXXOXX.OOXXOOOOO.OXXOOOO.OOXOOOXOOXXXXOXXX.X.XX..O.groups [(-1, 1, [0]), (1, 1, [7, 17]), (-1, 5, [0, 36]), (-1, 15, [77]), (1, 4, [78, 80]), (-1, 1, [54, 72]), (-1, 1, [78, 80])]
Game 44 white -1 ply 77 atari (13, 78) move 6 top [[6, 0.9893], [45, 0.0023], [36, 0.0022], [79, 0.0021], [54, 0.001]].OO.OO.XOOOOOXOOOOO.OOXXOXOOOXOXXXXX.XXXXOOXO.XXXOOOOO.OOXXXOXX..XXXOOX..O.XOO...groups [(-1, 9, [3, 6]), (1, 1, [6]), (-1, 13, [78]), (-1, 2, [54, 64]), (1, 3, [71, 79])]
Game 44 white -1 ply 75 atari (13, 78) move 8 top [[8, 0.9999], [3, 0.0], [45, 0.0], [36, 0.0], [79, 0.0]].OO.OOXX.OOOOXOOOOO.OOXXOXOOOXOXXXXX.XXXXOOXO.XXXOOOOO.OOXXXOXX..XXXOOX..O.XOO...groups [(-1, 8, [3, 8]), (1, 2, [8]), (-1, 13, [78]), (-1, 2, [54, 64]), (1, 3, [71, 79])]
Game 44 white -1 ply 73 atari (13, 78) move 2 top [[2, 0.9825], [45, 0.0038], [36, 0.0036], [79, 0.0035], [54, 0.0016]].O.XOO.X.OOOOXOOOOO.OOXXOXOOOXOXXXXX.XXXXOOXO.XXXOOOOO.OOXXXOXX..XXXOOX..O.XOO...groups [(1, 1, [2]), (-1, 8, [6, 8]), (1, 1, [6, 8]), (-1, 13, [78]), (-1, 2, [54, 64]), (1, 3, [71, 79])]
Game 44 white -1 ply 71 atari (13, 78) move 5 top [[5, 0.9999], [2, 0.0001], [45, 0.0], [36, 0.0], [79, 0.0]].O.XO.XXXOOOOXOOOOO.OOXXOXOOOXOXXXXX.XXXXOOXO.XXXOOOOO.OOXXXOXX..XXXOOX..O.XOO...groups [(1, 1, [2]), (-1, 1, [5]), (1, 3, [5]), (-1, 6, [5]), (-1, 13, [78]), (-1, 2, [54, 64]), (1, 3, [71, 79])]
Game 37 black -1 ply 96 atari (11, 0) move 68 top [[68, 0.7588], [81, 0.2403], [64, 0.0008], [73, 0.0001], [53, 0.0]].XXXXOOO.OXXXO.OOOOOXOOOOXXOOXOOOOX.OOXOOXX.XXOXOXXXX..OOOOXX.XO.OOX.XX.O.OOOXX.Xgroups [(1, 11, [0]), (1, 3, [35, 43]), (1, 1, [54]), (1, 1, [68]), (1, 1, [71, 79])]
Game 37 black -1 ply 94 atari (11, 0) move 50 top [[50, 0.5512], [68, 0.2477], [81, 0.1502], [36, 0.0352], [54, 0.0151]].XXXXOOO.OXXXO.OOOOOXOOOOXXOOXOOOOX..OXOOXX.XXOXOX.XX..OOOOXX.XO.OOX.XX.O.OOOXX.Xgroups [(1, 11, [0]), (1, 3, [35, 43]), (1, 1, [36, 54]), (1, 1, [50]), (1, 1, [68]), (1, 1, [71, 79])]
Game 37 black -1 ply 92 atari (11, 0) move 45 top [[64, 0.5271], [45, 0.2038], [54, 0.1119], [63, 0.0788], [50, 0.0455]].XXXXOOO.OXXXO.OOOOOXOOOOXXOOXOOOOX..OXOOXX.X.OXOX.XX..OOOOXX.X..OOX.XX.O.OOOXX.Xgroups [(1, 11, [0]), (1, 3, [35, 43]), (1, 1, [50]), (1, 1, [68]), (-1, 1, [63, 73]), (1, 1, [71, 79])]
Game 37 black -1 ply 90 atari (11, 0) move 49 top [[49, 1.0], [64, 0.0], [45, 0.0], [54, 0.0], [73, 0.0]].XXXXOOO.OXXXO.OOOOOXOOOOXXOOXOOOOX..OXOOXX.X.OXO.OXX..OOOOXX.X..OOX.XX.O..OOXX.Xgroups [(1, 11, [0]), (1, 3, [35, 43]), (-1, 1, [49]), (1, 1, [68]), (-1, 1, [63, 73]), (1, 1, [71, 79])]
Game 37 black -1 ply 88 atari (11, 0) move 26 top [[26, 0.7542], [35, 0.1523], [68, 0.056], [81, 0.0375], [53, 0.0]].XXXXOOO.OXXXO.OOOOOXOOOOX.OOXOOOOX.XOXOOXX.XXOXO.OXX.XOOOOXX.XXXOOX.XX..XXOOXX.Xgroups [(1, 11, [0]), (1, 7, [72]), (-1, 1, [49]), (1, 1, [68]), (1, 1, [71, 79])]
Loss endings:Counter({('strong', 'two passes'): 33, ('weak', 'two passes'): 6, ('strong', 'repetition'): 5, ('weak', 'repetition'): 3})import shutilshutil.copyfile("/work/design.py","/work/design_v2.py")s=open("/work/design.py").read()s=s.replace('seed_shared_liberty=1.0,','seed_shared_liberty=1.0, positional_scale=2.0, low_liberty=1.5,')s=s.replace(' add(3,unit(5,p),unit(4,p),1)',r''' # Prefer moves with room to grow, not just moves that evade atari. dest=unit(5,p) B[3][dest]=3-len(adj[p]) for q in adj[p]: add(3,dest,unit(0,q),-1) add(3,dest,unit(1,q),1) add(3,dest,unit(2,q),2) add(3,dest,unit(3,q),-3)''')s=s.replace('add(5,dest,unit(5,p),-1.5)','add(5,dest,unit(5,p),-P["low_liberty"])')s=s.replace('OB[p] = -20 + positional','OB[p] = -20 + P["positional_scale"]*positional')open("/work/design.py","w").write(s)overrides=dict(friend_adj=1.4,enemy_adj=0.5,friend_diag=0.6, friend_jump=0.25,friend_knight=0.1, crowd=2.0,rescue=6.0,self_atari=9.0)open("/work/params_v3.json","w").write(json.dumps(overrides))exec(s)print(P){'capture': 7.0, 'rescue': 6.0, 'self_atari': 9.0, 'eye': 11.0, 'crowd': 2.0, 'pass_bias': -2.0, 'friend_adj': 1.4, 'enemy_adj': 0.5, 'friend_diag': 0.6, 'enemy_diag': 0.1, 'friend_jump': 0.25, 'enemy_jump': 0.15, 'friend_knight': 0.1, 'enemy_knight': 0.05, 'seed_shared_liberty': 1.0, 'positional_scale': 2.0, 'low_liberty': 1.5}{"games":{"strong":80,"weak":48}}{"ok": true, "pass": 3, "kind": "games", "per_opponent": {"strong": {"games": 80, "score": 0.48750001192092896, "wins": 39, "losses": 41, "score_as_black": 0.4749999940395355, "score_as_white": 0.5, "mean_margin": 25.037500381469727, "mean_length": 111.5, "stones_captured_per_game": 49.85, "stones_lost_per_game": 15.5875, "passes_per_game": 2.8375, "games_with_a_pass_before_move_60": 4, "end_two_passes": 78, "end_repetition": 2, "end_move_limit": 0}, "weak": {"games": 48, "score": 0.8541666865348816, "wins": 41, "losses": 7, "score_as_black": 0.7083333134651184, "score_as_white": 1.0, "mean_margin": 63.89583206176758, "mean_length": 123.22916666666667, "stones_captured_per_game": 83.54166666666667, "stones_lost_per_game": 4.416666666666667, "passes_per_game": 2.7083333333333335, "games_with_a_pass_before_move_60": 1, "end_two_passes": 46, "end_repetition": 1, "end_move_limit": 1}}, "files": "/work/pass_3/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutil, jsonshutil.copyfile("/work/design.py","/work/design_v3.py")s=open("/work/design.py").read()s=s.replace('low_liberty=1.5,','low_liberty=1.5, weak_friend=1.0, weak_enemy=2.0,')a=s.index(' dest = unit(4,p)',s.index('# Safety propagates'))b=s.index('# Fourth layer',a)s=s[:a]+r''' # Local liberty pressure, reduced for already connected stones. for color,ch in [(0,4),(1,5)]: dest=unit(ch,p) add(2,dest,unit(color,p),3) B[2][dest]=-len(adj[p]) for q in adj[p]: add(2,dest,unit(0,q),1) add(2,dest,unit(1,q),1) add(2,dest,unit(color,q),-0.5)
''' + s[b:]a=s.index(' add(3,unit(4,p),unit(4,p),1)')b=s.index(' # Prefer moves with room',a)s=s[:a]+r''' # Urgency to support pressured stones and reduce enemy liberties. for q in adj[p]: add(3,unit(4,p),unit(4,q),P["weak_friend"]) add(3,unit(4,p),unit(5,q),P["weak_enemy"])''' + s[b:]s=s.replace(' add(5,unit(3,p),unit(4,p),1)',r''' dest=unit(3,p) B[5][dest]=1-len(adj[p]) for q in adj[p]: add(5,dest,unit(0,q),1) for q in diag[p]: add(5,dest,unit(1,q),-0.5 if len(adj[p])==4 else -1)''')s=s.replace('add(5,dest,unit(5,p),-P["low_liberty"])','''add(5,dest,unit(5,p),-P["low_liberty"]) add(5,dest,unit(4,p),1)''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v3.json"))exec(s)print("Added proactive local-liberty pressure and support.")print(P)Added proactive local-liberty pressure and support.{'capture': 7.0, 'rescue': 6.0, 'self_atari': 9.0, 'eye': 11.0, 'crowd': 2.0, 'pass_bias': -2.0, 'friend_adj': 1.4, 'enemy_adj': 0.5, 'friend_diag': 0.6, 'enemy_diag': 0.1, 'friend_jump': 0.25, 'enemy_jump': 0.15, 'friend_knight': 0.1, 'enemy_knight': 0.05, 'seed_shared_liberty': 1.0, 'positional_scale': 2.0, 'low_liberty': 1.5, 'weak_friend': 1.0, 'weak_enemy': 2.0}{"games":{"strong":80,"weak":48}}{"ok": true, "pass": 4, "kind": "games", "per_opponent": {"strong": {"games": 80, "score": 0.550000011920929, "wins": 44, "losses": 36, "score_as_black": 0.4749999940395355, "score_as_white": 0.625, "mean_margin": 35.45000076293945, "mean_length": 115.8375, "stones_captured_per_game": 54.8, "stones_lost_per_game": 15.65, "passes_per_game": 1.9125, "games_with_a_pass_before_move_60": 1, "end_two_passes": 79, "end_repetition": 1, "end_move_limit": 0}, "weak": {"games": 48, "score": 0.8541666865348816, "wins": 41, "losses": 7, "score_as_black": 0.7083333134651184, "score_as_white": 1.0, "mean_margin": 59.625, "mean_length": 121.33333333333333, "stones_captured_per_game": 76.25, "stones_lost_per_game": 5.208333333333333, "passes_per_game": 2.9791666666666665, "games_with_a_pass_before_move_60": 1, "end_two_passes": 47, "end_repetition": 1, "end_move_limit": 0}}, "files": "/work/pass_4/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutilshutil.copyfile("/work/design.py","/work/design_v4.py")s=open("/work/design.py").read()s=s.replace('weak_friend=1.0, weak_enemy=2.0,','weak_friend=1.0, weak_enemy=2.0, decisiveness=1.6,')s=s.replace('for k in range(6):\n save(', 'OW *= P["decisiveness"]\nOB *= P["decisiveness"]\n\nfor k in range(6):\n save(')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v3.json"))exec(s)print("Increased policy decisiveness, with unchanged move ranking.")Increased policy decisiveness, with unchanged move ranking.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 5, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5833333134651184, "wins": 56, "losses": 40, "score_as_black": 0.4375, "score_as_white": 0.7291666865348816, "mean_margin": 39.34375, "mean_length": 115.57291666666667, "stones_captured_per_game": 61.333333333333336, "stones_lost_per_game": 15.479166666666666, "passes_per_game": 1.6979166666666667, "games_with_a_pass_before_move_60": 0, "end_two_passes": 89, "end_repetition": 4, "end_move_limit": 3}, "weak": {"games": 32, "score": 0.9375, "wins": 30, "losses": 2, "score_as_black": 0.875, "score_as_white": 1.0, "mean_margin": 69.71875, "mean_length": 123.1875, "stones_captured_per_game": 87.6875, "stones_lost_per_game": 3.125, "passes_per_game": 2.375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 32, "end_repetition": 0, "end_move_limit": 0}}, "files": "/work/pass_5/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}exec(open("/work/analysis_helpers.py").read())games=json.load(open("/work/pass_5/games.json"))boards=np.load("/work/pass_5/boards.npy")for color in ["black","white"]: gg=[g for g in games if g["opponent"]=="strong" and g["net_color"]==color] print(color, "margins", sorted(g["margin"] for g in gg))for i,g in [(i,g) for i,g in enumerate(games) if g["opponent"]=="strong" and g["net_color"]=="black" and g["result"]<0][:5]: print("\nGAME",i,"margin",g["margin"],"end",g["end"],"captures",g["stones_captured_by_net"],"lost",g["stones_lost_by_net"]) print(show(boards[i,len(g["moves"])-1])) print("Opening",[(m["by"],m["move"]) for m in g["moves"][:24]]) print("Last",g["moves"][-6:])black margins [-61.5, -34.5, -29.5, -29.5, -23.5, -18.5, -17.5, -17.5, -15.5, -13.5, -12.5, -11.5, -11.5, -10.5, -9.5, -9.5, -8.5, -7.5, -6.5, -6.5, -5.5, -4.5, -3.5, -1.5, -0.5, 2.5, 10.5, 30.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5, 73.5]white margins [-16.5, -15.5, -13.5, -9.5, -9.5, -8.5, -8.5, -7.5, -5.5, -5.5, -5.5, -1.5, -0.5, 2.5, 5.5, 7.5, 9.5, 64.5, 85.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5, 88.5]
GAME 0 margin -34.5 end two passes captures 1 lost 28OOOOOO.O..XOOOOOOOOOOOOOXXOOOOOOXXOOOOXXOXXXOOO.OOXXXOOOOOXXXXXOOOOOXXX.OOOOOX.XXOpening [('net', 60), ('opponent', 40), ('net', 59), ('opponent', 48), ('net', 58), ('opponent', 49), ('net', 50), ('opponent', 31), ('net', 70), ('opponent', 57), ('net', 41), ('opponent', 23), ('net', 51), ('opponent', 66), ('net', 32), ('opponent', 22), ('net', 24), ('opponent', 15), ('net', 33), ('opponent', 16), ('net', 42), ('opponent', 14), ('net', 25), ('opponent', 67)]Last [{'ply': 101, 'by': 'opponent', 'move': 56}, {'ply': 102, 'by': 'net', 'move': 38, 'top5': [[38, 1.0], [81, 0.0], [39, 0.0], [47, 0.0], [71, 0.0]]}, {'ply': 103, 'by': 'opponent', 'move': 12}, {'ply': 104, 'by': 'net', 'move': 39, 'top5': [[39, 0.832], [47, 0.168], [81, 0.0], [71, 0.0], [78, 0.0]]}, {'ply': 105, 'by': 'opponent', 'move': 81}, {'ply': 106, 'by': 'net', 'move': 81, 'top5': [[81, 0.9996], [71, 0.0002], [78, 0.0002], [0, 0.0], [1, 0.0]]}]
GAME 1 margin -29.5 end two passes captures 2 lost 40XOOOOOOOOXOOO.OOOOXXOOOOOOOXXXOOOOOOXXXXO.OOOXXXXOXOOOXXXOOXXOO.XXXOOOOOX.XXOOOO.Opening [('net', 56), ('opponent', 40), ('net', 60), ('opponent', 58), ('net', 39), ('opponent', 49), ('net', 48), ('opponent', 31), ('net', 41), ('opponent', 32), ('net', 50), ('opponent', 30), ('net', 59), ('opponent', 57), ('net', 66), ('opponent', 21), ('net', 42), ('opponent', 24), ('net', 47), ('opponent', 67), ('net', 38), ('opponent', 68), ('net', 29), ('opponent', 20)]Last [{'ply': 107, 'by': 'opponent', 'move': 14}, {'ply': 108, 'by': 'net', 'move': 81, 'top5': [[81, 0.8807], [36, 0.1192], [63, 0.0], [73, 0.0], [0, 0.0]]}, {'ply': 109, 'by': 'opponent', 'move': 7}, {'ply': 110, 'by': 'net', 'move': 36, 'top5': [[81, 0.8807], [36, 0.1192], [63, 0.0], [73, 0.0], [0, 0.0]]}, {'ply': 111, 'by': 'opponent', 'move': 81}, {'ply': 112, 'by': 'net', 'move': 81, 'top5': [[81, 0.9999], [63, 0.0], [73, 0.0], [0, 0.0], [1, 0.0]]}]
GAME 4 margin -7.5 end two passes captures 16 lost 20XXX.XXOO..XXXXOOOOXXXOOO.OO.XXXOOOOOX.XXO.OOOXXXOOXOOOXXXXOXOOO.X.XOOOOOX.XXXOO..Opening [('net', 24), ('opponent', 40), ('net', 39), ('opponent', 49), ('net', 59), ('opponent', 58), ('net', 60), ('opponent', 48), ('net', 50), ('opponent', 31), ('net', 41), ('opponent', 32), ('net', 57), ('opponent', 22), ('net', 47), ('opponent', 67), ('net', 56), ('opponent', 23), ('net', 66), ('opponent', 68), ('net', 30), ('opponent', 33), ('net', 42), ('opponent', 21)]Last [{'ply': 102, 'by': 'net', 'move': 50, 'top5': [[50, 0.9992], [59, 0.0004], [41, 0.0003], [81, 0.0], [3, 0.0]]}, {'ply': 103, 'by': 'opponent', 'move': 25}, {'ply': 104, 'by': 'net', 'move': 59, 'top5': [[59, 1.0], [41, 0.0], [81, 0.0], [3, 0.0], [79, 0.0]]}, {'ply': 105, 'by': 'opponent', 'move': 62}, {'ply': 106, 'by': 'net', 'move': 81, 'top5': [[81, 0.9965], [3, 0.0018], [79, 0.0013], [65, 0.0002], [37, 0.0001]]}, {'ply': 107, 'by': 'opponent', 'move': 81}]
GAME 5 margin -6.5 end two passes captures 8 lost 35XX.XOOO.XX.XXOOOOX.XXXXOOOOXXXXXOOOO.XXXOXXOOXXXXOO.OOXOOOOOOOOXXXXXOOOOX.XXOOOOOOpening [('net', 48), ('opponent', 40), ('net', 31), ('opponent', 49), ('net', 39), ('opponent', 58), ('net', 30), ('opponent', 57), ('net', 47), ('opponent', 32), ('net', 22), ('opponent', 56), ('net', 38), ('opponent', 23), ('net', 41), ('opponent', 50), ('net', 42), ('opponent', 33), ('net', 51), ('opponent', 60), ('net', 21), ('opponent', 24), ('net', 34), ('opponent', 14)]Last [{'ply': 99, 'by': 'opponent', 'move': 81}, {'ply': 100, 'by': 'net', 'move': 8, 'top5': [[81, 0.7823], [8, 0.2175], [2, 0.0001], [10, 0.0], [36, 0.0]]}, {'ply': 101, 'by': 'opponent', 'move': 81}, {'ply': 102, 'by': 'net', 'move': 17, 'top5': [[7, 0.3588], [17, 0.3588], [81, 0.2823], [2, 0.0], [10, 0.0]]}, {'ply': 103, 'by': 'opponent', 'move': 81}, {'ply': 104, 'by': 'net', 'move': 81, 'top5': [[81, 0.9998], [2, 0.0001], [10, 0.0001], [36, 0.0], [18, 0.0]]}]
GAME 7 margin -1.5 end two passes captures 25 lost 34.OOOXXXXXO.OOOXX.XOO.OOXXXXOOXOOOXX.OOXOOXX.XOXXOXXXX.OOOOOXX.XOOOOXX.X..OOOX.X.XOpening [('net', 49), ('opponent', 40), ('net', 50), ('opponent', 58), ('net', 60), ('opponent', 48), ('net', 59), ('opponent', 57), ('net', 47), ('opponent', 39), ('net', 67), ('opponent', 31), ('net', 41), ('opponent', 32), ('net', 51), ('opponent', 56), ('net', 23), ('opponent', 22), ('net', 42), ('opponent', 24), ('net', 33), ('opponent', 15), ('net', 14), ('opponent', 13)]Last [{'ply': 96, 'by': 'net', 'move': 81, 'top5': [[81, 0.9995], [16, 0.0003], [43, 0.0], [69, 0.0], [61, 0.0]]}, {'ply': 97, 'by': 'opponent', 'move': 27}, {'ply': 98, 'by': 'net', 'move': 81, 'top5': [[81, 0.9995], [16, 0.0003], [43, 0.0], [69, 0.0], [61, 0.0]]}, {'ply': 99, 'by': 'opponent', 'move': 54}, {'ply': 100, 'by': 'net', 'move': 81, 'top5': [[81, 0.9995], [16, 0.0003], [43, 0.0], [69, 0.0], [61, 0.0]]}, {'ply': 101, 'by': 'opponent', 'move': 81}]import shutilshutil.copyfile("/work/design.py","/work/design_v5.py")s=open("/work/design.py").read()marker='OB[81] = P["pass_bias"]'s=s.replace(marker,r'''# Tengen is a useful universal first move on the small board.# This gate is active only on the completely empty board.B[0][486]=1for p in range(81): W[0][3*p,486]=-1 W[0][3*p+1,486]=-1for k in range(1,6): W[k][486,486]=1OW[486,40]=8
''' + marker)open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v3.json"))exec(s)print("Added an empty-board-only tengen opening gate.")Added an empty-board-only tengen opening gate.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 6, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.59375, "wins": 57, "losses": 39, "score_as_black": 0.4791666567325592, "score_as_white": 0.7083333134651184, "mean_margin": 31.79166603088379, "mean_length": 112.65625, "stones_captured_per_game": 49.822916666666664, "stones_lost_per_game": 14.239583333333334, "passes_per_game": 2.0, "games_with_a_pass_before_move_60": 0, "end_two_passes": 90, "end_repetition": 5, "end_move_limit": 1}, "weak": {"games": 32, "score": 0.90625, "wins": 29, "losses": 3, "score_as_black": 0.8125, "score_as_white": 1.0, "mean_margin": 68.5625, "mean_length": 125.03125, "stones_captured_per_game": 87.46875, "stones_lost_per_game": 3.46875, "passes_per_game": 2.28125, "games_with_a_pass_before_move_60": 0, "end_two_passes": 31, "end_repetition": 0, "end_move_limit": 1}}, "files": "/work/pass_6/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutilshutil.copyfile("/work/design.py","/work/design_v6.py")s=open("/work/design.py").read()s=s.replace('decisiveness=1.6,','decisiveness=1.6, group_pressure=1.0,')s=s.replace(' add(2,dest,unit(color,p),3)\n B[2][dest]=-len(adj[p])',''' add(2,dest,unit(color,p),7) B[2][dest]=-len(adj[p])-4''')s=s.replace(' add(2,dest,unit(color,q),-0.5)',''' add(2,dest,unit(color,q),-0.5) add(2,dest,unit(2 if color==0 else 4,q),P["group_pressure"])''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v3.json"))overrides.update(weak_friend=2.0,weak_enemy=2.5)open("/work/params_v7.json","w").write(json.dumps(overrides))exec(s)print("Pressure features now account for vulnerable connected neighbours.")print(P)Pressure features now account for vulnerable connected neighbours.{'capture': 7.0, 'rescue': 6.0, 'self_atari': 9.0, 'eye': 11.0, 'crowd': 2.0, 'pass_bias': -2.0, 'friend_adj': 1.4, 'enemy_adj': 0.5, 'friend_diag': 0.6, 'enemy_diag': 0.1, 'friend_jump': 0.25, 'enemy_jump': 0.15, 'friend_knight': 0.1, 'enemy_knight': 0.05, 'seed_shared_liberty': 1.0, 'positional_scale': 2.0, 'low_liberty': 1.5, 'weak_friend': 2.0, 'weak_enemy': 2.5, 'decisiveness': 1.6, 'group_pressure': 1.0}{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 7, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.4479166567325592, "wins": 43, "losses": 53, "score_as_black": 0.3958333432674408, "score_as_white": 0.5, "mean_margin": 12.395833015441895, "mean_length": 136.65625, "stones_captured_per_game": 53.708333333333336, "stones_lost_per_game": 49.427083333333336, "passes_per_game": 1.5625, "games_with_a_pass_before_move_60": 0, "end_two_passes": 73, "end_repetition": 2, "end_move_limit": 21}, "weak": {"games": 32, "score": 0.78125, "wins": 25, "losses": 7, "score_as_black": 0.75, "score_as_white": 0.8125, "mean_margin": 46.625, "mean_length": 147.03125, "stones_captured_per_game": 88.46875, "stones_lost_per_game": 31.3125, "passes_per_game": 1.625, "games_with_a_pass_before_move_60": 0, "end_two_passes": 21, "end_repetition": 1, "end_move_limit": 10}}, "files": "/work/pass_7/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutilshutil.copyfile("/work/design.py","/work/design_v7.py")s=open("/work/design_v6.py").read()s=s.replace(' # Capture and rescue urgency.\n for q in adj[p]:\n add(5,unit(0,p),unit(3,q),1)\n add(5,unit(1,p),unit(2,q),1)',''' # Saturated tactical bonuses avoid counting the same string repeatedly. B[5][unit(0,p)]=1 B[5][unit(1,p)]=1 for q in adj[p]: add(5,unit(0,p),unit(3,q),-1) add(5,unit(1,p),unit(2,q),-1)''')s=s.replace('P["capture"], P["rescue"], -P["self_atari"]', '-P["capture"], -P["rescue"], -P["self_atari"]')s=s.replace('OB[p] = -20 + P["positional_scale"]*positional', 'OB[p] = -20 + P["capture"] + P["rescue"] + P["positional_scale"]*positional')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v3.json"))overrides.update(self_atari=16.0)open("/work/params_v8.json","w").write(json.dumps(overrides))exec(s)print("Saturated tactical urgency; strongly reject non-capturing self-atari.")Saturated tactical urgency; strongly reject non-capturing self-atari.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 8, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5625, "wins": 54, "losses": 42, "score_as_black": 0.5208333134651184, "score_as_white": 0.6041666865348816, "mean_margin": 33.76041793823242, "mean_length": 113.29166666666667, "stones_captured_per_game": 52.510416666666664, "stones_lost_per_game": 15.604166666666666, "passes_per_game": 2.0104166666666665, "games_with_a_pass_before_move_60": 0, "end_two_passes": 87, "end_repetition": 7, "end_move_limit": 2}, "weak": {"games": 32, "score": 1.0, "wins": 32, "losses": 0, "score_as_black": 1.0, "score_as_white": 1.0, "mean_margin": 81.0, "mean_length": 130.9375, "stones_captured_per_game": 99.71875, "stones_lost_per_game": 1.53125, "passes_per_game": 2.71875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 32, "end_repetition": 0, "end_move_limit": 0}}, "files": "/work/pass_8/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutilshutil.copyfile("/work/design.py","/work/design_v8.py")s=open("/work/design.py").read()a=s.index(' # Prefer moves with room')b=s.index('# Fifth layer',a)s=s[:a]+r''' # Binary access to a friendly string with spare liberties. # Count the string once even if it touches a move on several sides. dest=unit(5,p) B[3][dest]=1 for q in adj[p]: add(3,dest,unit(0,q),-1) add(3,dest,unit(2,q),1)
''' + s[b:]a=s.index(' # Insufficient escape')b=s.index(' dest=unit(3,p)',a)s=s[:a]+r''' # Conservative self-atari prevention with saturated friendly access. dest=unit(2,p) B[5][dest]=0.5-len(adj[p]) add(5,dest,unit(5,p),1.5) for q in adj[p]: add(5,dest,unit(0,q),1) add(5,dest,unit(1,q),1) add(5,dest,unit(3,q),-2)
''' + s[b:]s=s.replace(' for q in diag[p]:\n add(5,dest,unit(0,q),0.5)',''' for q in adj[p]: add(5,dest,unit(1,q),-0.75) for q in diag[p]: add(5,dest,unit(0,q),0.5)''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v8.json"))overrides.update(low_liberty=0.5)open("/work/params_v9.json","w").write(json.dumps(overrides))exec(s)print("Conservative string access; permit necessary connections in contested areas.")Conservative string access; permit necessary connections in contested areas.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 9, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.65625, "wins": 63, "losses": 33, "score_as_black": 0.5625, "score_as_white": 0.75, "mean_margin": 41.32291793823242, "mean_length": 116.625, "stones_captured_per_game": 60.9375, "stones_lost_per_game": 14.03125, "passes_per_game": 1.8020833333333333, "games_with_a_pass_before_move_60": 0, "end_two_passes": 84, "end_repetition": 8, "end_move_limit": 4}, "weak": {"games": 32, "score": 1.0, "wins": 32, "losses": 0, "score_as_black": 1.0, "score_as_white": 1.0, "mean_margin": 72.4375, "mean_length": 121.03125, "stones_captured_per_game": 85.1875, "stones_lost_per_game": 2.21875, "passes_per_game": 2.53125, "games_with_a_pass_before_move_60": 0, "end_two_passes": 31, "end_repetition": 1, "end_move_limit": 0}}, "files": "/work/pass_9/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import shutilshutil.copyfile("/work/design.py","/work/design_v9.py")s=open("/work/design.py").read()s=s.replace(' add(5,dest,unit(5,p),-P["low_liberty"])',r''' # Extend from healthy strings rather than from stones in trouble. for offsets, strength in [(DI,0.3),(JU,0.5),(KN,0.2)]: for q in points(p,offsets): add(5,dest,unit(0,q),strength) add(5,dest,unit(2,q),-strength) add(5,dest,unit(5,p),-P["low_liberty"])''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added healthy-string influence for diagonal, one-space, and knight extensions.")Added healthy-string influence for diagonal, one-space, and knight extensions.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 10, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5416666865348816, "wins": 52, "losses": 44, "score_as_black": 0.3958333432674408, "score_as_white": 0.6875, "mean_margin": 33.32291793823242, "mean_length": 110.3125, "stones_captured_per_game": 50.604166666666664, "stones_lost_per_game": 10.791666666666666, "passes_per_game": 2.03125, "games_with_a_pass_before_move_60": 0, "end_two_passes": 88, "end_repetition": 8, "end_move_limit": 0}, "weak": {"games": 32, "score": 0.875, "wins": 28, "losses": 4, "score_as_black": 0.8125, "score_as_white": 0.9375, "mean_margin": 62.46875, "mean_length": 119.625, "stones_captured_per_game": 79.0625, "stones_lost_per_game": 4.1875, "passes_per_game": 3.0625, "games_with_a_pass_before_move_60": 0, "end_two_passes": 30, "end_repetition": 2, "end_move_limit": 0}}, "files": "/work/pass_10/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,numpy as npexec(open("/work/analysis_helpers.py").read())gs=json.load(open("/work/pass_9/games.json")); bs=np.load("/work/pass_9/boards.npy")for i,g in enumerate(gs): if g["end"]!="repetition": continue print("\nGAME",i,g["opponent"],g["net_color"],"result",g["result"],"margin",g["margin"]) print(show(bs[i,len(g["moves"])-2])) print(g["moves"][-7:])
GAME 12 strong black result -1 margin -24.5...OOOO.OOOOOOOO..XXOO..OOO.XXOOOOOOXXXXXXOOO.XXXOOO.OXXXXO..OOXXXXXOOOO.X.XXXOO.[{'ply': 90, 'by': 'net', 'move': 22, 'top5': [[22, 0.6551], [14, 0.1973], [1, 0.1433], [17, 0.0015], [7, 0.0014]]}, {'ply': 91, 'by': 'opponent', 'move': 14}, {'ply': 92, 'by': 'net', 'move': 17, 'top5': [[17, 1.0], [1, 0.0], [7, 0.0], [81, 0.0], [59, 0.0]]}, {'ply': 93, 'by': 'opponent', 'move': 81}, {'ply': 94, 'by': 'net', 'move': 7, 'top5': [[7, 1.0], [1, 0.0], [81, 0.0], [59, 0.0], [22, 0.0]]}, {'ply': 95, 'by': 'opponent', 'move': 8}, {'ply': 96, 'by': 'net', 'move': 16, 'top5': [[16, 0.9832], [1, 0.0166], [81, 0.0001], [59, 0.0], [22, 0.0]]}]
GAME 27 strong black result -1 margin 6.5OX.X.XXO..OXXXXO.O.OOOOOOOOOXXOXXXXOOOXOX.XXXOOXX.XXX.OOX.X.X.XOOOXXXXXX.OO......[{'ply': 74, 'by': 'net', 'move': 71, 'top5': [[0, 0.3025], [76, 0.1872], [78, 0.1728], [71, 0.1255], [75, 0.0987]]}, {'ply': 75, 'by': 'opponent', 'move': 0}, {'ply': 76, 'by': 'net', 'move': 9, 'top5': [[9, 0.9427], [18, 0.0573], [2, 0.0], [78, 0.0], [76, 0.0]]}, {'ply': 77, 'by': 'opponent', 'move': 74}, {'ply': 78, 'by': 'net', 'move': 18, 'top5': [[18, 1.0], [75, 0.0], [76, 0.0], [78, 0.0], [80, 0.0]]}, {'ply': 79, 'by': 'opponent', 'move': 0}, {'ply': 80, 'by': 'net', 'move': 9, 'top5': [[9, 0.9427], [18, 0.0573], [75, 0.0], [2, 0.0], [76, 0.0]]}]
GAME 29 strong black result -1 margin 8.5XXXOOOOO..XOOOXOOOX.XOOXXXO.XXOXXX.XXXXOX.XX.X.XOOXXXXXXXXOXXXOXXOOOOXO.XOOOOOOO.[{'ply': 84, 'by': 'net', 'move': 63, 'top5': [[63, 0.9997], [81, 0.0003], [80, 0.0], [62, 0.0], [41, 0.0]]}, {'ply': 85, 'by': 'opponent', 'move': 76}, {'ply': 86, 'by': 'net', 'move': 81, 'top5': [[81, 0.9693], [80, 0.0192], [62, 0.011], [41, 0.0004], [34, 0.0]]}, {'ply': 87, 'by': 'opponent', 'move': 77}, {'ply': 88, 'by': 'net', 'move': 80, 'top5': [[80, 1.0], [81, 0.0], [62, 0.0], [41, 0.0], [34, 0.0]]}, {'ply': 89, 'by': 'opponent', 'move': 62}, {'ply': 90, 'by': 'net', 'move': 71, 'top5': [[71, 1.0], [81, 0.0], [41, 0.0], [34, 0.0], [19, 0.0]]}]
GAME 51 strong white result -1 margin -3.5.X.X.XXX.XX..OXXX.XXX.XXXOXXXXXXOOOOXXO.XOOO..X.XOOOOOX.XXXOOOOXXXXOOOOO.XXXXO.O.[{'ply': 91, 'by': 'net', 'move': 13, 'top5': [[39, 0.4435], [13, 0.2159], [11, 0.184], [26, 0.1336], [12, 0.0212]]}, {'ply': 92, 'by': 'opponent', 'move': 26}, {'ply': 93, 'by': 'net', 'move': 17, 'top5': [[17, 1.0], [12, 0.0], [39, 0.0], [11, 0.0], [47, 0.0]]}, {'ply': 94, 'by': 'opponent', 'move': 73}, {'ply': 95, 'by': 'net', 'move': 8, 'top5': [[4, 0.7231], [8, 0.2769], [12, 0.0], [39, 0.0], [11, 0.0]]}, {'ply': 96, 'by': 'opponent', 'move': 26}, {'ply': 97, 'by': 'net', 'move': 17, 'top5': [[17, 1.0], [12, 0.0], [39, 0.0], [11, 0.0], [47, 0.0]]}]
GAME 54 strong white result -1 margin 2.5O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXXX.XXXXXX.[{'ply': 93, 'by': 'net', 'move': 81, 'top5': [[81, 0.996], [59, 0.004], [60, 0.0], [11, 0.0], [1, 0.0]]}, {'ply': 94, 'by': 'opponent', 'move': 72}, {'ply': 95, 'by': 'net', 'move': 64, 'top5': [[64, 0.9999], [81, 0.0001], [59, 0.0], [60, 0.0], [63, 0.0]]}, {'ply': 96, 'by': 'opponent', 'move': 81}, {'ply': 97, 'by': 'net', 'move': 63, 'top5': [[63, 0.5], [73, 0.5], [81, 0.0], [59, 0.0], [60, 0.0]]}, {'ply': 98, 'by': 'opponent', 'move': 81}, {'ply': 99, 'by': 'net', 'move': 73, 'top5': [[73, 1.0], [81, 0.0], [59, 0.0], [60, 0.0], [11, 0.0]]}]
GAME 57 strong white result -1 margin 33.5.O.OOOO.OOOOOO.OOOOO.OOOOOX.OOO.OOXXO.O.OOOXXOOOOOOOXXXOXXOOOXX.XXXXXXXX.XXXX.XX.[{'ply': 89, 'by': 'net', 'move': 72, 'top5': [[72, 0.9991], [81, 0.0009], [54, 0.0001], [20, 0.0], [31, 0.0]]}, {'ply': 90, 'by': 'opponent', 'move': 54}, {'ply': 91, 'by': 'net', 'move': 63, 'top5': [[63, 1.0], [72, 0.0], [81, 0.0], [73, 0.0], [20, 0.0]]}, {'ply': 92, 'by': 'opponent', 'move': 73}, {'ply': 93, 'by': 'net', 'move': 72, 'top5': [[72, 1.0], [81, 0.0], [54, 0.0], [20, 0.0], [31, 0.0]]}, {'ply': 94, 'by': 'opponent', 'move': 54}, {'ply': 95, 'by': 'net', 'move': 63, 'top5': [[63, 1.0], [81, 0.0], [20, 0.0], [31, 0.0], [39, 0.0]]}]
GAME 58 strong white result -1 margin 13.5.OX..XO..O.OXXXXO..OXXXOOO.O.OXXOO.X.OOXXOOOXO.OXXOOOO.OOXXOOO.OXXXXXXXX..X......[{'ply': 67, 'by': 'net', 'move': 53, 'top5': [[53, 0.9645], [4, 0.0128], [6, 0.0073], [26, 0.0068], [62, 0.0036]]}, {'ply': 68, 'by': 'opponent', 'move': 71}, {'ply': 69, 'by': 'net', 'move': 6, 'top5': [[4, 0.3974], [6, 0.227], [26, 0.2096], [5, 0.0333], [17, 0.0284]]}, {'ply': 70, 'by': 'opponent', 'move': 5}, {'ply': 71, 'by': 'net', 'move': 4, 'top5': [[4, 0.9953], [7, 0.0047], [26, 0.0], [17, 0.0], [72, 0.0]]}, {'ply': 72, 'by': 'opponent', 'move': 2}, {'ply': 73, 'by': 'net', 'move': 3, 'top5': [[3, 0.9912], [7, 0.0088], [10, 0.0], [26, 0.0], [17, 0.0]]}]
GAME 80 strong white result -1 margin -2.5.XXO.XX..XXXOXXXXOXXXOXXXO.XXXXXXOOO.X.XXOOO.XXOXOOOOOXXOXXOOO.XXXXXOOOO.XXXOO.OO[{'ply': 121, 'by': 'net', 'move': 21, 'top5': [[21, 0.9549], [7, 0.0422], [4, 0.0016], [81, 0.0011], [2, 0.0003]]}, {'ply': 122, 'by': 'opponent', 'move': 2}, {'ply': 123, 'by': 'net', 'move': 7, 'top5': [[7, 0.9739], [81, 0.0246], [26, 0.0015], [62, 0.0], [44, 0.0]]}, {'ply': 124, 'by': 'opponent', 'move': 26}, {'ply': 125, 'by': 'net', 'move': 17, 'top5': [[17, 1.0], [8, 0.0], [81, 0.0], [7, 0.0], [44, 0.0]]}, {'ply': 126, 'by': 'opponent', 'move': 81}, {'ply': 127, 'by': 'net', 'move': 8, 'top5': [[8, 0.9917], [81, 0.0082], [26, 0.0001], [7, 0.0], [62, 0.0]]}]
GAME 105 weak black result 1 margin 2.5.XXX.XXX.XX.XXXOOOX.XXOOOO..XXOOOOOX.XXOXXOXXXOXXXOXXXOOOXXOX.XOOOOOOXX..O..OOX.X[{'ply': 69, 'by': 'opponent', 'move': 54}, {'ply': 70, 'by': 'net', 'move': 35, 'top5': [[35, 0.9703], [7, 0.0287], [26, 0.0008], [17, 0.0001], [8, 0.0]]}, {'ply': 71, 'by': 'opponent', 'move': 17}, {'ply': 72, 'by': 'net', 'move': 7, 'top5': [[7, 0.9997], [81, 0.0002], [27, 0.0001], [75, 0.0], [74, 0.0]]}, {'ply': 73, 'by': 'opponent', 'move': 27}, {'ply': 74, 'by': 'net', 'move': 45, 'top5': [[45, 1.0], [81, 0.0], [19, 0.0], [75, 0.0], [74, 0.0]]}, {'ply': 75, 'by': 'opponent', 'move': 36}]g=gs[54]; i=54for t in range(89,len(g["moves"])): print("\n",g["moves"][t]) print(show(bs[i,t]))
[stderr]Traceback (most recent call last): File "<string>", line 32, in <module>NameError: name 'gs' is not defined. Did you mean: 'os'?import json,numpy as npexec(open("/work/analysis_helpers.py").read())gs=json.load(open("/work/pass_9/games.json")); bs=np.load("/work/pass_9/boards.npy")g=gs[54]; i=54for t in range(89,len(g["moves"])): print("\n",g["moves"][t]) print(show(bs[i,t]))
{'ply': 89, 'by': 'net', 'move': 63, 'top5': [[63, 1.0], [65, 0.0], [81, 0.0], [73, 0.0], [59, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOO.XXXXXXX.XXXXXX.
{'ply': 90, 'by': 'opponent', 'move': 81}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOO.XXXXXXX.XXXXXX.
{'ply': 91, 'by': 'net', 'move': 73, 'top5': [[73, 1.0], [65, 0.0], [81, 0.0], [59, 0.0], [60, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOO.XXXXXX.OXXXXXX.
{'ply': 92, 'by': 'opponent', 'move': 65}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXX.OXXXXXX.
{'ply': 93, 'by': 'net', 'move': 81, 'top5': [[81, 0.996], [59, 0.004], [60, 0.0], [11, 0.0], [1, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXX.OXXXXXX.
{'ply': 94, 'by': 'opponent', 'move': 72}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XX..XXXXXXXX.XXXXXX.
{'ply': 95, 'by': 'net', 'move': 64, 'top5': [[64, 0.9999], [81, 0.0001], [59, 0.0], [60, 0.0], [63, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XX.OXXXXXXXX.XXXXXX.
{'ply': 96, 'by': 'opponent', 'move': 81}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XX.OXXXXXXXX.XXXXXX.
{'ply': 97, 'by': 'net', 'move': 63, 'top5': [[63, 0.5], [73, 0.5], [81, 0.0], [59, 0.0], [60, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXXX.XXXXXX.
{'ply': 98, 'by': 'opponent', 'move': 81}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXXX.XXXXXX.
{'ply': 99, 'by': 'net', 'move': 73, 'top5': [[73, 1.0], [81, 0.0], [59, 0.0], [60, 0.0], [11, 0.0]]}O.OO.O.OOOO.OO.OOXOOOOOOOXXOXOOOOXXXOXXOOOXXXXXXXOXXXXXXXXX..XXOOXXXXXXX.OXXXXXX.import json,shutilshutil.copyfile("/work/design.py","/work/design_v10.py")s=open("/work/design_v9.py").read()a=s.index(' # Local liberty pressure')b=s.index('# Fourth layer',a)s=s[:a]+r''' # Long-range safety messages travel only through proven same-colour # bridges: a stone and ALL its neighbours must have that colour. # Every Manhattan-distance-two endpoint is then connected to it. ring2=points(p,DI+JU) for color,ach,ch in [(0,2,4),(1,4,5)]: dest=unit(ch,p) B[2][dest]=-len(adj[p])-1 add(2,dest,unit(color,p),1) for q in adj[p]: add(2,dest,unit(color,q),1) for q in ring2: add(2,dest,unit(color,q),1/16) add(2,dest,unit(ach,q),-1/16)
''' + s[b:]a=s.index('# Fourth layer')b=s.index('# Sixth layer',a)s=s[:a]+r'''# Fourth layer: ordinary propagation plus certified dense bridges.for p in range(81): for ch in (0,1): carry(3,ch,p) for color,dch,tch in [(0,2,4),(1,3,5)]: dest=unit(dch,p) add(3,dest,unit(dch,p),1) add(3,dest,unit(tch,p),-4096) for q in adj[p]: add(3,dest,unit(color,q),-1) add(3,dest,unit(dch,q),1) add(3,dest,unit(tch,q),-4096) dest=unit(tch,p) B[3][dest]=-len(adj[p])-1 add(3,dest,unit(color,p),1) for q in adj[p]: add(3,dest,unit(color,q),1) for q in points(p,DI+JU): add(3,dest,unit(color,q),1/16) add(3,dest,unit(dch,q),-1/16) add(3,dest,unit(tch,q),1/16)
# Fifth layer completes long-range propagation and prepares action features.for p in range(81): for ch in (0,1): carry(4,ch,p) for color,dch,tch in [(0,2,4),(1,3,5)]: dest=unit(dch,p) add(4,dest,unit(dch,p),1) add(4,dest,unit(tch,p),-4096) for q in adj[p]: add(4,dest,unit(color,q),-1) add(4,dest,unit(dch,q),1) add(4,dest,unit(tch,q),-4096)
# Proactive pressure on enemy stones with few local liberties. dest=unit(4,p) B[4][dest]=-len(adj[p]) add(4,dest,unit(1,p),3) for q in adj[p]: add(4,dest,unit(0,q),1) add(4,dest,unit(1,q),0.5)
dest=unit(5,p) B[4][dest]=1 for q in adj[p]: add(4,dest,unit(0,q),-1) add(4,dest,unit(2,q),1) add(4,dest,unit(4,q),-4096)
''' + s[b:]s=s.replace(' add(5,dest,unit(4,p),1)',''' for q in adj[p]: add(5,dest,unit(4,q),P["weak_enemy"])''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added certified two-step safety propagation through dense strings.")Added certified two-step safety propagation through dense strings.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 11, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5416666865348816, "wins": 52, "losses": 44, "score_as_black": 0.375, "score_as_white": 0.7083333134651184, "mean_margin": 36.5625, "mean_length": 113.17708333333333, "stones_captured_per_game": 51.895833333333336, "stones_lost_per_game": 13.916666666666666, "passes_per_game": 2.2083333333333335, "games_with_a_pass_before_move_60": 0, "end_two_passes": 87, "end_repetition": 7, "end_move_limit": 2}, "weak": {"games": 32, "score": 0.9375, "wins": 30, "losses": 2, "score_as_black": 1.0, "score_as_white": 0.875, "mean_margin": 68.40625, "mean_length": 121.65625, "stones_captured_per_game": 80.78125, "stones_lost_per_game": 4.53125, "passes_per_game": 3.375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 29, "end_repetition": 2, "end_move_limit": 1}}, "files": "/work/pass_11/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v11.py")s=open("/work/design_v9.py").read()marker='# Tengen is a useful universal first move'idx=s.index(marker)extra=r'''# The unused units certify connectivity along complete straight strings.# A straight occupied segment has no duplicated boundary liberties.segments=[]for r in [0,2,4,6,8]: segments += [[r*9+c for c in range(5)], [r*9+c for c in range(4,9)]]for c in [0,2,4,6,8]: segments += [[r*9+c for r in range(5)], [r*9+c for r in range(4,9)]]for r in [1,7]: segments.append([r*9+c for c in range(2,7)])for c in [1,7]: segments.append([r*9+c for r in range(2,7)])assert len(segments)==24
# First layer seeds enemy strings with two distinct liberties.for j,seg in enumerate(segments): u=487+j boundary=[q for p in seg for q in adj[p] if q not in seg] assert len(boundary)==len(set(boundary)) B[0][u]=len(boundary)-1-16*len(seg) for p in seg: W[0][3*p+1,u]+=16 for q in boundary: W[0][3*q,u]-=1 W[0][3*q+1,u]-=1 for p in seg: W[1][u,unit(4,p)]-=16
# Second layer seeds own strings in the same way.for j,seg in enumerate(segments): u=487+j boundary=[q for p in seg for q in adj[p] if q not in seg] B[1][u]=len(boundary)-1-16*len(seg) for p in seg: W[1][unit(0,p),u]+=16 for q in boundary: W[1][unit(0,q),u]-=1 W[1][unit(1,q),u]-=1 reach=set(seg) for p in seg: reach.update(adj[p]) for p in reach: W[2][u,unit(2,p)]-=16
# Further layers broadcast safety across fully connected segments.for k,color,danger in [(2,1,4),(3,0,2)]: for j,seg in enumerate(segments): u=487+j B[k][u]=-len(seg) for p in seg: W[k][unit(color,p),u]+=1+1/16 W[k][unit(danger,p),u]-=1/16 reach=set(seg) for p in seg: reach.update(adj[p]) outdanger=3 if color==1 else 2 for p in reach: W[k+1][u,unit(outdanger,p)]-=32
'''s=s[:idx]+extra+s[idx:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added exact straight-string liberty and connectivity certificates.")Added exact straight-string liberty and connectivity certificates.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 12, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.6979166865348816, "wins": 67, "losses": 29, "score_as_black": 0.5833333134651184, "score_as_white": 0.8125, "mean_margin": 44.57291793823242, "mean_length": 119.48958333333333, "stones_captured_per_game": 67.94791666666667, "stones_lost_per_game": 13.427083333333334, "passes_per_game": 2.4583333333333335, "games_with_a_pass_before_move_60": 0, "end_two_passes": 86, "end_repetition": 6, "end_move_limit": 4}, "weak": {"games": 32, "score": 0.90625, "wins": 29, "losses": 3, "score_as_black": 1.0, "score_as_white": 0.8125, "mean_margin": 71.5625, "mean_length": 122.15625, "stones_captured_per_game": 88.125, "stones_lost_per_game": 2.84375, "passes_per_game": 2.9375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 29, "end_repetition": 3, "end_move_limit": 0}}, "files": "/work/pass_12/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v12.py")s=open("/work/design.py").read()idx=s.index('# Tengen is a useful universal first move')extra=r'''# Corner/edge snapback and cyclic-capture guard.# A singleton capture is dangerous if the resulting string has no# other empty neighbour and no connection to a healthy friendly string.corner_points=set()for r0,c0,dr,dc in [(0,0,1,1),(0,8,1,-1),(8,0,-1,1),(8,8,-1,-1)]: for a,b in [(0,0),(1,0),(0,1),(1,1),(2,0),(0,2)]: corner_points.add((r0+dr*a)*9+c0+dc*b)corner_points=sorted(corner_points)assert len(corner_points)==24slot={p:487+j for j,p in enumerate(corner_points)}for p,u in slot.items(): W[4][unit(3,p),u]=1 for q in adj[p]: W[4][unit(1,q),u]-=1
for p,u in slot.items(): B[5][u]=-4-4*len(adj[p]) W[5][unit(5,p),u]+=4 for q in adj[p]: W[5][unit(0,q),u]+=4 W[5][unit(1,q),u]+=4 W[5][unit(3,q),u]-=2 if q in slot: W[5][slot[q],u]+=3 OW[u,p]-=14
'''s=s[:idx]+extra+s[idx:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added local snapback/cyclic-capture guards in all four corners.")Added local snapback/cyclic-capture guards in all four corners.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 13, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5208333134651184, "wins": 50, "losses": 46, "score_as_black": 0.3958333432674408, "score_as_white": 0.6458333134651184, "mean_margin": 30.36458396911621, "mean_length": 111.69791666666667, "stones_captured_per_game": 49.677083333333336, "stones_lost_per_game": 15.114583333333334, "passes_per_game": 2.1354166666666665, "games_with_a_pass_before_move_60": 0, "end_two_passes": 88, "end_repetition": 6, "end_move_limit": 2}, "weak": {"games": 32, "score": 0.96875, "wins": 31, "losses": 1, "score_as_black": 0.9375, "score_as_white": 1.0, "mean_margin": 70.75, "mean_length": 121.40625, "stones_captured_per_game": 79.6875, "stones_lost_per_game": 3.03125, "passes_per_game": 2.84375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 30, "end_repetition": 2, "end_move_limit": 0}}, "files": "/work/pass_13/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v13.py")s=open("/work/design_v12.py").read()s=s.replace('for k,color,danger in [(2,1,4),(3,0,2)]:', 'for k,color,danger in [(2,1,4),(3,1,3)]:')needle=' reach=set(seg)\n for p in seg:\n reach.update(adj[p])\n outdanger=3 if color==1 else 2'replacement=''' if k==3: # Intersecting certified segments belong to the same string. for jj,other in enumerate(segments): if set(seg).intersection(other): W[k][487+jj,u]+=1/128 reach=set(seg) for p in seg: reach.update(adj[p]) outdanger=3 if color==1 else 2'''assert needle in ss=s.replace(needle,replacement)# A message can now be as small as (1/16)/128.s=s.replace('W[k+1][u,unit(outdanger,p)]-=32', 'W[k+1][u,unit(outdanger,p)]-=4096')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Extended enemy-string safety through intersecting certified segments.")Extended enemy-string safety through intersecting certified segments.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 14, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.6354166865348816, "wins": 61, "losses": 35, "score_as_black": 0.5, "score_as_white": 0.7708333134651184, "mean_margin": 39.57291793823242, "mean_length": 114.27083333333333, "stones_captured_per_game": 57.135416666666664, "stones_lost_per_game": 12.489583333333334, "passes_per_game": 1.9895833333333333, "games_with_a_pass_before_move_60": 0, "end_two_passes": 89, "end_repetition": 5, "end_move_limit": 2}, "weak": {"games": 32, "score": 0.96875, "wins": 31, "losses": 1, "score_as_black": 0.9375, "score_as_white": 1.0, "mean_margin": 71.75, "mean_length": 127.09375, "stones_captured_per_game": 84.40625, "stones_lost_per_game": 4.71875, "passes_per_game": 3.71875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 30, "end_repetition": 1, "end_move_limit": 1}}, "files": "/work/pass_14/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v14.py")overrides=json.load(open("/work/params_v9.json"))overrides["decisiveness"]=2.5open("/work/params_v15.json","w").write(json.dumps(overrides))exec(open("/work/design.py").read())print("Made the certified tactical/shape policy more decisive.")Made the certified tactical/shape policy more decisive.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 15, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.59375, "wins": 57, "losses": 39, "score_as_black": 0.4791666567325592, "score_as_white": 0.7083333134651184, "mean_margin": 37.63541793823242, "mean_length": 115.14583333333333, "stones_captured_per_game": 56.40625, "stones_lost_per_game": 13.8125, "passes_per_game": 2.1458333333333335, "games_with_a_pass_before_move_60": 0, "end_two_passes": 89, "end_repetition": 4, "end_move_limit": 3}, "weak": {"games": 32, "score": 0.96875, "wins": 31, "losses": 1, "score_as_black": 1.0, "score_as_white": 0.9375, "mean_margin": 78.6875, "mean_length": 125.46875, "stones_captured_per_game": 93.8125, "stones_lost_per_game": 2.625, "passes_per_game": 2.875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 30, "end_repetition": 2, "end_move_limit": 0}}, "files": "/work/pass_15/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v15.py")s=open("/work/design_v14.py").read()s=s.replace(' add(2,dest,unit(color,p),3)\n B[2][dest]=-len(adj[p])',''' add(2,dest,unit(color,p),7) B[2][dest]=-len(adj[p])-4''')s=s.replace(' add(2,dest,unit(color,q),-0.5)',''' add(2,dest,unit(color,q),-0.5) # Only healthy neighbours reduce a stone's local urgency. add(2,dest,unit(2 if color==0 else 4,q),0.5)''')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Local urgency now discounts healthy support, not endangered string-mates.")Local urgency now discounts healthy support, not endangered string-mates.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 16, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.625, "wins": 60, "losses": 36, "score_as_black": 0.5416666865348816, "score_as_white": 0.7083333134651184, "mean_margin": 42.45833206176758, "mean_length": 115.86458333333333, "stones_captured_per_game": 60.65625, "stones_lost_per_game": 11.947916666666666, "passes_per_game": 1.8958333333333333, "games_with_a_pass_before_move_60": 0, "end_two_passes": 80, "end_repetition": 12, "end_move_limit": 4}, "weak": {"games": 32, "score": 0.90625, "wins": 29, "losses": 3, "score_as_black": 0.875, "score_as_white": 0.9375, "mean_margin": 71.1875, "mean_length": 121.0625, "stones_captured_per_game": 81.09375, "stones_lost_per_game": 4.71875, "passes_per_game": 2.28125, "games_with_a_pass_before_move_60": 0, "end_two_passes": 31, "end_repetition": 1, "end_move_limit": 0}}, "files": "/work/pass_16/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v16.py")s=open("/work/design.py").read()idx=s.index('# Tengen is a useful universal first move')extra=r'''# Conservative endgame stopping: count only stones certified to have# at least two liberties. Ignore all prospective territory and captures.# If those stones alone beat every other point plus komi, avoid needless# invasions and positional-repetition fights.W[0][2,511]=1for k in range(1,6): W[k][511,511]=1for u,shift in [(487,0),(488,1)]: B[5][u]=-46.75-shift W[5][511,u]=7.5 for p in range(81): W[5][unit(0,p),u]+=1 W[5][unit(2,p),u]-=1OW[487,81]+=16OW[488,81]-=16
'''s=s[:idx]+extra+s[idx:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added a conservative safe-stone, komi-aware winning-pass gate.")Added a conservative safe-stone, komi-aware winning-pass gate.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 17, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.5729166865348816, "wins": 55, "losses": 41, "score_as_black": 0.5416666865348816, "score_as_white": 0.6041666865348816, "mean_margin": 26.76041603088379, "mean_length": 123.40625, "stones_captured_per_game": 55.53125, "stones_lost_per_game": 15.333333333333334, "passes_per_game": 8.770833333333334, "games_with_a_pass_before_move_60": 0, "end_two_passes": 69, "end_repetition": 6, "end_move_limit": 21}, "weak": {"games": 32, "score": 0.84375, "wins": 27, "losses": 5, "score_as_black": 0.8125, "score_as_white": 0.875, "mean_margin": 53.03125, "mean_length": 140.8125, "stones_captured_per_game": 92.71875, "stones_lost_per_game": 6.71875, "passes_per_game": 17.0, "games_with_a_pass_before_move_60": 0, "end_two_passes": 15, "end_repetition": 4, "end_move_limit": 13}}, "files": "/work/pass_17/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v17.py")s=open("/work/design_v14.py").read()a=s.index(' # Local liberty pressure')b=s.index('# Fourth layer',a)s=s[:a]+r''' # Shared friendly/enemy contact supports blocking, hane and connection. # min(own-contact, enemy-contact) is reconstructed in the next layer. dest=unit(4,p) for q in adj[p]: add(2,dest,unit(0,q),1) add(2,dest,unit(1,q),-1) dest=unit(5,p) add(2,dest,unit(1,p),3) B[2][dest]=-len(adj[p]) for q in adj[p]: add(2,dest,unit(0,q),1) add(2,dest,unit(1,q),0.5)
''' + s[b:]a=s.index(' # Urgency to support')b=s.index(' # Binary access',a)s=s[:a]+r''' B[3][unit(4,p)]=20 add(3,unit(4,p),unit(4,p),-1.5) for q in adj[p]: add(3,unit(4,p),unit(0,q),1.5) add(3,unit(4,p),unit(5,q),P["weak_enemy"])
''' + s[b:]s=s.replace(' B[5][dest] = 20',' B[5][dest] = 0')# The carried pressure/contact channel already contains the +20 offset.open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added explicit mixed-contact blocking/hane/connection preference.")Added explicit mixed-contact blocking/hane/connection preference.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 18, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.6666666865348816, "wins": 64, "losses": 32, "score_as_black": 0.5833333134651184, "score_as_white": 0.75, "mean_margin": 43.45833206176758, "mean_length": 114.8125, "stones_captured_per_game": 55.489583333333336, "stones_lost_per_game": 14.041666666666666, "passes_per_game": 1.59375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 84, "end_repetition": 11, "end_move_limit": 1}, "weak": {"games": 32, "score": 1.0, "wins": 32, "losses": 0, "score_as_black": 1.0, "score_as_white": 1.0, "mean_margin": 76.40625, "mean_length": 121.9375, "stones_captured_per_game": 85.15625, "stones_lost_per_game": 3.5, "passes_per_game": 2.40625, "games_with_a_pass_before_move_60": 0, "end_two_passes": 32, "end_repetition": 0, "end_move_limit": 0}}, "files": "/work/pass_18/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v18.py")s=open("/work/design.py").read()a=s.index('segments=[]')b=s.index('assert len(segments)==24',a)s=s[:a]+r'''# Fully occupied 2x2 blocks are connected and have eight distinct# external neighbours, so their liberty certificates are exact too.anchors=[(r,c) for r in [0,2,5,7] for c in [0,2,5,7]]anchors += [(r,c) for r in [3,4] for c in [3,4]]anchors += [(1,1),(1,6),(6,1),(6,6)]segments=[[(r+dr)*9+c+dc for dr in [0,1] for dc in [0,1]] for r,c in anchors]''' +s[b:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Connectivity certificates now cover dense 2x2 blocks across the board.")Connectivity certificates now cover dense 2x2 blocks across the board.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 19, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.7604166865348816, "wins": 73, "losses": 23, "score_as_black": 0.7083333134651184, "score_as_white": 0.8125, "mean_margin": 55.46875, "mean_length": 119.35416666666667, "stones_captured_per_game": 68.23958333333333, "stones_lost_per_game": 10.791666666666666, "passes_per_game": 1.7604166666666667, "games_with_a_pass_before_move_60": 0, "end_two_passes": 86, "end_repetition": 9, "end_move_limit": 1}, "weak": {"games": 32, "score": 0.96875, "wins": 31, "losses": 1, "score_as_black": 1.0, "score_as_white": 0.9375, "mean_margin": 76.78125, "mean_length": 120.875, "stones_captured_per_game": 83.25, "stones_lost_per_game": 3.0625, "passes_per_game": 2.25, "games_with_a_pass_before_move_60": 0, "end_two_passes": 30, "end_repetition": 2, "end_move_limit": 0}}, "files": "/work/pass_19/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v19.py")s=open("/work/design.py").read()needle='# Further layers broadcast safety across fully connected segments.\nfor k,color,danger in [(2,1,4),(3,1,3)]:\n for j,seg in enumerate(segments):'replacement=r'''# Stagger the later block certificates. Together the three enemy# stages cover all 64 possible 2x2 blocks, preserving board symmetries.def blocks_with_orbits(orbits): out=[] for r in range(8): for c in range(8): key=tuple(sorted([abs(2*r-7),abs(2*c-7)])) if key in orbits: out.append([(r+dr)*9+c+dc for dr in [0,1] for dc in [0,1]]) return outthird=blocks_with_orbits({(1,3),(5,7),(1,1),(5,5)})fourth=blocks_with_orbits({(1,5),(1,7),(3,5)})assert len(third)==len(fourth)==24assert len({tuple(x) for x in segments+third+fourth})==64
# Further layers broadcast safety across fully connected blocks.for k,color,danger in [(2,1,4),(3,1,3)]: active_segments=third if k==2 else fourth for j,seg in enumerate(active_segments):'''assert needle in ss=s.replace(needle,replacement)s=s.replace('for jj,other in enumerate(segments):','for jj,other in enumerate(third):')open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Staggered safety certificates cover every 2x2 block.")Staggered safety certificates cover every 2x2 block.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 20, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.7083333134651184, "wins": 68, "losses": 28, "score_as_black": 0.7291666865348816, "score_as_white": 0.6875, "mean_margin": 46.0625, "mean_length": 116.375, "stones_captured_per_game": 61.25, "stones_lost_per_game": 14.572916666666666, "passes_per_game": 1.6979166666666667, "games_with_a_pass_before_move_60": 1, "end_two_passes": 82, "end_repetition": 10, "end_move_limit": 4}, "weak": {"games": 32, "score": 0.90625, "wins": 29, "losses": 3, "score_as_black": 0.9375, "score_as_white": 0.875, "mean_margin": 69.875, "mean_length": 115.40625, "stones_captured_per_game": 69.09375, "stones_lost_per_game": 2.375, "passes_per_game": 2.09375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 28, "end_repetition": 4, "end_move_limit": 0}}, "files": "/work/pass_20/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v20.py")s=open("/work/design_v19.py").read()# Insert after the ordinary opening gate has been constructed.idx=s.index('OB[81] = P["pass_bias"]')extra=r'''# Stop unnecessary fights only with BOTH a conservative safe-stone# area lead and two solid eyes witnessed on a symmetric sample.W[0][2,511]=1for k in range(1,4): W[k][511,511]=1
eye_points=[r*9+c for r in range(0,9,2) for c in range(0,9,2) if (r,c)!=(4,4)]assert len(eye_points)==24for j,p in enumerate(eye_points): u=487+j ring=adj[p]+diag[p] B[4][u]=1-len(ring) for q in ring: W[4][unit(0,q),u]+=1 W[4][unit(0,p),u]-=8 W[4][unit(1,p),u]-=8
# Two neighbouring thresholds make a clipped, komi-aware lead signal.W[4][:,486]=0W[4][:,511]=0for u,shift in [(511,0),(486,1)]: B[4][u]=-46.75-shift W[4][511,u]=7.5 for p in range(81): W[4][unit(0,p),u]+=1 W[4][unit(2,p),u]-=1
# For fewer than two witnessed eyes both gates are zero.# Otherwise their difference is exactly the clipped lead signal.for u,source in [(487,511),(488,486)]: B[5][u]=-200 W[5][source,u]=1 for v in range(487,511): W[5][v,u]=100OW[487,81]+=16OW[488,81]-=16
# Recompute the empty-board gate directly; its old carry slot was reused.W[5][:,486]=0B[5][486]=1for p in range(81): W[5][unit(0,p),486]=-1 W[5][unit(1,p),486]=-1
'''s=s[:idx]+extra+s[idx:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added a bounded winning-pass gate requiring two solid eyes and an area lead.")Added a bounded winning-pass gate requiring two solid eyes and an area lead.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 21, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.75, "wins": 72, "losses": 24, "score_as_black": 0.7083333134651184, "score_as_white": 0.7916666865348816, "mean_margin": 48.375, "mean_length": 117.54166666666667, "stones_captured_per_game": 59.479166666666664, "stones_lost_per_game": 11.4375, "passes_per_game": 3.25, "games_with_a_pass_before_move_60": 0, "end_two_passes": 87, "end_repetition": 8, "end_move_limit": 1}, "weak": {"games": 32, "score": 0.875, "wins": 28, "losses": 4, "score_as_black": 0.9375, "score_as_white": 0.8125, "mean_margin": 71.6875, "mean_length": 116.1875, "stones_captured_per_game": 76.59375, "stones_lost_per_game": 2.28125, "passes_per_game": 2.84375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 26, "end_repetition": 5, "end_move_limit": 1}}, "files": "/work/pass_21/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json,shutilshutil.copyfile("/work/design.py","/work/design_v21.py")s=open("/work/design_v19.py").read()idx=s.index('OB[81] = P["pass_bias"]')extra=r'''# Two witnessed solid enemy eyes warn against treating a large living# string as capturable merely because its liberties are far apart.eye_points=[r*9+c for r in range(0,9,2) for c in range(0,9,2)]for j,p in enumerate(eye_points): u=487+j ring=adj[p]+diag[p] B[4][u]=1-len(ring) for q in ring: W[4][unit(1,q),u]+=1 W[4][unit(0,p),u]-=8 W[4][unit(1,p),u]-=8
B[5][487]=1for v in range(487,512): W[5][v,487]=-1for p in range(81): # Positive capture evidence, disabled when two solid eyes are seen. u=unit(0,p) W[5][:,u]=0 B[5][u]=4 for q in adj[p]: W[5][unit(3,q),u]+=1 for v in range(487,512): W[5][v,u]-=4 OW[u,p]=P["capture"] OW[487,p]-=4*P["capture"] OB[p]-=P["capture"]
'''s=s[:idx]+extra+s[idx:]open("/work/design.py","w").write(s)overrides=json.load(open("/work/params_v9.json"))exec(s)print("Added a two-solid-enemy-eyes safeguard against false capture urgency.")Added a two-solid-enemy-eyes safeguard against false capture urgency.{"games":{"strong":96,"weak":32}}{"ok": true, "pass": 22, "kind": "games", "per_opponent": {"strong": {"games": 96, "score": 0.6354166865348816, "wins": 61, "losses": 35, "score_as_black": 0.625, "score_as_white": 0.6458333134651184, "mean_margin": 44.03125, "mean_length": 110.69791666666667, "stones_captured_per_game": 55.354166666666664, "stones_lost_per_game": 11.479166666666666, "passes_per_game": 1.4791666666666667, "games_with_a_pass_before_move_60": 0, "end_two_passes": 79, "end_repetition": 16, "end_move_limit": 1}, "weak": {"games": 32, "score": 0.96875, "wins": 31, "losses": 1, "score_as_black": 0.9375, "score_as_white": 1.0, "mean_margin": 71.875, "mean_length": 117.5625, "stones_captured_per_game": 73.375, "stones_lost_per_game": 2.34375, "passes_per_game": 2.6875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 32, "end_repetition": 0, "end_move_limit": 0}}, "files": "/work/pass_22/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}import json, shutil, numpy as npshutil.copyfile("/work/design.py","/work/design_v22.py")final_source=open("/work/design_v19.py").read()open("/work/design.py","w").write(final_source)open("/work/final_design.py","w").write(final_source)overrides=json.load(open("/work/params_v9.json"))open("/work/final_parameters.json","w").write(json.dumps(overrides,indent=2))exec(final_source)
# Audit tensors only; no policy evaluation is performed here.total=0for name in saved(): a=load(name) assert np.isfinite(a).all(), name total+=a.size print(name, a.shape, "nonzero", np.count_nonzero(a), "max_abs", float(np.max(np.abs(a))))assert total==1480274print("Final network restored and saved; all 1,480,274 parameters are finite.")L1.W (243, 512) nonzero 3368 max_abs 16.0L1.b (512,) nonzero 349 max_abs 61.0L2.W (512, 512) nonzero 4203 max_abs 16.0L2.b (512,) nonzero 186 max_abs 61.0L3.W (512, 512) nonzero 3896 max_abs 16.0L3.b (512,) nonzero 105 max_abs 4.0L4.W (512, 512) nonzero 3234 max_abs 4096.0L4.b (512,) nonzero 186 max_abs 20.0L5.W (512, 512) nonzero 1895 max_abs 4096.0L5.b (512,) nonzero 0 max_abs 0.0L6.W (512, 512) nonzero 5548 max_abs 2.0L6.b (512,) nonzero 405 max_abs 3.5out.W (512, 82) nonzero 487 max_abs 25.600000381469727out.b (82,) nonzero 82 max_abs 14.080000877380371Final network restored and saved; all 1,480,274 parameters are finite.{"positions":[{"board":[".........",".........",".........",".........",".........",".........",".........",".........","........."],"to_move":"black"},{"board":[".........",".........",".........","....X....","...XO....","....X....",".........",".........","........."],"to_move":"black"},{"board":[".........",".........",".........","....O....","...OX....","....O....",".........",".........","........."],"to_move":"black"},{"board":[".........",".........",".........","...XX....","..XOO....","...XX....",".........",".........","........."],"to_move":"black"},{"board":[".........",".........",".........","....X....","...X.X...","....X....",".........",".........","........."],"to_move":"black"},{"board":["XXXXXXXXX","XXXXXXXXX","XX.XXXXXX","XXXXXXXXX","XXXXXXXXX","XXXXXXXXX","XXXXXX.XX","XXXXXXXXX","XXXXXXXXX"],"to_move":"black"}],"activations":true}{"ok": true, "pass": 23, "kind": "positions", "positions": 6, "top3_per_position": [[["(4,4)", 1.0], ["(2,6)", 0.0], ["(6,6)", 0.0]], [["(4,5)", 1.0], ["(3,3)", 0.0], ["(5,3)", 0.0]], [["(4,5)", 0.9996], ["(3,3)", 0.0001], ["(5,3)", 0.0001]], [["(4,5)", 1.0], ["(3,2)", 0.0], ["(5,2)", 0.0]], [["(3,3)", 0.2062], ["(5,5)", 0.2062], ["(5,3)", 0.2062]], [["pass", 1.0], ["(2,2)", 0.0], ["(6,6)", 0.0]]], "files": "/work/pass_23/", "readme": "inputs.npy (P, 243) the network inputs; legal.npy (P, 82) the legal moves (for 'board' positions: the empty points and pass; suicide and ko are not checked); logits.npy, probs.npy (P, 82); act_L1.npy .. act_L6.npy (P, 512) the hidden activations after ReLU."}{"games":{"strong":128}}{"ok": true, "pass": 24, "kind": "games", "per_opponent": {"strong": {"games": 128, "score": 0.734375, "wins": 94, "losses": 34, "score_as_black": 0.703125, "score_as_white": 0.765625, "mean_margin": 52.6171875, "mean_length": 116.671875, "stones_captured_per_game": 62.7109375, "stones_lost_per_game": 10.3359375, "passes_per_game": 1.671875, "games_with_a_pass_before_move_60": 0, "end_two_passes": 114, "end_repetition": 13, "end_move_limit": 1}}, "files": "/work/pass_24/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}{"games":{"weak":64,"random":64}}{"ok": true, "pass": 25, "kind": "games", "per_opponent": {"random": {"games": 64, "score": 0.984375, "wins": 63, "losses": 1, "score_as_black": 1.0, "score_as_white": 0.96875, "mean_margin": 77.84375, "mean_length": 117.21875, "stones_captured_per_game": 80.84375, "stones_lost_per_game": 0.5, "passes_per_game": 1.109375, "games_with_a_pass_before_move_60": 0, "end_two_passes": 63, "end_repetition": 1, "end_move_limit": 0}, "weak": {"games": 64, "score": 0.921875, "wins": 59, "losses": 5, "score_as_black": 0.875, "score_as_white": 0.96875, "mean_margin": 71.796875, "mean_length": 118.8125, "stones_captured_per_game": 72.8125, "stones_lost_per_game": 4.265625, "passes_per_game": 2.125, "games_with_a_pass_before_move_60": 0, "end_two_passes": 60, "end_repetition": 4, "end_move_limit": 0}}, "files": "/work/pass_25/", "readme": "games.json: one entry per game (opponent, net_color, result +1/-1, margin = net's area score minus the opponent's incl. komi, end, stones captured / lost, moves: ply, by, move (row*9+col, 81 = pass), and for the network's moves its top-5 [move, probability]). boards.npy: (games, 162, 81) int8, the board AFTER each ply (1 Black, -1 White, 0 empty; index row*9+col); valid.npy: (games, 162) which plies were played."}