LoginSignup
0
0

More than 1 year has passed since last update.

目指せ!第14回UEC杯コンピューター囲碁大会<本編> Step [O12o__11o__100o0] データファイル作成 ~ Step [O12o__11o__10o0] 連データベース定義 ~ Step [O12o__11o__10o5o__10o0] 連データベースのロード

Last updated at Posted at 2022-09-27

目指せ!第14回UEC杯コンピューター囲碁大会<本編> Step [O12o__11o__100o0] データファイル作成 ~ Step [O12o__11o__10o0] 連データベース定義 ~ Step [O12o__11o__10o5o__10o0] 連データベースのロード

連載の目次

📖 目指せ!第14回UEC杯コンピューター囲碁大会<本編>

Step [O12o__11o__100o0] データファイル作成 - data/ren_db1.json ファイル

あとで使うファイルを先に作成する

👇 以下のファイルを新規作成してほしい

  	📂 kifuwarabe-uec14
	├── 📂 data
👉 	│	└── 📄 ren_db1.json
	├── 📂 kernel
	│	├── 📄 go.mod
 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go
{
    "header": {
        "boardWidth": 19,
        "boardHeight": 19
    },
    "rens": {
        "001,01A": {
            "stone": "x",
            "locate": "A1",
            "liberty": "B1 A2"
        },
        "001,06N": {
            "stone": ".",
            "locate": "N6",
            "liberty": ""
        },
        "001,13E": {
            "stone": "o",
            "locate": "E13",
            "liberty": "E12 D13"
        }
    }
}

Step [O12o__11o__101o0]

Removed

Step [O12o__11o__10o0] 連データベース定義

  • 取った石の場所を記憶しておく構造を作成する
  • 入出力ファイルの構造でもある

📖 目指せ!第14回UEC杯コンピューター囲碁大会☆(^q^)<その4>

Step [O12o__11o__10o1o0]

Removed

Step [O12o__11o__10o2o0] ファイル作成 - ren_db.go ファイル

👇 以下のファイルを新規作成してほしい

  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
	│	├── 📄 o12o__10o1o0_point.go
	│	├── 📄 ren_db_item.go
👉	│	├── 📄 ren_db.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go
// BOF [O12o__11o__10o2o0]

package kernel

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

// RenId - 連データベースに格納される連のId
// * 外部ファイルの可読性を優先して数値型ではなく文字列
type RenId string

// GetRenId - 連のIdを取得
func GetRenId(boardMemoryWidth int, positionNthFigure int, positionNumber int, minimumLocation Point) RenId {
	var posNth = positionNumber + geta
	var coord = getRenIdFromPointOnBoard(boardMemoryWidth, minimumLocation)

	return RenId(fmt.Sprintf("%0*d,%s", positionNthFigure, posNth, coord))
}

// RenDb - 連データベース
type RenDb struct {
	// Header - ヘッダー
	Header RenDbDocHeader `json:"header"`

	// 要素
	Rens map[RenId]*Ren `json:"rens"`
}

// NewRenDb - 連データベースを新規作成
func NewRenDb(boardWidth int, boardHeight int) *RenDb {
	var db = new(RenDb)
	db.Header.Init(boardWidth, boardHeight)
	db.Rens = make(map[RenId]*Ren)
	return db
}

// Init - 初期化
func (db *RenDb) Init(boardWidth int, boardHeight int) {
	db.Header.Init(boardWidth, boardHeight)

	// Clear
	for ri := range db.Rens {
		delete(db.Rens, ri)
	}
}

// Save - 連データベースの外部ファイル書込
func (db *RenDb) Save(path string, convertLocation func(Point) string, onError func(error) bool) bool {

	// 外部ファイルに出力するための、内部状態の整形
	db.RefreshToExternalFile(convertLocation)

	// Marshal関数でjsonエンコード
	// ->返り値jsonDataにはエンコード結果が[]byteの形で格納される
	jsonBinary, errA := json.Marshal(db)
	if errA != nil {
		return onError(errA)
	}

	// ファイル読込
	var errB = os.WriteFile(path, jsonBinary, 0664)
	if errB != nil {
		return onError(errB)
	}

	return true
}

// FindRen - 連を取得
func (db *RenDb) GetRen(renId RenId) (*Ren, bool) {
	var ren, isOk = db.Rens[renId]

	if isOk {
		return ren, true
	}

	return nil, false
}

// RegisterRen - 連を登録
// * すでに Id が登録されているなら、上書きしない
func (db *RenDb) RegisterRen(positionNthFigure int, positionNumber int, ren *Ren) {
	var renId = GetRenId(db.Header.GetBoardMemoryWidth(), positionNthFigure, positionNumber, ren.minimumLocation)

	var _, isExists = db.Rens[renId]
	if !isExists {
		db.Rens[renId] = ren
	}
}

// Dump - ダンプ
func (db *RenDb) Dump() string {
	var sb strings.Builder

	// 全ての要素
	for idStr, item := range db.Rens {
		sb.WriteString(fmt.Sprintf("[%s]%s ", idStr, item.Dump()))
	}

	var text = sb.String()
	if 0 < len(text) {
		text = text[:len(text)-1]
	}
	return text
}

// RefreshToExternalFile - 外部ファイルに出力されてもいいように内部状態を整形します
func (db *RenDb) RefreshToExternalFile(convertLocation func(Point) string) {
	for _, ren := range db.Rens {
		ren.RefreshToExternalFile(convertLocation)
	}
}

// RenDbDocHeader - ヘッダー
type RenDbDocHeader struct {
	// BoardWidth - 盤の横幅
	BoardWidth int `json:"boardWidth"`
	// BoardHeight - 盤の縦幅
	BoardHeight int `json:"boardHeight"`
}

// Init - 初期化
func (h *RenDbDocHeader) Init(boardWidth int, boardHeight int) {
	h.BoardWidth = boardWidth
	h.BoardHeight = boardHeight
}

// GetBoardMemoryArea - 枠付き盤の面積
func (h *RenDbDocHeader) GetBoardMemoryArea() int {
	return h.GetBoardMemoryWidth() * h.GetBoardMemoryHeight()
}

// GetBoardMemoryWidth - 枠付き盤の横幅
func (h *RenDbDocHeader) GetBoardMemoryWidth() int {
	return h.BoardWidth + bothSidesWallThickness
}

// GetBoardMemoryHeight - 枠付き盤の縦幅
func (h *RenDbDocHeader) GetBoardMemoryHeight() int {
	return h.BoardHeight + bothSidesWallThickness
}

// EOF [O12o__11o__10o2o0]

Step [O12o__11o__10o3o0] ファイル編集 - kernel.go ファイル

👇 以下の既存ファイルを編集してほしい

  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
👉 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
	│	├── 📄 o12o__10o1o0_point.go
	│	├── 📄 ren_db_item.go
	│	├── 📄 ren_db.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go
// ...略...
// type Kernel struct {
	// ...略...

	// * 以下を追加
	// RenDb - [O12o__11o__10o3o0] 連データベース
	renDb *RenDb
// }
// ...略...

// func NewDirtyKernel(boardWidht int, boardHeight int,
	// ...略...

	// * 以下を追加
	// RenDb - [O12o__11o__10o3o0] 連データベース
	k.renDb = NewRenDb(k.Position.Board.coordinate.GetWidth(), k.Position.Board.coordinate.GetHeight())

//	return k
// }
// ...略...

Step [O12o__11o__10o4o0] コマンド編集 - kernel.go ファイル

👇 以下の既存ファイルを編集してほしい

  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
👉 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
	│	├── 📄 o12o__10o1o0_point.go
	│	├── 📄 ren_db_item.go
	│	├── 📄 ren_db.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go

👇 がんばって、 Execute メソッドに挿入してほしい

	// ...略...
	// この下にコマンドを挟んでいく
	// -------------------------
	// ...略...

	// * アルファベット順になる位置に、以下のケース文を挿入
	case "rendb_dump": // [O12o__11o__10o4o0]
		var text = k.renDb.Dump()
		logg.C.Info("= dump'''%s\n'''\n", text)
		logg.J.Infow("ok", "dump", text)
		return true

	case "rendb_save": // [O12o__11o__10o4o0]
		// Example: `rendb_save data/ren_db1_temp.json`
		// * ファイルパスにスペースがはいっていてはいけない
		var path = tokens[1]

		var convertLocation = func(location Point) string {
			return k.Position.Board.coordinate.GetGtpMoveFromPoint(location)
		}

		var onError = func(err error) bool {
			logg.C.Infof("? error:%s\n", err)
			logg.J.Infow("error", "err", err)
			return false
		}

		var isOk = k.renDb.Save(path, convertLocation, onError)
		if isOk {
			logg.C.Infof("=\n")
			logg.J.Infow("ok")
			return true
		}

		return false

	// ...略...
	// この上にコマンドを挟んでいく
	// -------------------------
	// ...略...

Step [O12o__11o__10o5o__10o0] 連データベースのロード

連データベースをロードするには、盤のサイズも、連も既知でないといけない
盤のサイズ、連の定義を終えた段階で、連データベースのロードを実装する

Step [O12o__11o__10o5o__10o_10o0] ファイル作成 - kernel/kernel_facade.go ファイル

👇 以下のファイルを新規作成してほしい

  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
👉 	│	├── 📄 kernel_facade.go
 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
	│	├── 📄 o12o__10o1o0_point.go
	│	├── 📄 ren_db_item.go
	│	├── 📄 ren_db.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go
// BOF [O12o__11o__10o5o__10o0]

package kernel

import (
	"encoding/json"
	"os"
)

// LoadRenDb - [O12o__11o__10o5o__10o_10o0] 連データベースの外部ファイル読取
func (k *Kernel) LoadRenDb(path string, onError func(error) bool) bool {
	// ファイル読込
	var binary, errA = os.ReadFile(path)
	if errA != nil {
		return onError(errA)
	}

	var db = new(RenDb)
	var errB = json.Unmarshal(binary, db)
	if errB != nil {
		return onError(errB)
	}

	// 外部ファイルからの入力を、内部状態へ適用
	for _, ren := range db.Rens {
		var isOk = k.RefreshRenToInternal(ren)
		if !isOk {
			return false
		}
	}

	// 差し替え
	k.renDb = db
	return true
}

// RefreshRenToInternal - TODO 外部ファイルから入力された内容を内部状態に適用します
func (k *Kernel) RefreshRenToInternal(r *Ren) bool {
	{
		var getDefaultStone = func() (bool, Stone) {
			panic(fmt.Sprintf("unexpected stone:%s", r.Sto))
		}

		// TODO stone from r.Sto
		// Example: "x" --> black
		var isOk, stone = GetStoneFromChar(r.Sto, getDefaultStone)
		if !isOk {
			return false
		}
		r.stone = stone
	}
	{
		// TODO locations from r.Loc
		// Example: "C1 D1 E1"
		if 0 < len(r.Loc) {
			var codes = strings.Split(r.Loc, " ")

			var numbers = []Point{}
			for _, code := range codes {
				var location = k.Position.Board.coordinate.GetPointFromGtpMove(code)
				numbers = append(numbers, location)
			}

			r.locations = numbers
		}
	}
	{
		// TODO libertyLocations from r.LibLoc
		// Example: "F1 E2 D2 B1 C2"
		if 0 < len(r.LibLoc) {
			var codes = strings.Split(r.LibLoc, " ")

			var numbers = []Point{}
			for _, code := range codes {
				var location = k.Position.Board.coordinate.GetPointFromGtpMove(code)
				numbers = append(numbers, location)
			}

			r.libertyLocations = numbers
		}
	}

	return true
}

// EOF [O12o__11o__10o5o__10o0]

Step [O12o__11o__10o5o__10o1o0] コマンド編集 - kernel.go ファイル

👇 以下の既存ファイルを編集してほしい

  	📂 kifuwarabe-uec14
	├── 📂 kernel
	│	├── 📄 go.mod
👉 	│	├── 📄 kernel.go
 	│	├── 📄 logger.go
	│	├── 📄 o12o__10o1o0_point.go
	│	├── 📄 ren_db_item.go
	│	├── 📄 ren_db.go
 	│	└── 📄 stone.go
    ├── 📄 .gitignore
 	├── 📄 engine_config.go
  	├── 📄 engine.toml
    ├── 📄 go.mod
  	├── 📄 go.work
  	└── 📄 main.go
	// ...略...

	// この下にコマンドを挟んでいく
	// -------------------------
	// ...略...

	case "rendb_load": // [O12o__11o__10o5o__10o1o0]
		// Example: `rendb_load data/ren_db1_temp.json`
		// * ファイルパスにスペースがはいっていてはいけない
		var path = tokens[1]
		var onError = func(err error) bool {
			logg.C.Infof("? error:%s\n", err)
			logg.J.Infow("error", "err", err)
			return false
		}

		var isOk = k.LoadRenDb(path, onError)
		if isOk {
			logg.C.Infof("=\n")
			logg.J.Infow("ok")
			return true
		}
		return false

	// ...略...

	// この上にコマンドを挟んでいく
	// -------------------------
	// ...略...

Step [O12o__11o__10o5o_1o0] 設定 - .gitignore ファイル

👇 以下の既存ファイルを編集してほしい

  	📂 kifuwarabe-uec14
👉  └── 📄 .gitignore

👇 例えば冒頭に追加

# この下に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
# ...略...

# [O12o__11o__10o5o_1o0]
*_temp.json

# この上に kifuwarabe-uec14 でリポジトリにコミットしないものを追加する
# ---------------------------------------------------------------
# ...略...

Step [O12o__11o__10o5o0] 動作確認

👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい

Input:

go run .

これで、思考エンジン内の入力待機ループに入った

👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい

Input:

rendb_load data/ren_db1.json

Output > Console:

[2022-09-18 21:21:15]   # rendb_load data/ren_db1.json
[2022-09-18 21:21:15]   =

👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい

Input:

rendb_dump

Output > Console:

[2022-09-25 22:22:44]   # rendb_dump
[2022-09-25 22:22:44]   = dump'''[001,01A]22
[001,06N]139
[001,13E]278
'''

👇 以下のコマンドをコピーして、ターミナルに貼り付けてほしい

Input:

rendb_save data/ren_db1_temp.json

Output > Console:

[2022-09-18 22:15:43]   # rendb_save data/ren_db1_temp.json
[2022-09-18 22:15:43]   =

📄 ren_db1_temp.json:

{"header":{"boardWidth":19,"boardHeight":19},"rens":{"001,01A":{"stone":".","locate":"","liberty":""},"001,06N":{"stone":".","locate":"","liberty":""},"001,13E":{"stone":".","locate":"","liberty":""}}}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0