# QuoridorAI 仕様 Repository: [![grkon03/Quoridor-AI - GitHub](https://gh-card.dev/repos/grkon03/Quoridor-AI.svg)](https://github.com/grkon03/Quoridor-AI) ## 必要なクラス(型) - SquareEdge // be used for expressing wall - Square - Fence // one fence(wall) - SEFile // SquareEdge File - SERank // SquareEdge Rank - Bitboard96 - WallBBOD // Wall One Direction - Move // planning to express by SquareEdge - Color - WallDir - Board - CommandLine - Zobrist Hashing 関連(何bitにする?) - Thread 関連... (未定) あとで改善する可能性のあるものは、抽象にした方がいいのかもしれない... ### SquareEdge | | A | B | C | D | E | F | G | H | I | J | | -----| :-----: |:----:| :-----: |:-----:| :---: |:----:| :---:| :----:|:----:| :----:| | R9 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | | R8 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | | R7 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | | R6 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | | R5 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | | R4 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | | R3 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | | R2 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | | R1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | | R0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ### Move Square と Fence からなる(Castによって得られる) - enum で定義 - MakeMove 関数で SquareEdge 2つから作成できるものとする. - -1 を invalid とする. - 最初8bitは値が小さい方の SquareEdge 次の8bitは値が大きい方のSquareEdge ```C++ enum Move : int { MoveInvalid = -1, NumberOfMove = 209 } ``` ### Square - MakeSquare - 大きいSquareEdge - 小さいSquareEdge = 11 となる対角線をとる. - 一応 = 9 となるような場合も MakeSquare できるものとする(自然と = 11 となるようになる) ```C++ enum Square : int { SquareInvalid = -1, NumberOfSquare = 81, } ``` ### Fence - MakeFence ```C++ enum Fence : int { FenceInvalid = -1, NumberOfFence = 128 } ``` ### Color プレイヤーの色 ```C++ enum Color : int { White = 0, Black, ColorLimit, }; ``` ### WallDir Wall の縦横 ```C++ enum WallDir : int { Vertical = 0, Horizontal, WallDirLimit, } ``` ### WallBBOD #### 継承 ```c++ class WallBBOD : public Bitboard96 ``` #### 必要な変数 - `WallDir` **wallDir** #### メモ Rank が若い順, Rank が同じなら File が若い順 ### Board #### 変数 - `Square` **kingSq[ColorLimit]**: Player の King の位置のマス - `Bitboard96` **kingSqBB[ColorLimit]**: Player の King の位置の Bitboard - `Color` **turnPlayer**: 現在のターン - `WallBBOD` **fixedWall[WallDirLimit]**: WallDir の設置された壁の Bitboard KingBBはいるのか...? ### CommandLine #### 変数 - `Board` **realtimeBoard**: 現在のボード ## 必要な演算 ### メイン層 - [ ] m1: Board.動けるマスのBitboard96変数を返す - [ ] m2: Board.マスを受け取り、そこに動けるかを判定boolean - [ ] m4: Board.勝ち負け引き分けを判断する // これは簡単ね - [ ] m6: Board.Moveを受け取って合法か判定boolean - [ ] m7: Board.Moveを受け取って手を指す - [ ] m8: WallBBOD.Moveを受け取って置けるか判定(この置けるというのは, 他の壁が邪魔をしないという意味) - [ ] m9: WallBBOD.置ける壁のMoveのvectorを返す(この置けるというのは, 他の壁が邪魔をしないという意味) - [ ] m10: Board.合法Moveを返す ### サブ層 - [ ] s1: Board.Moveを受け取って、それにより閉じ込められるか判定 - [ ] s2: Board.マスを受け取り、通る壁のBitboard96を2つ返す - [ ] s3: Board.壁の位置を受け取り、そこに置けるか判定boolean // これむずそう... ### 各演算のクラスごとの分配 #### Board m1-m7, m10, s1-s3 #### WallBBOD m8-m9 ## Indexer ```C++ class Indexer { public: static const Indexer indexer; // 標準の indexer // static functions static int SquareToIndex(Square); static int FenceToIndex(Fence); static int MoveToIndex(Move); public: // note: public // variables Square IndexedSquare[81]; Fence IndexedFence[128]; Move IndexedMove[209]; }; ``` Square, Fence, Move に対して固有の Index を対応させる ### Indexing Rules #### Square 合計81種 SquareEdge の小さい順に並べる。 A3 ### Fence 合計128種 縦, 横で分ける: - 縦:0 - 63 - 横:64 - 127 SquareEdge の小さい順に並べる。 ### Move Square: Square のインデックスのまま Fence: Fence + 81 ## Thread の分配 ## Zobrist Hashing キング81マス $\times$ プレイヤー2人 = 162 壁1方向64マス $\times$ 2方向 = 128 合計290種 ### HashKey ```C++ using HashKey = uint64_t; ``` ## Shorthand Notation - King Move - Rule: expressed in "K" + (bottom-left square edge) - e2f3 $\rightarrow$ Ke2 - a7b8 $\rightarrow$ Ka7 - Fence Move - Rule: expressed in (wall direction) + (bottom-left square edge) - d7f7 $\rightarrow$ Hd7 - b2b4 $\rightarrow$ Vb2 ## メモ - 道を塞いだかどうかは dijkstra で判定 - 道を塞ぐ壁は Board に保存, リアルタイム更新