github.com/frankkopp/FrankyGo@v1.0.3/internal/types/posValues.go (about)

     1  //
     2  // FrankyGo - UCI chess engine in GO for learning purposes
     3  //
     4  // MIT License
     5  //
     6  // Copyright (c) 2018-2020 Frank Kopp
     7  //
     8  // Permission is hereby granted, free of charge, to any person obtaining a copy
     9  // of this software and associated documentation files (the "Software"), to deal
    10  // in the Software without restriction, including without limitation the rights
    11  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    12  // copies of the Software, and to permit persons to whom the Software is
    13  // furnished to do so, subject to the following conditions:
    14  //
    15  // The above copyright notice and this permission notice shall be included in all
    16  // copies or substantial portions of the Software.
    17  //
    18  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    19  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    20  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    21  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    22  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    24  // SOFTWARE.
    25  //
    26  
    27  package types
    28  
    29  import (
    30  	"github.com/frankkopp/FrankyGo/internal/assert"
    31  )
    32  
    33  // PosMidValue returns the pre computed positional value
    34  // for the piece on the given square in mid game
    35  func PosMidValue(p Piece, sq Square) Value {
    36  	if assert.DEBUG {
    37  		assert.Assert(initialized, "Pos values have not been initialized. Please call types.Init() first.")
    38  	}
    39  	return posMidValue[p][sq]
    40  }
    41  
    42  // PosEndValue returns the pre computed positional value
    43  // for the piece on the given square in end game
    44  func PosEndValue(p Piece, sq Square) Value {
    45  	if assert.DEBUG {
    46  		assert.Assert(initialized, "Pos values have not been initialized. Please call types.Init() first.")
    47  	}
    48  	return posEndValue[p][sq]
    49  }
    50  
    51  // PosValue returns the pre computed positional value
    52  // for the piece on the given square and given game phase
    53  func PosValue(p Piece, sq Square, gp int) Value {
    54  	if assert.DEBUG {
    55  		assert.Assert(initialized, "Pos values have not been initialized. Please call types.Init() first.")
    56  	}
    57  	return posValue[p][sq][gp]
    58  }
    59  
    60  // initPosValues pre computes arrays containing the positional values of each piece
    61  // for each square and game phase
    62  func initPosValues() {
    63  	// all game phases
    64  	for pc := WhiteKing; pc <= BlackQueen; pc++ {
    65  		for sq := SqA1; sq <= SqH8; sq++ {
    66  			for gp := GamePhaseMax; gp >= 0; gp-- {
    67  				switch pc {
    68  				case WhiteKing:
    69  					posMidValue[pc][sq] = kingMidGame[63-sq]
    70  					posEndValue[pc][sq] = kingEndGame[63-sq]
    71  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &kingMidGame, &kingEndGame)
    72  				case WhitePawn:
    73  					posMidValue[pc][sq] = pawnsMidGame[63-sq]
    74  					posEndValue[pc][sq] = pawnsEndGame[63-sq]
    75  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &pawnsMidGame, &pawnsEndGame)
    76  				case WhiteKnight:
    77  					posMidValue[pc][sq] = knightMidGame[63-sq]
    78  					posEndValue[pc][sq] = knightEndGame[63-sq]
    79  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &knightMidGame, &knightEndGame)
    80  				case WhiteBishop:
    81  					posMidValue[pc][sq] = bishopMidGame[63-sq]
    82  					posEndValue[pc][sq] = bishopEndGame[63-sq]
    83  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &bishopMidGame, &bishopEndGame)
    84  				case WhiteRook:
    85  					posMidValue[pc][sq] = rookMidGame[63-sq]
    86  					posEndValue[pc][sq] = rookEndGame[63-sq]
    87  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &rookMidGame, &rookEndGame)
    88  				case WhiteQueen:
    89  					posMidValue[pc][sq] = queenMidGame[63-sq]
    90  					posEndValue[pc][sq] = queenEndGame[63-sq]
    91  					posValue[pc][sq][gp] = calcPosValueWhite(sq, gp, &queenMidGame, &queenEndGame)
    92  				case BlackKing:
    93  					posMidValue[pc][sq] = kingMidGame[sq]
    94  					posEndValue[pc][sq] = kingEndGame[sq]
    95  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &kingMidGame, &kingEndGame)
    96  				case BlackPawn:
    97  					posMidValue[pc][sq] = pawnsMidGame[sq]
    98  					posEndValue[pc][sq] = pawnsEndGame[sq]
    99  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &pawnsMidGame, &pawnsEndGame)
   100  				case BlackKnight:
   101  					posMidValue[pc][sq] = knightMidGame[sq]
   102  					posEndValue[pc][sq] = knightEndGame[sq]
   103  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &knightMidGame, &knightEndGame)
   104  				case BlackBishop:
   105  					posMidValue[pc][sq] = bishopMidGame[sq]
   106  					posEndValue[pc][sq] = bishopEndGame[sq]
   107  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &bishopMidGame, &bishopEndGame)
   108  				case BlackRook:
   109  					posMidValue[pc][sq] = rookMidGame[sq]
   110  					posEndValue[pc][sq] = rookEndGame[sq]
   111  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &rookMidGame, &rookEndGame)
   112  				case BlackQueen:
   113  					posMidValue[pc][sq] = queenMidGame[sq]
   114  					posEndValue[pc][sq] = queenEndGame[sq]
   115  					posValue[pc][sq][gp] = calcPosValueBlack(sq, gp, &queenMidGame, &queenEndGame)
   116  				default:
   117  				}
   118  			}
   119  		}
   120  	}
   121  }
   122  
   123  func calcPosValueBlack(sq Square, gamePhase int, posMidTable *[SqLength]Value, posEndTable *[SqLength]Value) Value {
   124  	return (Value(gamePhase)*posMidTable[sq] + (Value(GamePhaseMax-gamePhase) * posEndTable[sq])) / GamePhaseMax
   125  }
   126  
   127  func calcPosValueWhite(sq Square, gamePhase int, posMidTable *[SqLength]Value, posEndTable *[SqLength]Value) Value {
   128  	return (Value(gamePhase)*posMidTable[63-sq] + (Value(GamePhaseMax-gamePhase))*posEndTable[63-sq]) / GamePhaseMax
   129  }
   130  
   131  var (
   132  	posMidValue = [PieceLength][SqLength]Value{}
   133  	posEndValue = [PieceLength][SqLength]Value{}
   134  	posValue    = [PieceLength][SqLength][GamePhaseMax + 1]Value{}
   135  
   136  	// positional values for pieces
   137  	// @formatter:off
   138  	// PAWN Tables
   139  	pawnsMidGame = [SqLength]Value {
   140  	0,  0,  0,  0,  0,  0,  0,  0,
   141  	0,  0,  0,  0,  0,  0,  0,  0,
   142  	0,  5,  5,  5,  5,  5,  5,  0,
   143  	5,  5, 10, 30, 30, 10,  5,  5,
   144  	0,  0,  0, 30, 30,  0,  0,  0,
   145  	5, -5,-10,  0,  0,-10, -5,  5,
   146  	5, 10, 10,-30,-30, 10, 10,  5,
   147  	0,  0,  0,  0,  0,  0,  0,  0}
   148  
   149  	pawnsEndGame = [SqLength]Value {
   150  	0,  0,  0,  0,  0,  0,  0,  0,
   151  	90, 90, 90, 90, 90, 90, 90, 90,
   152  	40, 50, 50, 60, 60, 50, 50, 40,
   153  	20, 30, 30, 40, 40, 30, 30, 20,
   154  	10, 10, 20, 20, 20, 10, 10, 10,
   155  	5, 10, 10, 10, 10, 10, 10,  5,
   156  	5, 10, 10, 10, 10, 10, 10,  5,
   157  	0,  0,  0,  0,  0,  0,  0,  0}
   158  
   159  	// KNIGHT Tables
   160  	knightMidGame = [SqLength]Value {
   161  	-50,-40,-30,-30,-30,-30,-40,-50,
   162  	-40,-20,  0,  0,  0,  0,-20,-40,
   163  	-30,  0, 10, 15, 15, 10,  0,-30,
   164  	-30,  5, 15, 20, 20, 15,  5,-30,
   165  	-30,  0, 15, 20, 20, 15,  0,-30,
   166  	-30,  5, 10, 15, 15, 10,  5,-30,
   167  	-40,-20,  0,  5,  5,  0,-20,-40,
   168  	-50,-25,-20,-30,-30,-20,-25,-50}
   169  
   170  	knightEndGame = [SqLength]Value {
   171  	-50,-40,-30,-30,-30,-30,-40,-50,
   172  	-40,-20,  0,  0,  0,  0,-20,-40,
   173  	-30,  0, 10, 15, 15, 10,  0,-30,
   174  	-30,  0, 15, 20, 20, 15,  0,-30,
   175  	-30,  0, 15, 20, 20, 15,  0,-30,
   176  	-30,  0, 10, 15, 15, 10,  0,-30,
   177  	-40,-20,  0,  0,  0,  0,-20,-40,
   178  	-50,-40,-20,-30,-30,-20,-40,-50}
   179  
   180  	// BISHOP Tables
   181  	bishopMidGame = [SqLength]Value {
   182  	-20,-10,-10,-10,-10,-10,-10,-20,
   183  	-10,  0,  0,  0,  0,  0,  0,-10,
   184  	-10,  0,  5, 10, 10,  5,  0,-10,
   185  	-10,  5,  5, 10, 10,  5,  5,-10,
   186  	-10,  0, 10, 10, 10, 10,  0,-10,
   187  	-10, 10, 10, 10, 10, 10, 10,-10,
   188  	-10,  5,  0,  0,  0,  0,  5,-10,
   189  	-20,-10,-40,-10,-10,-40,-10,-20}
   190  
   191  	bishopEndGame = [SqLength]Value {
   192  	-20,-10,-10,-10,-10,-10,-10,-20,
   193  	-10,  0,  0,  0,  0,  0,  0,-10,
   194  	-10,  0,  5,  5,  5,  5,  0,-10,
   195  	-10,  0,  5, 10, 10,  5,  0,-10,
   196  	-10,  0,  5, 10, 10,  5,  0,-10,
   197  	-10,  0,  5,  5,  5,  5,  0,-10,
   198  	-10,  0,  0,  0,  0,  0,  0,-10,
   199  	-20,-10,-10,-10,-10,-10,-10,-20}
   200  
   201  	// ROOK Tables
   202  	rookMidGame  = [SqLength]Value {
   203  	5,  5,  5,  5,  5,  5,  5,  5,
   204  	10, 10, 10, 10, 10, 10, 10, 10,
   205  	0,  0,  0,  0,  0,  0,  0,  0,
   206  	0,  0,  0,  0,  0,  0,  0,  0,
   207  	0,  0,  0,  0,  0,  0,  0,  0,
   208  	0,  0,  0,  0,  0,  0,  0,  0,
   209  	0,  0,  0,  0,  0,  0,  0,  0,
   210  	-15,-10, 15, 15, 15, 15,-10,-15}
   211  
   212  	rookEndGame  = [SqLength]Value {
   213  	5,  5,  5,  5,  5,  5,  5,  5,
   214  	0,  0,  0,  0,  0,  0,  0,  0,
   215  	0,  0,  0,  0,  0,  0,  0,  0,
   216  	0,  0,  0,  0,  0,  0,  0,  0,
   217  	0,  0,  0,  0,  0,  0,  0,  0,
   218  	0,  0,  0,  0,  0,  0,  0,  0,
   219  	0,  0,  0,  0,  0,  0,  0,  0,
   220  	0,  0,  0,  0,  0,  0,  0,  0}
   221  
   222  	// Queen Tables
   223  	queenMidGame = [SqLength]Value {
   224  	-20,-10,-10, -5, -5,-10,-10,-20,
   225  	-10,  0,  0,  0,  0,  0,  0,-10,
   226  	-10,  0,  0,  0,  0,  0,  0,-10,
   227  	-5,  0,  2,  2,  2,  2,  0, -5,
   228  	-5,  0,  5,  5,  5,  5,  0, -5,
   229  	-10,  0,  5,  5,  5,  5,  0,-10,
   230  	-10,  0,  5,  5,  5,  5,  0,-10,
   231  	-20,-10,-10, -5, -5,-10,-10,-20}
   232  
   233  	queenEndGame = [SqLength]Value {
   234  	-20,-10,-10, -5, -5,-10,-10,-20,
   235  	-10,  0,  0,  0,  0,  0,  0,-10,
   236  	-10,  0,  5,  5,  5,  5,  0,-10,
   237  	-5,  0,  5,  5,  5,  5,  0, -5,
   238  	-5,  0,  5,  5,  5,  5,  0, -5,
   239  	-10,  0,  5,  5,  5,  5,  0,-10,
   240  	-10,  0,  0,  0,  0,  0,  0,-10,
   241  	-20,-10,-10, -5, -5,-10,-10,-20}
   242  
   243  	// King Tables
   244  	kingMidGame  = [SqLength]Value {
   245  	-30,-40,-40,-50,-50,-40,-40,-30,
   246  	-30,-40,-40,-50,-50,-40,-40,-30,
   247  	-30,-40,-40,-50,-50,-40,-40,-30,
   248  	-30,-40,-40,-50,-50,-40,-40,-30,
   249  	-20,-30,-30,-40,-40,-30,-30,-20,
   250  	-10,-20,-20,-30,-30,-30,-20,-10,
   251  	0,  0,-20,-20,-20,-20,  0,  0,
   252  	20, 50,  0,-20,-20,  0, 50, 20}
   253  
   254  	kingEndGame  = [SqLength]Value {
   255  	-50,-30,-30,-20,-20,-30,-30,-50,
   256  	-30,-20,-10,  0,  0,-10,-20,-30,
   257  	-30,-10, 20, 30, 30, 20,-10,-30,
   258  	-30,-10, 30, 40, 40, 30,-10,-30,
   259  	-30,-10, 30, 40, 40, 30,-10,-30,
   260  	-30,-10, 20, 30, 30, 20,-10,-30,
   261  	-30,-30,  0,  0,  0,  0,-30,-30,
   262  	-50,-30,-30,-30,-30,-30,-30,-50}
   263  	// @formatter:on
   264  )