プログラムを読まない人のための Stockfish 評価値アルゴリズム解説 (2)

#はじめに
この記事は Stockfish（ストックフィッシュ）の局面評価方法を解説します．

[プログラムを読まない人のための Stockfish 評価値アルゴリズム解説 (1)](https://qiita.com/anjyu108/items/43f3bfd5a5387660373a) からの続きなので，そちらを先に読んで頂ければと思います．

前回は Stockfish の基本とスコアを決定する要素のうち4つまで（`piece squrare-table`, `imbalance`, `contempt`, `ポーン価値の補正`）まで説明しました．残りのスコア要素のうち，`駒の利き`，`mobility`，`キングの安全性`，`threat` について説明します．

なお，前回のはじめに記載しましたが，本稿は Stockfish のアルゴリズムを厳密に解説するものではありません．
そのため，一部のケースは説明を省いています．（chess960 でしか起こり得ない配置，一方がクイーンを複数持っている時など）

#駒の利き
駒がどれだけ働いているかを元にした評価軸です．全ての駒に対してそれぞれ計算し，合算して求めます．以下の要素によって決まります．

+ ナイトとビショップに適応する要素
  + Outpost （アウトポストを活用しているか）
  + BehindPawn　（自ポーンの真後ろにいるか）
  + KingProtector （キングの防御に貢献していないか）
+ ビショップに適応する要素
  + BishopPawn （利きがポーンに邪魔されているか）
  + LongDiagonalBishop　（大ダイアゴナルの支配）
+ ルックに適応する要素
  + RookOnPawn （相手ポーンへの圧力）
  + RookOnFile （オープン・セミオープンファイルの支配）
  + TrappedRook （自キングが邪魔で中央へ動けずにいないか）
+ クイーンに適応する要素
  + WeakQueen （ピンやディスカバード攻撃の圧力を受けているか）

各要素はベーススコアを元に，それぞれ決まった方法で計算されます．
次の式により，駒の利きスコアが求められます．

```math
駒の利きスコア = Outpost + BehindPawn - KingProtector - BishopPawn \\
 + LongDiagonalBishop + RookOnPawn + RookOnFile \\
 +  - TrappedRook - weakQueen
```

ベーススコアは以下表の通りです．

|     | 中盤 |　終盤 |
| --- | --- | ---|
|   Outpost(knight)  |  22   |  6   |  
|   Outpost (knight) (ポーンにより守られている場合)  |   36  |   12  |
|   Outpost(bishop)  |   9  |   2  |  
|   Outpost (bishop) (ポーンにより守られている場合)  |  15   |   5  |
|    BehindPawn |   16  |  0   | 
|  KingProtector   |   6  |   6  | 
|  BishpPawn   |   3  |   7  | 
|   LongDiagonal  |  22   | 0    | 
|   RookOnPawn  |  10   |   3  | 
|   RookOnFile（セミオープン）  |  20   |  7   |
|   RookOnFile（オープン）  |   45  |  20   | 
|   TrappedRook  |   92  |   0  | 
|  WeakQueen   |   50  |  10   | 


###Outpost
この要素は以下の式により求められます．

```math
アウトポストにいる場合　　　　　　： Outpost = ベーススコア \\
アウトポストに次の手で行ける場合　： Outpost = ベーススコア ÷2
```

マスがアウトポストである条件は以下の2つです．

+ 4~6段目にいる（黒の場合は3~5段目）
+ 自駒より前方でかつ両隣の列に相手ポーンがいない（ポーンによって追い払われない）

###BehindPawn
この要素はポーンの真後ろにいるナイトとビショップにボーナスを与える要素です．ポーンによってその駒の安全性が増すことを意味します．

ベーススコアがそのまま BehindPawn スコアになります．

###KingProtector
キングの防御にどの程度貢献していないかを表す要素です．マイナス要素なので，KingProtector スコアが大きい程，最終的な駒の利きスコアが小さくなります．以下の式で求められます．

``` math
キングからの距離 = 駒とキングの"段の差"と"列の差"のうち大きい方 \\
KingProtector = ベーススコア × キングからの距離
```

###BishopPawn
ポーンがビショップの利きをどれだけ阻害しているか示す要素です．マイナス要素です．以下の式で表されます．

```math
BishopPawn = ベーススコア × ビショップと同色マスのポーン数 \\
× (1 + ブロックされているセンターファイル上のポーン数)
```

ここで言う「センターファイル」とは，c~fファイルを指します．

###LongDiagonal
大ダイアゴナルの支配しているビショップにボーナスを加算する要素です．d4 と e5 ，又は d5 と e4 に利きがある時，大ダイアゴナルを支配していると判定されます．

ベーススコアがそのまま LongDiagonal スコアになります 

###RookOnPawn
相手ポーンへ圧力をかけているルックにボーナスを加算する要素です．次の式で求められます．

```math
RookOnPawn = ベーススコア　×　利きが働いているポーンの数
```

"利きが働いている"とは，"次に取れる"とも言いかえられます．

###RookOnFile
オープンファイル，又はセミオープンファイルを支配しているルックにボーナスを与える要素です．

ベーススコアがそのまま RookOnFile スコアになります．

###TrappedRook
ルックが中央で活躍できない度合いに応じたペナルティーです．キングによってルックがトラップされている時に適応されます．次の式で与えられます．

```math
キャスリング権がある場合:　TrappedRook = ベーススコア - 動けるマス × 22 \\
キャスリング権がない場合:　TrappedRook = (ベーススコア - 動けるマス × 22) × 2
```

ただし，ルックの動けるマスが3つを超える時，TrappedRook スコアは0点になります．

###weakQueen
クイーンが十分活躍できていない時に与えられるペナルティーです．クイーンがピンされている時，又はクイーンへのディスカバード攻撃の筋がある時に適応されます．

内部的には，十分活躍できていないクイーンの条件は次の通りです．

+ Sniper（攻撃駒) をルック，ビショップ，クイーンとする．
+ 自クイーンと相手 Sniper との間に（自分相手問わずに）駒が1つだけ存在する．

ベーススコアがそのまま weakQueen スコアになります．

#mobility
駒の動きやすさに応じてボーナスを与える要素です．そこへ移動して活用できるマスの数に応じて決まります．

便宜上，そこへ移動して活用できるマスを mobility マスとします．mobility スコアは以下の表により決定されます．

+ mobility スコア（中盤）

| mobility マス数 |  Knight  |  Bishop  |  Rook   |  Queen  |
| ----| ----  | --- | ---- | ---- |
1 | -76 | -59 | -76 | -36 |
2 | -54 | -23 | -18 | -15 |
3 | -28 | -3 | 28 | 8 |
4 | -10 | 13 | 55 | 18 |
5 | 5 | 24 | 69 | 34 |
6 | 12 | 42 | 82 | 54 |
7 | 26 | 54 | 112 | 61 |
8 | 29 | 57 | 118 | 73 |
9 | 29 | 65 | 132 | 79 |

+ mobility スコア（終盤）

| mobility マス数 |  Knight  |  Bishop  |  Rook   |  Queen  | 
| ----| ----  | --- | ---- | ---- |
1 | -75 | -48 | -58 | -39 |
2 | -57 | -20 | -27 | -21 |
3 | -9 | 16 | -15 | 3 |
4 | -2 | 26 | -10 | 3 |
5 | 6 | 38 | -5 | 14 |
6 | 14 | 51 | -2 | 22 |
7 | 22 | 55 | 9 | 28 |
8 | 29 | 63 | 16 | 41 |
9 | 36 | 63 | 30 | 43 |


mobility マスの正確な条件は以下の通りです．

+ 駒の利きが及んでいる（次に移動できる）
+ 相手ポーンの利きが及ばない
+ 2, 3段目（黒は6, 7段目）の自ポーンがいない
+ blocked な（前進できない）自ポーンがいない
+ 自キングと自クーンがいない

#キングの安全性
キングの安全性を表す要素です．以下の要素を合算して決まります．

+ Shelter（キング位置の防衛拠点能力）
    + キング位置ボーナス
    + 安全性ボーナス
    + 相手ポーンストリームボーナス
+ Danger（キングへ迫る脅威）
+ その他の要素
    + mobility スコア差の考慮など

その他の要素は，Shelter と Danger スコア以外の要素のことです．数が多く，言葉にして説明すると長くなる上に，（筆者の直感的に）支配的な程大きな点数にならないため，本稿では割愛します．

###Shelter
キング位置の防衛拠点としての有効性を表す要素です．この要素は特に計算がかなり複雑だったり，例外規定が多いです．そのため，この項目は正確性を特に犠牲にし，簡単さを優先して説明します．

スコアはキングの位置に応じて，次の式によって決まります．キャスリング権がある時は，キャスリング後のスコアも計算して最も高いスコアを採用します．

```math
Shelter スコア（中盤） = キング位置ボーナス + 安全性ボーナス - 相手ポーンストームペナルティ \\
Shelter スコア（終盤） = -16 × キングから最も近いポーンとの距離
```

######キング位置ボーナス
スコアは374点で，以下の条件を共に満たす時に与えられます．満たさない場合は0点です．

+ キングが a1 か h1 （黒はa8, h8）にいる
+ キングの位置するファイル前方に，相手ポーンがいる

######安全性ボーナス
キング周りのポーンとの位置関係から，ボーナスを加算する要素です．自キングとその両脇のファイル上の自ポーンの位置によって決まります．それぞれにファイルごとに計算し，合算して求められます．

|     |  a  |  b  |  c   |  d  |  e  |  f   |  g  |  h  |
| ----| ----  | --- | ---- | ----  | ---| ----| ----  | ---|
|No Pawn| -6 | -43 | -10 | -39 | -39 | -10 | -43 | -6 |
| 7 | 25 | -63 | -45 |-166  | -166 | -45 | -63  | 25 |
| 6 | 18 | -11 | 3 | -67 | -67 | 3 | -11 | 18 |
| 5 | 39 | -29 | 32 | -48 | -48 | 32 | -29 |39  |
| 4 | 58 | -49 | -2 | -52 | -52 | -2 | -49 |  58 |
| 3 | 93 | 35 | 23 |-29  | -29 | 23 | 35 | 93 |
| 2 | 81 | 61 | 75 |-13  | -13 | 75 |  61| 81 |

######相手ポーンストームペナルティ
`相手ポーンストームペナルティ`は，相手ポーンが自キングに迫っているかを示す要素です．自キングとその両脇のファイル上の相手ポーンの位置によって決まります．それぞれにファイルごとに計算し，合算して求められます．

+ 相手ポーンが自ポーンでブロックされている時（ファイルに関係ない）

| rank | score  |
| ----| ----  |
| 7 | 15 |
| 6 | 1 |
| 5 | 5 |
| 4 | 6 |
| 3 | 66 |
| 2 | 0 |

+ 相手ポーンが自ポーンでブロックされていない時

|     |  a  |  b  |  c   |  d  |  e  |  f   |  g  |  h  |
| ----| ----  | --- | ---- | ----  | ---| ----| ----  | ---|
| 7 | 51 | 23 | -2 | -16 | -16 | -2 | 23 | 51 |
| 6 | 45 | -7 | -14 | -7 | -7 | -14 | -7 | 45 |
| 5 | 57 | 39 | 7 | 2 | 2 | 7 | 39 | 57 |
| 4 | 93 | 46 | 37 | 15 | 15 | 37 | 46 | 93 |
| 3 | 123 | 123 | 162 | 90 | 90 | 162 | 123 | 123 |
| 2 | 107 | -18 | 52 | -14 | -14 | 52 | -18 | 107 |

+ そもそも相手ポーンがない時（ランクに関係ない）

|  a  |  b  |  c   |  d  |  e  |  f   |  g  |  h  |
| ----| ----  | --- | ---- | ----  | ---| ----| ----  | ---|
| 89 | 44 | 4 | -10 | -10 | 4 | 44 | 89 |

###Danger
相手ピースのキングへの攻撃力を示す要素です．以下の式で求められます．

```math
kingDanger = 780 × ただ取りされずにチェックできる相手駒数 \\
 + キング周囲1マス内へ利いている相手駒の駒危険係数の合計 \\
 + 185 × キング周囲1マス内の weak マス数 \\
 + 129 × ただ取りされればチェックできる相手駒数 \\
 + 4 × キング拠点範囲への攻撃マス数 \\
 - 873 × 相手クイーンの駒数 \\
 - Shelter スコア（中盤）÷ 8 \\
 - 30 \\
Danger（中盤) = kingDanger × kingDanger / 4096 \\
Danger（終盤) = kingDanger / 16
```

+ 駒危険係数

| Knight | Bishop | Rook | Queen|
| ---    | ---    | ---  | ---  |
| 77     | 55     |  44  | 10   |

weak マスとは，相手駒で攻撃されているマスの内，自キング又はクイーンにしか守られていないマスを指します．

キング拠点範囲とは，キングの周囲の空間を指します．正確な定義は言葉にすると複雑なため，割愛します．（一般的な感覚でキングの拠点と感じる領域です）


#threat
相手への圧力（タクティクスの発生しやすさ）を示す要素です．なお，説明に用いる`攻撃`という言葉は，[x-ray 攻撃](https://www.chessprogramming.org/X-ray_Attacks_(Bitboards))を含めた攻撃を指します．

threat スコアは以下の式で求められます．

```math
threat スコア = ThreatBy \\
+ WeakUnoppsedPawn × weak な相手ポーン数 \\
+ ThreatByPawnPush × ただ取りされずに前進可能なポーン数 \\
+ ThreatBySafePawn × ただ取りされない位置にいるポーン数 \\
+ KnightOnQueen × 次の手で相手クイーンへ攻撃可能なナイト数 \\
+ SliderOnQueen × 次の手で相手クイーンへ攻撃可能なビショップとルック数
```

weak とは，自分の攻撃駒数が相手の防御駒数より多く，かつ相手がポーンで守っていないことを指します．

ThreatBy は以下の式で求められます．

```math
ThreatBy = ThreatByMinor ×ナイトorビショップが攻撃している相手駒数 \\
+ ThreatByRook × ルックが攻撃している weak な相手駒数 \\
+ ThreatByKing × キングが攻撃している weak な相手駒数 \\
+ Hanging × weak なポーン以外の相手駒数 \\
+ Overload × weak な相手ポーン数
```

各種係数は以下の通りです．

+ 攻撃相手駒によらない係数

|     | 中盤 |　終盤 |
| --- | --- | ---|
|  ThreatByKing  |  23   |    76 |
|  Hanging  |   57  |  32   |
|  Overload  |  13   |   6  |
|   WeakUnoppsedPawn  |   5  |   29  |  
|  ThreatByPawnPush  |   45  |   40  |
| ThreatBySafePawn   |   107  |   102  |
| KnightOnQueen   |   21  |  11   |
| SliderOnQueen   |   42  |   21  |

+ ThreatMinor 

|  攻撃相手駒   | 中盤 |　終盤 |
| --- | --- | ---|
|  ポーン  |  0   |    31 |
|  ナイト  |   39  |  42   |
|  ビショップ  |  57   |   44  |
|   ルック  |   68  |   112  |  
|  クイーン  |   47  |   120  |

+ ThreatRook 

|  攻撃相手駒   | 中盤 |　終盤 |
| --- | --- | ---|
|  ポーン  |  0   |    24 |
|  ナイト  |   38  |  71   |
|  ビショップ  |  38   |   61  |
|   ルック  |   0  |   38  |  
|  クイーン  |   36  |   38  |


#おわりに
こんな細かいアルゴリズム書いてもみんな興味ない気が途中からしましたが，意地でここまで書きました．

ここまで読んでくれた人の中には，評価値アルゴリズムが戦略（ストラテジ）的な観点しかないことに気づいたかもしれません．Stockfish の戦術（タクティクス）力は強力な探索能力によって実現しています．

つまり，Stockfish の強さは現代コンピュータのパワーに頼った力任せな大量探索能力無くしてはありえないと言えます．（当然，Stockfish は[アルファ・ベータ法](https://www.webcyou.com/?p=6997)をはじめとした様々な手法を使って探索を高速化していますが）

とはいえ戦略的観点での評価だと割り切れば，人間が指すときにも十分参考になるアルゴリズムだと自分は思います．

Stockfish の評価値にはまだ解説していない要素があります．
時間とやる気が満ちたらまた続きを書こうと思います．

#参考文献
https://github.com/official-stockfish/Stockfish
https://www.chessprogramming.org/Main_Page
https://www.webcyou.com/?p=6997