目次
練習編
📖 目指せ!第14回UEC杯コンピューター囲碁大会<練習編>
本編
📖 Step [O1o0] 導入
📖 Step [O11o___100o0] カーネル作成 ~ Step [O11o__10o_1o0] 思考エンジン設定ファイル
📖 Step [O11o__10o0] ロガー設定 ~ Step [O11o__10o3o_2o0] welcome プログラム
📖 Step [O11o__11o0] デバッグ可能標準入力 作成
📖 Step [O11o_3o_10o0] ゲームルール作成
📖 Step [O11o_3o_11o0] ポジション作成
📖 Step [O11o_3o0] カーネルのインタープリター
📖 Step [O11o_4o0] 石の色定義
📖 Step [O11o_4o2o0] 連の定義
📖 Step [O11o_5o0] 石定義
📖 Step [O12o__10o0] 点定義、またはその盤座標符号定義
📖 Step [O12o__11o__100o0] データファイル作成 ~ Step [O12o__11o__10o0] 連データベース定義 ~ Step [O12o__11o__10o5o__10o0] 連データベースのロード
📖 Step [O12o__11o_1o0] 棋譜定義
📖 Step [O12o__11o0] 盤定義(土台)
📖 Step [O12o_1o0] 盤定義(盤面走査)
📖 Step [O13o_1o0] 盤表示
📖 Step [O15o__10o0] 盤サイズの変更
📖 Step [O15o__14o_1o0] データファイル作成
📖 Step [O15o__14o0] 初期盤面を設定する
📖 Step [O15o_1o0] 座標の定義
📖 Step [O19o_1o0] 石を打つ
📖 Step [O22o_1o0] データファイル作成
📖 Step [O22o1o0] 空点以外のところ(石または枠の上)に石を置くことの禁止
📖 Step [O22o2o0] 連の認識と、呼吸点のカウント
📖 Step [O22o3o0] 相手の眼に石を置くことの禁止
📖 Step [O22o4o0] 自分の眼に石を置くことの任意の禁止
📖 Step [O22o5o0] 任意の連の打ち上げ
📖 Step [O22o6o0] 死に石の連の打ち上げ
📖 Step [O22o7o0] コウの禁止
Step [O23o_1o0] データファイル作成 - data/board4.txt ファイル
あとで使うファイルを先に作成する
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ ├── 📄 board3.txt
👉 │ └── 📄 board4.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ ├── 📄 kernel_facade.go
│ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
A B C D E F G H J K L M N O P Q R S T
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1 + x . x x x . . . . . . . . . x x x . x +
2 + . . . . . . . . . . . . . . . . . . . +
3 + x . x x x x x . o o o . . . . . . . x +
4 + x . x . . . x . o o o x x x . . . . x +
5 + x . x . x . x . o o o x o x . . . . x +
6 + . . x x x . x . . . . x . x . . . . . +
7 + . . . . . . x . . . . x x x . . . . . +
8 + . . x x x x x . . . . . . o o o o o . +
9 + . . . . . . . . . . . . . o . o . o . +
10 + o o o o o o o o o o o o o o o o o o o +
11 + . . . . . . . x . . x . . . . . . . . +
12 + . . . . . o . x x . x . x x x x x . . +
13 + . . . . o x o . x x x . x . . . . . . +
14 + . . . o x . x o . . . . x . x x x . . +
15 + x . o x . . . x o . . . x . x . x . x +
16 + x . . o x . x o . . . . x . . . x . x +
17 + x . . . o x o . . . . . x x x x x . x +
18 + . . . . . o . . . . . . . . . . . . . +
19 + x . x x x . . . . . . . . . x x x . x +
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Step [O23o_2o0] 盤上の連のスキャン
石を打つ
ことを実装できたなら、呼吸点を調べるアルゴリズムも実装されていて、
着手点に隣接する上下左右にある石の連の認識はできているはずだ
次は、盤面全体に点在する連を認識できるか試したい
Step [O23o_2o1o0] ファイル編集 - kernel_facade.go
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ ├── 📄 board3.txt
│ └── 📄 board4.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
👉 │ ├── 📄 kernel_facade.go
│ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
👇 がんばって以下を追加してほしい
// ...略...
// FindAllRens - [O23o_2o1o0] 盤上の全ての連を見つけます
// * 見つけた連は、連データベースへ入れます
func (k *Kernel) FindAllRens() {
// チェックボードの初期化
k.Position.CheckBoard.Init(k.Position.Board.coordinate)
var maxPosNthFigure = k.Record.GetMaxPosNthFigure()
var setLocation = func(location Point) {
var libertySearchAlgorithm = NewLibertySearchAlgorithm(k.Position.Board, k.Position.CheckBoard)
var ren, isFound = libertySearchAlgorithm.findRen(location)
if isFound {
k.renDb.RegisterRen(maxPosNthFigure, k.Record.positionNumber, ren)
}
}
// 盤上の枠の内側をスキャン。筋、段の順
k.Position.Board.GetCoordinate().ForeachPayloadLocationOrderByYx(setLocation)
}
// ...略...
Step [O23o_2o2o0] コマンド編集 - kernel.go ファイル
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ ├── 📄 board3.txt
│ └── 📄 board4.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ ├── 📄 kernel_facade.go
👉 │ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
👇 がんばって、 Execute メソッドに挿入してほしい
// ...略...
// この下にコマンドを挟んでいく
// -------------------------
// ...略...
// * アルファベット順になる位置に、以下のケース文を挿入
case "find_all_rens": // [O23o_2o2o0]
// Example: `find_all_rens`
k.FindAllRens()
logg.C.Infof("=\n")
logg.J.Infow("ok")
return true
// ...略...
// この上にコマンドを挟んでいく
// -------------------------
// ...略...
Step [O23o_2o3o_1o0] ファイル編集 - board_set.go
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ ├── 📄 board3.txt
│ └── 📄 board4.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
👉 │ ├── 📄 board_set.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ ├── 📄 kernel_facade.go
│ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
👇 がんばって以下を追加してほしい
// ...略...
// func (k *Kernel) DoSetBoard(command string, logg *Logger) {
// if tokens[1] == "file" {
// ...略...
// if int(i) != size {
// logg.C.Infof("? not enough size i:%d size:%d\n", i, size)
// logg.J.Infow("error not enough size", "i", i, "size", size)
// return
// }
// * 以下を追加
// [O23o_2o3o_1o0] 連データベース初期化
k.renDb.Init(k.Position.Board.GetWidth(), k.Position.Board.GetHeight())
k.FindAllRens()
// }
// }
// ...略...
Step [O23o_2o3o0] 動作確認
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
go run .
これで、思考エンジン内の入力待機ループに入った
👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい
Input:
board_set file data/board4.txt
rendb_dump
find_all_rens
rendb_dump
rendb_save data/ren_db_board4_temp.json
Output > Console:
[2022-09-18 23:58:02] # board_set file data/board4.txt
[2022-09-18 23:58:02] =
[2022-09-18 23:58:51] # find_all_rens
[2022-09-18 23:58:51] =
Step [O23o_2o4o0] TODO 出力ファイルの内容の盤表示
Step [O23o_2o4o1o0] ファイル編集 - kernel.go ファイル
👇 以下の既存ファイルを編集してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ ├── 📄 board3.txt
│ └── 📄 board4.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
│ ├── 📄 board_set.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ ├── 📄 kernel_facade.go
👉 │ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
TODO 📄 ren_db1_temp.json
ファイルを読み込む
TODO 連データベースには「何手目」の「どの連」という形で項目がいくつもある。その全項目をコンソールへ盤表示
Step [O23o_2o4o2o0]
TODO FIXME rendb_dump の結果が全部空っぽ?
📄 .vscode/launch.json:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"args" : ["-d=true"]
}
]
}
📄 debug.input.txt:
rendb_load data/ren_db_board4.json
rendb_dump
rendb_load data/ren_db_board4.json
find_all_rens
rendb_dump
Step [O23o_3o0] TODO 石を打った後の連の再スキャン
Step [O23o0] 打った石のアンドゥ - Undo
打った石をやっぱり止める、一手戻す、ということは、石を打つよりも実装がむずかしい
Step [O23o1o0] ファイル作成 - play_undo.go
👇 以下のファイルを新規作成してほしい
📂 kifuwarabe-uec14
├── 📂 data
│ ├── 📄 board1.txt
│ ├── 📄 board2.txt
│ └── 📄 board3.txt
├── 📂 kernel
│ ├── 📂 play_rule
│ ├── 📄 board_area.go
│ ├── 📄 board_coord.go
│ ├── 📄 o12o__11o1o0_board.go
│ ├── 📄 check_board.go
│ ├── 📄 color.go
│ ├── 📄 go.mod
│ ├── 📄 go.sum
│ ├── 📄 kernel_facade.go
│ ├── 📄 kernel.go
│ ├── 📄 liberty.go
│ ├── 📄 logger.go
│ ├── 📄 masonry.go
👉 │ ├── 📄 play_undo.go
│ ├── 📄 play.go
│ ├── 📄 o12o__10o1o0_point.go
│ ├── 📄 record_item.go
│ ├── 📄 record.go
│ ├── 📄 ren.go
│ └── 📄 stone.go
├── 📄 .gitignore
├── 📄 engine_config.go
├── 📄 engine.toml
├── 📄 go.mod
├── 📄 go.work
└── 📄 main.go
// BOF [O23o1o0]
package kernel
// DoUndoPlay - 石を打ったのを戻す
//
// * `command` - Example: `undo`
// ........................----
// ........................0
func (k *Kernel) DoUndoPlay(command string, logg *Logger) {
k.UndoPlay()
}
// UndoPlay - 石を打ったのを戻す
//
// Returns
// -------
// isOk : bool
//
// 石を置けたら真、置けなかったら偽
func (k *Kernel) UndoPlay() bool {
// 初期局面から前には戻せない
if k.Record.GetPositionNumber() < 1 {
return false
}
return false
}
// EOF [O23o1o0]
TODO 東、北、西、南に隣接する連を重複して数えないように常に注意すること
TODO 棋譜に取った石を記録する
TODO 取った石を戻す
TODO アンドゥ
参考にした記事
Go言語
ファイル分割
コマンドライン引数
列挙型
📖 How to make Go print enum fields as string?
出力
可変長引数
📖 Concatenating and Building Strings in Go 1.10+
📖 Convert interface to string
文字列
📖 Go: 1文字ずつアクセスする
📖 Golang String Padding Example
配列
📖 スライス操作(要素の追加・削除, ソート, 他のスライスと結合)
ファイル入出力
JSON
📖 Goにおけるjsonの扱い方を整理・考察してみた ~ データスキーマを添えて
コレクション
ハッシュテーブル
📖 [Go言語] 初心者必見シリーズ: マップ(Map)
📖 Go言語: マップのキーが存在するかチェックしたい
ビット演算
📖 Goのビット演算について
📖 How to define bit literals in Go?
数学
デバッギング
📖 標準入力のあるプログラムを delve でデバッグしたい
.