Pyaq(囲碁ソフト)の調査

Pyaq(囲碁ソフト)の調査

目次

1 概要

  • Deep Learningで学習できる、囲碁ソフト
  • Pythonベース
  • MITライセンス

2 リンク

3 Boardクラスをちょっと試してみる

  • Dockerイメージで構築します。
  • Docker Hub の tensorflow/tensorflowイメージをベースに行います。
  • tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。

3.1 以下の操作を行っている動画


3.2 GNU Globalでソースを読みやすくなるようにする

  • terminalを起動し以下を実行
  • 作業用のディレクトリを作成し、ソースをゲット、GNU Globalで処理して、よみやすくなったHTMLを生成し、w3mで開く
sudo su - user
cd /tf/notebooks/
mkdir -p Pyaq
cd Pyaq
git clone https://github.com/ymgaq/Pyaq.git
cd Pyaq
# gtags --gtagslabel=pygments
htags -afFIsngov --gtagslabel=pygments
w3m HTML/index.html
  • w3mでみたら、Shift+Fで、より読みやすくなる

3.3 他の端末を開いて、board.pyの中にはいっている、関数やBoardクラスを使ってみる

3.3.1 以下でipython3を起動

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq/
ipython3

3.3.2 ipython3内部で以下を実行

  • ボードを生成して、いろいろやってみる
import board
b=board.Board()  # ボードを作成
b.random_play()  # ランダムに1手
b.showboard()    # ボードを表示
b.clear()        # ボードをクリア
b.showboard()
board.ev2str(81) # 内部で81が何か? => 'D7'
board.ev2xy(81)  # 内部で81が何か? => (4, 7)
board.ev2rv(81)  # 内部で81が何か? => 57
board.str2ev("D7") # => 81
b.place_stone(board.str2ev("D7")) # D7に石を置く
b.showboard()                     # ボードを表示
b.place_stone(board.str2ev("E7")) # E7に石を置く
b.showboard()                     # ボードを表示
b.place_stone(board.str2ev("F8")) # F8に石を置く
b.showboard()                     # ボードを表示
b.place_stone(board.str2ev("E9")) # E9に石を置く
b.showboard()                     # ボードを表示
b.place_stone(board.str2ev("D8")) # D8に石を置く
b.showboard()                     # ボードを表示
b.play(board.str2ev("F7"))        # playとしてF7に石を置く
b.showboard()                     # ボードを表示
b.legal(board.str2ev("E8"))       # E8に石を置けるかチェック => False
b.legal(board.str2ev("F6"))       # F6に石を置けるかチェック => True
b.play(board.str2ev("F6"))        # playとしてF6に石を置く
b.showboard()                     # ボードを表示
b.play(board.str2ev("F5"))        # playとしてF5に石を置く
b.showboard()                     # ボードを表示
b.feature()                       # 評価関数(search.py evaluate)に渡されているものをみてみる
type(b.feature())                 # タイプ確認
b.feature().ndim                  # 次元数確認 => 2
b.feature().shape                 # 次元数確認 => (81, 7)
b.feature().size                  # 次元数確認 => 567
len(b.feature())                  # len => 81

3.4 この章のまとめ

  • Pyaqのソースをゲットしてきて、GNU Globalで読みやすく加工
  • IPythonを利用して、board.pyにはいっている関数や、Boardクラスを試してみた

4 Boardクラスをちょっと試してみる2

  • ボードの指定座標の状態を知る(白か黒か空か)
  • 一つ前の手を確認
  • 1つ前のボードの状態を確認
  • どちらの手番か確認
  • tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。

4.1 以下の操作を行っている動画


4.2 今回の操作をやるために調べたソースの部分

4.2.1 Boardクラスのshowboadメソッド

  • ループまわして、それぞれの座標の状態を表示している
  • 330行に調べる部分がある
  • このソースから、指定座標の状態を知る方法が簡単に調べられる
  • 333行目から、一つ前の手がどれかを調べる方法が確認可能
315     def showboard(self):
316
317         def pirnt_xlabel():
318             line_str = "  "
319             for x in range(BSIZE):
320                 line_str += " " + x_labels[x] + " "
321             stderr.write(line_str + "\n")
322
323         pirnt_xlabel()
324
325         for y in range(1, BSIZE + 1)[::-1]:  # 9, 8, ..., 1
326             line_str = str(y) if y >= 10 else " " + str(y)
327             for x in range(1, BSIZE + 1):
328                 v = xy2ev(x, y)
329                 x_str = " . "
330                 color = self.color[v]
331                 if color <= 1:
332                     stone_str = "O" if color == 0 else "X"
333                     if v == self.prev_move:
334                         x_str = "[" + stone_str + "]"
335                     else:
336                         x_str = " " + stone_str + " "
337                 line_str += x_str
338             line_str += str(y) if y >= 10 else " " + str(y)
339             stderr.write(line_str + "\n")
340
341         pirnt_xlabel()
342         stderr.write("\n")

4.2.2 Boardクラスの clearメソッド

  • 116行目に、prev_colorへの代入文がある。これから、KEEP_PREV_CNTの数の分前の盤の状態を保持することがわかる
110     def clear(self):
111         self.color[rv_list] = 2  # empty
112         self.id = np.arange(EBVCNT)  # id of stone group
113         self.next = np.arange(EBVCNT)  # next position in the same group
114         for i in range(EBVCNT):
115             self.sg[i].clear(stone=False)
116         self.prev_color = [np.copy(self.color) for _ in range(KEEP_PREV_CNT)]
117
118         self.ko = VNULL  # illegal position due to Ko
119         self.turn = 1  # black
120         self.move_cnt = 0  # move count
121         self.prev_move = VNULL  # previous move
122         self.remove_cnt = 0  # removed stones count
123         self.history = []

4.3 手順

  • 前の章のやり方でDocker imageを起動
  • 他の端末を開いて、IPythonを起動

4.3.1 以下でipython3を起動

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq/
ipython3
  • IPython内で以下を実行しボードクラスを使ってみる2
import board
b=board.Board()                   # ボードを作成
b.showboard()                     # ボードを表示
b.turn                            # => 1
b.prev_color                      
b.prev_color[0]==b.prev_color[1]  
b.color.reshape(11,11)            # ボード情報を格納しているcolorをreshapeして表示 0:O 1:X 2:空 3:壁
b.play(board.str2ev("F7"))        # playとしてF7に石を置く
b.showboard()                     # ボードを表示
b.color.reshape(11,11)
b.prev_color                      
b.prev_color[0]==b.prev_color[1]  
b.turn                            # => 0
b.play(board.str2ev("A1"))        # playとしてA1に石を置く
b.showboard()                     # ボードを表示
b.color.reshape(11,11)
b.color[board.str2ev("F7")]       # F7 の状態 => 1
b.color[board.str2ev("A1")]       # A1 の状態 => 0
b.color[board.str2ev("A2")]       # A2 の状態 => 2
b.color[1]                        # 壁 の状態 => 3
type(b.prev_color)                # => list
b.prev_move
board.ev2str(b.prev_move)         # => A1

import numpy as np
b.prev_color                      
b.prev_color[0]==b.prev_color[1]  
x=(b.prev_color[0]==b.prev_color[1])
np.where( x == False )            # どこが変化したか確認 => (arrya[83])
board.ev2str(83)                  # => F7

board.KEEP_PREV_CNT=3             # KEEP_PREV_CNTを変更してみる
b=board.Board()                   # Boardを再度生成
b.prev_color                      # prev_colorを確認、要素数が増えている
len(b.prev_color)                 # => 3

4.4 この章のまとめ

  • Boardクラスで、指定座標の状態の調べ方がわかった
  • 手番、一つ前のコマの状態、一つ前の盤の状態の調べ方がわかった
  • 一つ前の手の調べ方がわかった
  • 何手前まで、盤の状態を保持させるかの設定を変更してみた

5 評価関数で、好きな盤の状態を評価させてみた

  • 今までの章でボードクラスの扱いはだいたいわかったので、その盤の状態を現在の評価関数で評価させてみた
  • TensorFlow 2.1.0 で動かすと AttributeError: module ‘tensorflow’ has no attribute ‘get_default_graph’ というエラーが
  • 上の2.1.0で動かした時にエラー、これを使えば解決できそうだが? tf.compat.v1.get_default_graph https://www.tensorflow.org/api_docs/python/tf/compat/v1/get_default_graph
  • tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。

5.1 以下の操作を行っている動画


5.2 評価関数を直接使ってみる操作手順

5.2.1 イメージ起動

  • 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

5.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

5.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
ipython3                      #  ipython3起動

5.2.4 IPython内で以下を実行

from collections import Counter
import sys
from board import *
import gtp
import learn
import search
use_gpu = False

b = Board()                  #ボード生成

tree = search.Tree("model.ckpt", use_gpu) 
tree.evaluate(b)             # bのボードを評価
(a1,a2)=tree.evaluate(b)     # bのボードを評価を(a1,a2)に保存
a1.shape                     # a1 shape確認 => (1, 82)
a2.shape                     # a2 shape確認 => (1,)
type(a1)                     # a1 type確認  => numpy.ndarray
type(a2)                     # a2 type確認  => numpy.ndarray
a1                           # a1 確認      => 大きいので省略
a2                           # a2 確認      => array([0.02216651], dtype=float32)

5.3 この章でのまとめ

  • 評価関数に、作成した盤の状態をわたして、評価してみた
  • 返ってくるのは要素数82個の配列と、要素数1個の配列のタプル
  • この評価部分を差し替えれば、好きな評価関数での囲碁ソフトエンジン作成可能であろう(多分)
  • 9×9の盤なのに、なぜ82個なのか?調査継続

6 任意の盤を与えてお勧めの手をゲット

  • 前の章では、任意の盤を評価関数かけて、返り値をゲット出来た
  • この章では、任意の盤を与えて、一番お勧めの手をゲットしてみる
  • なぜ9×9=81の盤なのに、評価関数の返り値の配列の要素が82で1個多いのかも、理由判明(passがあるためでした)
  • search.pyの中を調べた
  • tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。

6.1 以下の操作を行っている動画


6.2 任意の盤を与えてお勧めの手をゲットする手順

6.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

6.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

6.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
ipython3                      #  ipython3起動

6.2.4 IPython内で以下を実行

from collections import Counter
import sys
from board import *
import gtp
import learn
import search
use_gpu = False

b = Board()                  #ボード生成

tree = search.Tree("model.ckpt", use_gpu) 
tree.evaluate(b)             # bのボードを評価
(a1,a2)=tree.evaluate(b)     # bのボードを評価を(a1,a2)に保存

rv2ev(np.argmax(tree.evaluate(b)[0][0])) # お勧めの手のev値ゲット
np.argmax(tree.evaluate(b)[0][0])        # np.argmax(tree.evaluate(b)[0][0]) の確認 => 40
tree.evaluate(b)[0][0]                   # tree.evaluate(b)[0][0] の確認 
ev2str(rv2ev(np.argmax(tree.evaluate(b)[0][0]))) # strでお勧めの手を確認 => 'E5'
b.showboard()                            # ボード表示
ev2str(rv2ev(0))                         #  0の場合のstr確認 => 'A1'
ev2str(rv2ev(1))                         #  1の場合のstr確認 => 'B1'
ev2str(rv2ev(81))                        # 81の場合のstr確認 => 'pass'
ev2str(rv2ev(82))                        # 82の場合のstr確認 => 'B10' 0->81で82個だから、この値にはならない

6.3 この章でのまとめ

  • 任意の盤でのお勧めの手を得る手順を確認
  • 9×9=81個のおける場所にたいして82個の配列がかえってくる理由を確認(passがあるからでした)

7 StoneGroupクラスの調査

7.1 以下の操作を行っている動画


7.2 任意の盤を与えてお勧めの手をゲットする手順

7.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

7.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

7.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
ipython3                      #  ipython3起動

7.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
    ipython3                      #  ipython3起動
    

7.2.5 IPython内で以下を実行

  • StoneGroup のメンバ変数 lib_cnt が 隣接の空いているあるいは、味方の石の数
  • StoneGroup のメンバ変数 size が縦横で接続されている石の数の場合もあるし、他の数値になっているケースも(追加調査必用)
  • StoneGroup のメンバ変数 v_atr が当たりになっているケースあり
  • StoneGroup のメンバ変数 libs が隣接の空座標や、先に存在している仲間の石の座標の場合も
from collections import Counter
import sys
from board import *
import gtp
import learn
import search
use_gpu = False

# ある座標のStoneGroupのメンバ変数の中身表示用関数
def myShowSg(x):
  print(">>>>>>>: "+x)
  print("lib_cnt: ", end=" ")
  print(b.sg[str2ev(x)].lib_cnt)
  print("size   : ", end=" ")
  print(b.sg[str2ev(x)].size)
  print("v_atr  : ", end=" ")
  print(str(b.sg[str2ev(x)].v_atr)+" : "+ev2str(b.sg[str2ev(x)].v_atr))
  print("libs   : ", end=" ")
  print(b.sg[str2ev(x)].libs)
  for i in b.sg[str2ev(x)].libs:
    print(ev2str(i), end=", ")
  print("")

b = Board()                  #ボード生成

b.place_stone(str2ev("E7")) # E7に石を置く
b.showboard()               # ボードを表示
b.place_stone(str2ev("F8")) # F8に石を置く
b.showboard()               # ボードを表示
b.place_stone(str2ev("E9")) # E9に石を置く
b.showboard()               # ボードを表示
b.place_stone(str2ev("D8")) # D8に石を置く
b.showboard()               # ボードを表示
b.turn=0
b.place_stone(str2ev("F9")) # F9に石を置く
b.showboard()               # ボードを表示
b.place_stone(str2ev("F7")) # F7に石を置く
b.showboard()               # ボードを表示
b.place_stone(str2ev("G8")) # G8に石を置く
b.showboard()               # ボードを表示
b.legal(str2ev("E8"))       # E8に石を置ける? => True


b.sg                        # ボードのsgメンバーの内容
type(b.sg)                  # b.sgのタイプは? => list
len(b.sg)                   # b.sgの長さは? => 121
b.color.shape               # b.colorのshapeは? => (121,) b.sgの長さと同じつまり、"b.sgは、evで希望のStoneGroupeにアクセス可能"

b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  .  .  .  9
#  8 .  .  .  X  .  X  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
myShowSg("E9")
myShowSg("E7")
myShowSg("D8")
myShowSg("F8")
# >>>>>>>: E9
# lib_cnt:  2
# size   :  1
# v_atr  :  93 : E8
# libs   :  {93, 103}
# E8, D9,
# >>>>>>>: E7
# lib_cnt:  3
# size   :  1
# v_atr  :  71 : E6
# libs   :  {81, 93, 71}
# D7, E8, E6,
# >>>>>>>: D8
# lib_cnt:  4
# size   :  1
# v_atr  :  81 : D7
# libs   :  {81, 91, 93, 103}
# D7, C8, E8, D9,
# >>>>>>>: F8
# lib_cnt:  1
# size   :  1
# v_atr  :  83 : F7
# libs   :  {93}
# E8,

b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  .  .  .  9
#  8 .  .  .  X  .  X  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
myShowSg("F9")
myShowSg("F7")
myShowSg("G8")
# >>>>>>>: F9
# lib_cnt:  1
# size   :  1
# v_atr  :  106 : G9
# libs   :  {106}
# G9,
# >>>>>>>: F7
# lib_cnt:  2
# size   :  1
# v_atr  :  72 : F6
# libs   :  {72, 84}
# F6, G7,
# >>>>>>>: G8
# lib_cnt:  3
# size   :  1
# v_atr  :  84 : G7
# libs   :  {96, 106, 84}
# H8, G9, G7,

b.place_stone(str2ev("G9")) # G9に石を置く
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  O  .  .  9
#  8 .  .  .  X  .  X  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
myShowSg("F9")
myShowSg("F7")
myShowSg("G8")
myShowSg("G9")
# >>>>>>>: F9
# lib_cnt:  0
# size   :  1
# v_atr  :  106 : G9
# libs   :  set()
# 
# >>>>>>>: F7
# lib_cnt:  2
# size   :  1
# v_atr  :  72 : F6
# libs   :  {72, 84}
# F6, G7,
# >>>>>>>: G8
# lib_cnt:  2
# size   :  1
# v_atr  :  84 : G7
# libs   :  {96, 84}
# H8, G7,
# >>>>>>>: G9
# lib_cnt:  3
# size   :  3
# v_atr  :  107 : H9
# libs   :  {96, 107, 84}
# H8, H9, G7,

b.play(str2ev("E8"))        # E8に石を置く(playモード) F8の石取れた!
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  O  .  .  9
#  8 .  .  .  X [O] .  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J

myShowSg("F9")
myShowSg("F7")
myShowSg("G8")
myShowSg("G9")
myShowSg("E8")
# >>>>>>>: F9
# lib_cnt:  0
# size   :  1
# v_atr  :  106 : G9
# libs   :  set()
# 
# >>>>>>>: F7
# lib_cnt:  3
# size   :  1
# v_atr  :  94 : F8
# libs   :  {72, 84, 94}
# F6, G7, F8,
# >>>>>>>: G8
# lib_cnt:  2
# size   :  1
# v_atr  :  84 : G7
# libs   :  {96, 84}
# H8, G7,
# >>>>>>>: G9
# lib_cnt:  4
# size   :  3
# v_atr  :  94 : F8
# libs   :  {96, 107, 84, 94}
# H8, H9, G7, F8,
# >>>>>>>: E8
# lib_cnt:  1
# size   :  1
# v_atr  :  94 : F8
# libs   :  {94}
# F8,

b.turn = 0
b.play(str2ev("H9"))        # E9に石を置く(playモード)
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  O [O] .  9
#  8 .  .  .  X  O  .  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J

myShowSg("F9")
myShowSg("F7")
myShowSg("G8")
myShowSg("G9")
myShowSg("E8")
myShowSg("H9")
# >>>>>>>: F9
# lib_cnt:  0
# size   :  1
# v_atr  :  106 : G9
# libs   :  set()
# >>>>>>>: F7
# lib_cnt:  3
# size   :  1
# v_atr  :  94 : F8
# libs   :  {72, 84, 94}
# F6, G7, F8,
# >>>>>>>: G8
# lib_cnt:  2
# size   :  1
# v_atr  :  84 : G7
# libs   :  {96, 84}
# H8, G7,
# >>>>>>>: G9
# lib_cnt:  4
# size   :  4
# v_atr  :  94 : F8
# libs   :  {96, 84, 108, 94}
# H8, G7, J9, F8,
# >>>>>>>: E8
# lib_cnt:  1
# size   :  1
# v_atr  :  94 : F8
# libs   :  {94}
# F8,
# >>>>>>>: H9
# lib_cnt:  2
# size   :  1
# v_atr  :  96 : H8
# libs   :  {96, 108}
# H8, J9,

b.turn = 0
b.play(str2ev("J9"))        # J9に石を置く(playモード) F8の石取れた!
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  X  O  O  O [O] 9
#  8 .  .  .  X  O  .  O  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J

myShowSg("F9")
myShowSg("F7")
myShowSg("G8")
myShowSg("G9")
myShowSg("E8")
myShowSg("H9")
myShowSg("J9")

# >>>>>>>: F9
# lib_cnt:  0
# size   :  1
# v_atr  :  106 : G9
# libs   :  set()
# 
# >>>>>>>: F7
# lib_cnt:  3
# size   :  1
# v_atr  :  94 : F8
# libs   :  {72, 84, 94}
# F6, G7, F8,
# >>>>>>>: G8
# lib_cnt:  2
# size   :  1
# v_atr  :  84 : G7
# libs   :  {96, 84}
# H8, G7,
# >>>>>>>: G9
# lib_cnt:  4
# size   :  5
# v_atr  :  94 : F8
# libs   :  {96, 97, 84, 94}
# H8, J8, G7, F8,
# >>>>>>>: E8
# lib_cnt:  1
# size   :  1
# v_atr  :  94 : F8
# libs   :  {94}
# F8,
# >>>>>>>: H9
# lib_cnt:  2
# size   :  1
# v_atr  :  96 : H8
# libs   :  {96, 108}
# H8, J9,
# >>>>>>>: J9
# lib_cnt:  1
# size   :  1
# v_atr  :  97 : J8
# libs   :  {97}
# J8,

7.3 この章でのまとめ

  • StoneGroupeのメンバ変数の内容を調べてみた
  • 取れるか否かのチェックに利用されているはず
  • 石のグループ全部が同じlibsになっておらず、グループの1つの座標が、そのグループの全体の情報を持っているようであった
  • StoneGroupeは取れる石の判定に利用されていると推測

8 Boardクラスのscore関数の調査

8.1 以下の操作を行っている動画


8.2 任意の盤を与えてお勧めの手をゲットする手順

8.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

8.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

8.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
ipython3                      #  ipython3起動

8.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
    ipython3                      #  ipython3起動
    

8.2.5 board.pyのBoardクラスに以下の関数を追加

  • scoreの内容を確認するための補助メソッド
  • score クラスの下あたりに追加がお勧め(Boardクラスのメソッドとして定義できてればOK)
  • 4つの要素をかえし、[Xの石の数、Oの石の数、空きの目でXのみ隣接している目の数, 空きの目でOのみ隣接している目の数, score関数と同じ答]を返す。
def bscore(self):
    stone_cnt = [0, 0, 0, 0, 0]
    for rv in range(BVCNT):
        v = rv2ev(rv)
        c = self.color[v]
        if c <= 1:
            stone_cnt[c] += 1
        else:
            nbr_cnt = [0, 0, 0, 0]
            for d in dir4:
                nbr_cnt[self.color[v + d]] += 1
            if nbr_cnt[0] > 0 and nbr_cnt[1] == 0:
                stone_cnt[0+2] += 1
            elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0:
                stone_cnt[1+2] += 1
    stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2]
    return stone_cnt

8.2.6 IPython内で以下を実行

  • 色々な盤面でscore関数、bscore関数を呼び出す
  • 下からすると、石がある目は、その石の陣営に+1, 石がない目は、周囲4方向に一方の陣営の石のみある場合その陣営に+1
  • 空き目で、周囲(上下4方向)に両方の陣営の石がある場合は、足さない
  • ハンデとして、board.py内のKOMIで設定(初期値-7.0)
from collections import Counter
import sys
from board import *
import gtp
import learn
import search
use_gpu = False

# ある座標のStoneGroupのメンバ変数の中身表示用関数
def myShowSg(x):
  print(">>>>>>>: "+x)
  print("lib_cnt: ", end=" ")
  print(b.sg[str2ev(x)].lib_cnt)
  print("size   : ", end=" ")
  print(b.sg[str2ev(x)].size)
  print("v_atr  : ", end=" ")
  print(str(b.sg[str2ev(x)].v_atr)+" : "+ev2str(b.sg[str2ev(x)].v_atr))
  print("libs   : ", end=" ")
  print(b.sg[str2ev(x)].libs)
  for i in b.sg[str2ev(x)].libs:
    print(ev2str(i), end=", ")
  print("")

b = Board()                 #ボード生成
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      # ([0, 0, 0, 0, -7.0], -7.0)

b.place_stone(str2ev("E7")) # E7に石を置く
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      # ([0, 1, 0, 4, -2.0], -2.0)

b.score()
b.place_stone(str2ev("F8")) # F8に石を置く
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  X  .  .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      # ([0, 2, 0, 6, 1.0], 1.0)

b.play(str2ev("D6"))        # D6に石を置く
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  X  .  .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  . [X] .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      # ([0, 3, 0, 8, 4.0], 4.0)

b.play(str2ev("G8"))        # G8に石を置
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  X [O] .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  X  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      #  ([1, 3, 3, 7, -1.0], -1.0)

b.play(str2ev("J8"))        # J8に石を置
b.showboard()               # ボードを表示
# この時点での盤の状態
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  X  O  . [X] 8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  X  .  .  .  .  .  6
#  5 .  .  .  .  .  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
(b.bscore(),b.score())      #  ([1, 4, 2, 9, 3.0], 3.0)

8.3 この章のまとめ

  • 点数計算方法の確認を、複数の盤面を作ってみて確認

9 Boardクラスのコピー

9.1 以下の操作を行っている動画


9.2 Boardクラスオブジェクトのコピーをする手順

9.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

9.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

9.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
ipython3                      #  ipython3起動

9.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    pip3 install tensorflow==1.4  #  古いバージョンに下げて、問題回避
    ipython3                      #  ipython3起動
    

9.2.5 IPython内で以下を実行

  • Boardオブジェクトb を Boardオブジェクトc にコピーするには、b.copy(c)で可能
from board import *

b=Board()
c=Board()

b.place_stone(str2ev("E7")) # E7に石を置く
b.copy(c)
b.showboard()               # ボードを表示

9.3 この章でのまとめ

  • ボードクラスのコピー方法について( bをcにコピーするなら、b.copy(c) で可能 )

10 幾つかの調査関数をBoardクラスのメンバ関数に組み込み

10.1 以下の操作を行っている動画


10.2 幾つかの調査関数をBoardクラスのメンバ関数に組み込む手順

10.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

10.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

10.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
# pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
# ipython3                      #  ipython3起動

10.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    # pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
    # ipython3                      #  ipython3起動
    

10.2.5 board.pyを編集

  • ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
  • Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
  1. Boardクラスのメンバ関数を追加
    • score関数の後に以下を追加する
    • bscore関数は前の章で追加したものと同じ、score関数内部の計算集計の詳細をゲットできる
    • myShowSg関数は指定した座標(strタイプ ex. “A1″)のStoneGroupeのメンバ変数の状態表示
    • myShowSgAll関数は、全ての石が置かれている目に対して、myShowSg関数を実行
    • listUpStoneEv関数は石が置かれているev値を配列にして返す(白石、黒石それぞれ)
    • listUpAtr関数は全ての盤面の石がおかれている所をチェックし、その目のStoneGroupのAtr値(あたり目かもしれない)をリストアップ。(その目が空の場合のみ集める)
    • listUpNeedCheckEvs関数は全ての盤面の石がおかれている所をチェックし、その目のStoneGroupのAtr値(あたり目かもしれない)をリストアップ。(StoneGroupeのlibsの数が1でその目が空の場合のみ集める)
    .....省略
        def bscore(self):
    .....省略
    	return stone_cnt[1] - stone_cnt[0] - KOMI
    
        def bscore(self):
    	stone_cnt = [0, 0, 0, 0, 0]
    	for rv in range(BVCNT):
    	    v = rv2ev(rv)
    	    c = self.color[v]
    	    if c <= 1:
    		stone_cnt[c] += 1
    	    else:
    		nbr_cnt = [0, 0, 0, 0]
    		for d in dir4:
    		    nbr_cnt[self.color[v + d]] += 1
    		if nbr_cnt[0] > 0 and nbr_cnt[1] == 0:
    		    stone_cnt[0+2] += 1
    		elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0:
    		    stone_cnt[1+2] += 1
    	stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2]
    	return stone_cnt
    
        def myShowSg(self, x):
    	print(">>>>>>>: "+x)
    	print("lib_cnt: ", end=" ")
    	print(self.sg[str2ev(x)].lib_cnt)
    	print("size   : ", end=" ")
    	print(self.sg[str2ev(x)].size)
    	print("v_atr  : ", end=" ")
    	print(str(self.sg[str2ev(x)].v_atr)+" : "+ev2str(self.sg[str2ev(x)].v_atr))
    	print("libs   : ", end=" ")
    	print(self.sg[str2ev(x)].libs)
    	for i in self.sg[str2ev(x)].libs:
    	  print(ev2str(i), end=", ")
    	print("")
    
        def myShowSgAll(self):
    	ans = [[],[]]
    	print("************ X ")
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 1:
    	    self.myShowSg(ev2str(v))
    	print("************ O ")
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 0:
    	    self.myShowSg(ev2str(v))
    
        def listUpStoneEv(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 0:
    	    ans[0].append(v)
    	  else:
    	    if c == 1:
    	      ans[1].append(v)
    	return ans
    
        def listUpAtr(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  v2 = self.sg[v].v_atr
    	  if self.color[v2]==2 :
    	    if c == 0:
    		ans[0].append(v2)
    	    else:
    	      if c == 1:
    		ans[1].append(v2)
    	return ans
    
        def listUpNeedCheckEvs(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  c2 = self.sg[v].lib_cnt
    	  if c2 == 1 :
    	    v2 = list(self.sg[v].libs)[0]
    	    if c == 0:
    		ans[0].append(v2)
    	    else:
    	      if c == 1:
    		ans[1].append(v2)
    	return ans
    .....省略
    

10.2.6 IPythonを起動

ipython3

10.2.7 IPython内で以下を実行

from board import *

b=Board()                   # ボードを作成

b.place_stone(str2ev("E5")) # E5に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [0, 1, 0, 4, -2.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# ************ O
# [[], [60]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.place_stone(str2ev("D6")) # D6に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [0, 2, 0, 6, 1.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# ************ O
# [[], [60, 70]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  X  .  .  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.place_stone(str2ev("F6")) # F6に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [0, 3, 0, 8, 4.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# >>>>>>>: F6
# lib_cnt:  4
# size   :  1
# v_atr  :  61 : F5
# libs   :  {73, 83, 61, 71}
# G6, F7, F5, E6,
# ************ O
# [[], [60, 70, 72]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  X  .  X  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.place_stone(str2ev("E7")) # E7に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [0, 4, 0, 9, 6.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# >>>>>>>: F6
# lib_cnt:  4
# size   :  1
# v_atr  :  61 : F5
# libs   :  {73, 83, 61, 71}
# G6, F7, F5, E6,
# >>>>>>>: E7
# lib_cnt:  4
# size   :  1
# v_atr  :  71 : E6
# libs   :  {81, 83, 93, 71}
# D7, F7, E8, E6,
# ************ O
# [[], [60, 70, 72, 82]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  X  .  X  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.turn=0
b.place_stone(str2ev("F7")) # E7に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [1, 4, 2, 8, 2.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# >>>>>>>: F6
# lib_cnt:  3
# size   :  1
# v_atr  :  61 : F5
# libs   :  {73, 61, 71}
# G6, F5, E6,
# >>>>>>>: E7
# lib_cnt:  3
# size   :  1
# v_atr  :  71 : E6
# libs   :  {81, 93, 71}
# D7, E8, E6,
# ************ O
# >>>>>>>: F7
# lib_cnt:  2
# size   :  1
# v_atr  :  94 : F8
# libs   :  {84, 94}
# G7, F8,
# [[83], [60, 70, 72, 82]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  X  .  X  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.place_stone(str2ev("G6")) # E7に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [2, 4, 4, 7, -2.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  4
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 61, 71}
# E4, D5, F5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# >>>>>>>: F6
# lib_cnt:  2
# size   :  1
# v_atr  :  61 : F5
# libs   :  {61, 71}
# F5, E6,
# >>>>>>>: E7
# lib_cnt:  3
# size   :  1
# v_atr  :  71 : E6
# libs   :  {81, 93, 71}
# D7, E8, E6,
# ************ O
# >>>>>>>: G6
# lib_cnt:  3
# size   :  1
# v_atr  :  62 : G5
# libs   :  {74, 84, 62}
# H6, G7, G5,
# >>>>>>>: F7
# lib_cnt:  2
# size   :  1
# v_atr  :  94 : F8
# libs   :  {84, 94}
# G7, F8,
# [[73, 83], [60, 70, 72, 82]]
# [[], []]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  X  .  X  O  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.place_stone(str2ev("F5")) # E7に石を置く
print(b.bscore())
b.myShowSgAll()
print(b.listUpStoneEv())
print(b.listUpNeedCheckEvs())
b.showboard()
# [3, 4, 5, 6, -5.0]
# ************ X
# >>>>>>>: E5
# lib_cnt:  3
# size   :  1
# v_atr  :  49 : E4
# libs   :  {49, 59, 71}
# E4, D5, E6,
# >>>>>>>: D6
# lib_cnt:  4
# size   :  1
# v_atr  :  59 : D5
# libs   :  {81, 59, 69, 71}
# D7, D5, C6, E6,
# >>>>>>>: F6
# lib_cnt:  1
# size   :  1
# v_atr  :  61 : F5
# libs   :  {71}
# E6,
# >>>>>>>: E7
# lib_cnt:  3
# size   :  1
# v_atr  :  71 : E6
# libs   :  {81, 93, 71}
# D7, E8, E6,
# ************ O
# >>>>>>>: F5
# lib_cnt:  2
# size   :  1
# v_atr  :  50 : F4
# libs   :  {50, 62}
# F4, G5,
# >>>>>>>: G6
# lib_cnt:  3
# size   :  1
# v_atr  :  62 : G5
# libs   :  {74, 84, 62}
# H6, G7, G5,
# >>>>>>>: F7
# lib_cnt:  2
# size   :  1
# v_atr  :  94 : F8
# libs   :  {84, 94}
# G7, F8,
# [[61, 73, 83], [60, 70, 72, 82]]
# [[], [71]]
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  X  .  X  O  .  .  6
#  5 .  .  .  .  X  O  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
print(ev2str(71))
# E6 
# E6に石を置けば取れる可能性があることをチェックできている 

10.3 この章でのまとめ

  • 幾つかの調査関数をBoardクラスの中に組み込んで使ってみた
  • StoneGroupの中身が調べやすくなった
  • アタリになっている可能性のあるev値のリストアップが出来た

11 playした時に取り除いた石のev値を保持するように改造

11.1 以下の操作を行っている動画


11.2 playした時に取り除いた石のev値を保持するように改造 する手順

11.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

11.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

11.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
# pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
# ipython3                      #  ipython3起動

11.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    # pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
    # ipython3                      #  ipython3起動
    

11.2.5 board.pyを編集

  • ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
  • Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
  1. Boardクラスに remove_ev_list を追加
    • self.remove_ev_list=[] を追加
    .....省略
    class Board(object):
    
        def __init__(self):
    	# 1-d array ([EBVCNT]) of stones or empty or exterior
    	# 0: white 1: black
    	# 2: empty 3: exterior
    	self.color = np.full(EBVCNT, 3)
    	self.sg = [StoneGroup() for _ in range(EBVCNT)]  # stone groups
    	self.clear()
    	self.remove_ev_list=[]
    
  2. Boardクラスの remove メソッドを以下に改造
    • print(“remove call:”str(v)“=”+ev2str(v)) 追加
    • print(“remove:”str(v_tmp)“=”+ev2str(v_tmp)) 追加
    • self.remove_ev_list.append(v_tmp) 追加
    .....省略
        def remove(self, v):
    	print("remove call:"+str(v)+"="+ev2str(v))
    	# remove stone group including stone at v
    	v_tmp = v
    	while 1:
    	    self.remove_cnt += 1
    	    self.color[v_tmp] = 2  # empty
    	    print("remove:"+str(v_tmp)+"="+ev2str(v_tmp))
    	    self.remove_ev_list.append(v_tmp)
    	    self.id[v_tmp] = v_tmp  # reset id
    	    for d in dir4:
    		nv = v_tmp + d
    		# add liberty to neighbor groups
    		self.sg[self.id[nv]].add(v_tmp)
    	    v_next = self.next[v_tmp]
    	    self.next[v_tmp] = v_tmp
    	    v_tmp = v_next
    	    if v_tmp == v:
    		break  # finish when all stones are removed
    
    

11.2.6 IPythonを起動

python3

11.2.7 IPython内で以下を実行

from board import *

b=Board()                   # ボードを作成

b.place_stone(str2ev("E5")) # E5に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("D6")) # D6に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("F6")) # F6に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("E7")) # E7に石を置く
print(b.remove_ev_list)
b.showboard()               # ボードを表示
# []
# []
# []
# []
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  .  .  .  .  7
#  6 .  .  .  X  .  X  .  .  .  6
#  5 .  .  .  .  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.turn=0
b.place_stone(str2ev("F7")) # E7に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("G6")) # G6に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("F5")) # F5に石を置く
print(b.remove_ev_list)
b.showboard()               # ボードを表示
# []
# []
# []
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  X  O  .  .  .  7
#  6 .  .  .  X  .  X  O  .  .  6
#  5 .  .  .  .  X  O  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.play(str2ev("E6"))        # F5に石を置く
print(b.remove_ev_list)     # 取り除いた石のEV値表示
print(ev2str(72))           # ev値72のstr形式は => F6

#####################
from board import *
b=Board()                   # ボードを作成
b.clear()                   # 盤の初期化
b.remove_ev_list.clear()    # b.remove_ev_listをクリア
print(b.remove_ev_list)
b.place_stone(str2ev("E5")) # E5に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("D5")) # D5に石を置く
b.showboard()               # ボードを表示
# []
# []
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  .  .  .  .  .  .  6
#  5 .  .  .  X  X  .  .  .  .  5
#  4 .  .  .  .  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.turn=0
b.place_stone(str2ev("C5")) # C5に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("D6")) # D6に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("E6")) # E6に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("F5")) # F5に石を置く
print(b.remove_ev_list)
b.place_stone(str2ev("D4")) # F5に石を置く
print(b.remove_ev_list)
b.showboard()               # ボードを表示
# []
# []
# []
# []
# []
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  .  .  .  .  .  7
#  6 .  .  .  O  O  .  .  .  .  6
#  5 .  .  O  X  X  O  .  .  .  5
#  4 .  .  .  O  .  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.play(str2ev("E4"))        # E4に石を置いてXを取る
print(b.remove_ev_list)     # 取った石のev値のリストゲット
# [59, 60]
for i in b.remove_ev_list:  #ev値はわかりにくいから、ループまわしてstr型に変換
  print(str(i)+":"+ev2str(i))
# 59:D5
# 60:E5

11.3 この章でのまとめ

  • 取り除いた石のev値のリストをゲットできるように改造してみた
  • 取る石が複数個でも上手く動いていることを確認

12 Boardクラスのメンバ関数拡張

12.1 以下の操作を行っている動画


12.2 Boardクラスのメンバ関数拡張 手順

12.2.1 イメージ起動

docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow

12.2.2 シェル起動

  • New から terminalを選択して、ターミナル起動

12.2.3 シェルで以下のコマンドを実行

sudo su - user
cd /tf/notebooks/Pyaq/Pyaq
cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
# pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
# ipython3                      #  ipython3起動

12.2.4 以前の章でPyaqのソースをゲットしてないなら

  1. ディレクトリ作成
    cd /tf/notebooks/
    sudo mkdir Pyaq
    
  2. 作成したPyaqディレクトリの所有権変更
    sudo chown user.user Pyaq
    cd Pyaq
    
  3. Pyaq ソースゲット
    git clone https://github.com/ymgaq/Pyaq.git
    
  4. Pyaq ソースゲット
    • GNU GLobalでソースを読みやすくしたHTMLファイル作成
    • ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
    cd Pyaq
    htags -afFIsngov --gtagslabel=pygments
    
    • 以下を実行し、IPython3を起動
    cd /tf/notebooks/Pyaq/Pyaq
    cp pre_train/model.ckpt .     # 学習済みモデルを利用できるように
    # pip3 install tensorflow==1.4  #  AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避
    # ipython3                      #  ipython3起動
    

12.2.5 board.pyを編集

  • ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
  • Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
  1. Boardクラスのメンバ関数を追加
    • 前の章の石を取り除いたものをremove_ev_listにいれる修正もした方が良いhttps://www.youtube.com/embed/CbW21FVp_yc
    • Boardクラスのscore関数の定義の後に以下を追加
    • 昔の章で追加した関数も含まれているので、昔のboardクラスにメンバ関数を追加された方は def listUpLibsEvs(self): 以下を追加してください。
    • listUpLibsEvsは石のある目のStoneGroupeのlibsを集めて返す関数
    • filterEmpty(self,listorset) は listorset のev値が空の時(2)のものだけフィルターしてリストでかえす
    • getDeadStonesEv(self,ev) は ev値に石を置いた時に取れる石のev値を返す
    • place_stones(self,evs) は、evsにstr形式で与えた目に石を置く関数(ルール上置けない場所には置けない)
    • place_stones10(self,evs1,evs0) は X(先手)の目をevs1に O(後手)の目をevs0に置く
    • place_stones01(self,evs0,evs1) は O(後手)の目をevs0に置く は X(先手)の目をevs1に置く(置く順番が異なる)
    • evs2strs(self,evs) は evの配列等を、str形式の配列で返す
    .....省略
        def bscore(self):
    	stone_cnt = [0, 0, 0, 0, 0]
    	for rv in range(BVCNT):
    	    v = rv2ev(rv)
    	    c = self.color[v]
    	    if c <= 1:
    		stone_cnt[c] += 1
    	    else:
    		nbr_cnt = [0, 0, 0, 0]
    		for d in dir4:
    		    nbr_cnt[self.color[v + d]] += 1
    		if nbr_cnt[0] > 0 and nbr_cnt[1] == 0:
    		    stone_cnt[0+2] += 1
    		elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0:
    		    stone_cnt[1+2] += 1
    	stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2]
    	return stone_cnt
    
        def myShowSg(self, x):
    	print(">>>>>>>: "+x)
    	print("lib_cnt: ", end=" ")
    	print(self.sg[str2ev(x)].lib_cnt)
    	print("size   : ", end=" ")
    	print(self.sg[str2ev(x)].size)
    	print("v_atr  : ", end=" ")
    	print(str(self.sg[str2ev(x)].v_atr)+" : "+ev2str(self.sg[str2ev(x)].v_atr))
    	print("libs   : ", end=" ")
    	print(self.sg[str2ev(x)].libs)
    	for i in self.sg[str2ev(x)].libs:
    	  print(ev2str(i), end=", ")
    	print("")
    
        def myShowSgAll(self):
    	ans = [[],[]]
    	print("************ X ")
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 1:
    	    self.myShowSg(ev2str(v))
    	print("************ O ")
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 0:
    	    self.myShowSg(ev2str(v))
    
    
        def listUpStoneEv(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 0:
    	    ans[0].append(v)
    	  else:
    	    if c == 1:
    	      ans[1].append(v)
    	return ans
    
        def listUpAtr(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  v2 = self.sg[v].v_atr
    	  if self.color[v2]==2 :
    	    if c == 0:
    		ans[0].append(v2)
    	    else:
    	      if c == 1:
    		ans[1].append(v2)
    	return ans
    
        def listUpNeedCheckEvs(self):
    	ans = [[],[]]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  c2 = self.sg[v].lib_cnt
    	  if c2 == 1 :
    	    v2 = list(self.sg[v].libs)[0]
    	    if c == 0:
    		ans[0].append(v2)
    	    else:
    	      if c == 1:
    		ans[1].append(v2)
    	return ans
    
        def listUpLibsEvs(self):
    	ans = [set([]),set([])]
    	for rv in range(BVCNT):
    	  v = rv2ev(rv)
    	  c = self.color[v]
    	  if c == 0 or c == 1:
    	    ans[c] = ans[c] | self.sg[v].libs
    	ans=[set(self.filterEmpty(ans[0])),set(self.filterEmpty(ans[1]))]
    	ans.append(ans[0]|ans[1]) 
    	return ans
    
        def filterEmpty(self,listorset):
    	ans=[]
    	for v in listorset:
    	  c = self.color[v]
    	  if c == 2 :
    	    ans.append(v)
    	return ans
    
        def getDeadStonesEv(self,ev):
    	c=Board()
    	self.copy(c)
    	ans1=c.legal(ev)
    	c.play(ev)
    	return (ans1,c.remove_ev_list)
    
        def place_stones(self,evs):
    	for v in evs:
    	  self.place_stone(str2ev(v))
    
        def place_stones10(self,evs1,evs0):
    	orgturn=self.turn
    	self.turn=1
    	self.place_stones(evs1)
    	self.turn=0
    	self.place_stones(evs0)
    	self.turn=self.turn
    
        def place_stones01(self,evs0,evs1):
    	orgturn=self.turn
    	self.turn=0
    	self.place_stones(evs0)
    	self.turn=1
    	self.place_stones(evs1)
    	self.turn=self.turn
    
        def evs2strs(self,evs):
    	ans=[]
    	for v in evs:
    	  ans.append(ev2str(v))
    	return ans
    
    .....省略
    

12.2.6 IPythonを起動

ipython3

12.2.7 IPython内で以下を実行

from board import *

b=Board()                       # ボードを作成
b.place_stones10(["E5","E6"],["E7","D6","D5","E4","F6"])  # 石を置く
# F5に石を置いたら、どこが取れるか (True, [60, 71])
# 最初のTrueは置ける場所を示す
b.getDeadStonesEv(str2ev("F5")) 
# F5に石を置いたら、どこが取れるかをstr形式で ['E5', 'E6']
b.evs2strs(b.getDeadStonesEv(str2ev("F5"))[1]) 
b.showboard()               # ボードを表示
#    A  B  C  D  E  F  G  H  J
#  9 .  .  .  .  .  .  .  .  .  9
#  8 .  .  .  .  .  .  .  .  .  8
#  7 .  .  .  .  O  .  .  .  .  7
#  6 .  .  .  O  X  O  .  .  .  6
#  5 .  .  .  O  X  .  .  .  .  5
#  4 .  .  .  .  O  .  .  .  .  4
#  3 .  .  .  .  .  .  .  .  .  3
#  2 .  .  .  .  .  .  .  .  .  2
#  1 .  .  .  .  .  .  .  .  .  1
#    A  B  C  D  E  F  G  H  J
b.turn                      # 手番確認 => 0
b.turn=1
b.getDeadStonesEv(str2ev("F5")) # F5にXをおいても取れない => (True, [])
b.listUpLibsEvs()               # 石に上下で隣接してて置ける場所をリストアップ
# [{38, 48, 50, 58, 61, 69, 73, 81, 83, 93},
#  {61},
#  {38, 48, 50, 58, 61, 69, 73, 81, 83, 93}]
b.evs2strs(b.listUpLibsEvs()[2]) # 石に隣接している空の目の座標をstr形式に変換
# ['C6', 'E3', 'G6', 'D4', 'D7', 'F4', 'F7', 'F5', 'C5', 'E8']

12.3 この章でのまとめ

  • Boardクラスのメンバ関数の拡張を行った
  • 事前に取れる石のチェックを出来るようになった

13 今後

  • こんぱ今後も文書追加していきます。

14 この文書のチェンジログ

  • 2020/02/03 初版
  • 2020/02/05 Boardクラスの調査2の章を追加
  • 2020/02/09 評価関数で、好きな盤の状態を評価させてみた の章追加
  • 2020/02/10 任意の盤を与えてお勧めの手をゲット の章追加
  • 2020/03/05 Groupクラスの調査 の章追加
  • 2020/03/06 Boardクラスのscore関数の調査 の章追加
  • 2020/03/06 Boardクラスのコピー方法について調査 の章追加
  • 2020/03/13 幾つかの調査関数をBoardクラスのメンバ関数に組み込み の章追加
  • 2020/03/14 playした時に取り除いた石のev値を保持するように改造 の章追加
  • 2020/03/14 Boardクラスのメンバ関数拡張 の章追加
  • 2020/03/15 Boardクラスのメンバ関数拡張2(わかりやすいStoneGroup機能追加) の章追加
  • 2020/04/04 Boardクラスのメンバ関数拡張2(わかりやすいStoneGroup機能追加) の章削除(バグがありました)

著者: NM Max

Created: 2020-04-04 土 20:52

Validate