git.mcksp
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
require "./board"
require "./piece"
require "./moves"

module Fork
  PAWN_VAL   =  100
  KNIGHT_VAL =  300
  BISHOP_VAL =  300
  ROOK_VAL   =  500
  QUEEN_VAL  =  900
  KING_VAL   = 1000

  PAWN_SCORE_TMPL = [
    90, 90, 90, 90, 90, 90, 90, 90,
    30, 30, 30, 30, 30, 30, 30, 30,
    20, 20, 20, 20, 20, 20, 20, 20,
     5,  5,  5, 15, 15,  5,  5,  5,
     0,  0,  0, 10, 10,  0,  0,  0,
     0,  0,  0,  5,  5,  0,  0,  0,
     5,  5,  5,  0,  0,  5,  5,  5,
     0,  0,  0,  0,  0,  0,  0,  0,
  ]

  KNIGHT_SCORE_TMPL = [
    -5,   0,   0,   0,   0,   0,   0,  -5,
    -5,   0,   0,  10,  10,   0,   0,  -5,
    -5,   5,  20,  20,  20,  20,   5,  -5,
    -5,  10,  20,  30,  30,  20,  10,  -5,
    -5,  10,  20,  30,  30,  20,  10,  -5,
    -5,   5,  20,  10,  10,  20,   5,  -5,
    -5,   0,   0,   0,   0,   0,   0,  -5,
    -5, -10,   0,   0,   0,   0, -10,  -5
  ]

  BISHOP_SCORE_TMPL = [
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,  20,   0,  10,  10,   0,  20,   0,
     0,   0,  10,  20,  20,  10,   0,   0,
     0,   0,  10,  20,  20,  10,   0,   0,
     0,  10,   0,   0,   0,   0,  10,   0,
     0,  30,   0,   0,   0,   0,  30,   0,
     0,   0, -10,   0,   0, -10,   0,   0
  ]

  ROOK_SCORE_TMPL = [
    50,  50,  50,  50,  50,  50,  50,  50,
    50,  50,  50,  50,  50,  50,  50,  50,
     0,   0,  10,  20,  20,  10,   0,   0,
     0,   0,  10,  10,  10,  10,   0,   0,
     0,   0,  10,  10,  10,  10,   0,   0,
     0,   0,  10,  10,  10,  10,   0,   0,
     0,   0,  10,  10,  10,  10,   0,   0,
     0,   0,   0,  20,  20,  20,   0,   0
  ]

  QUEEN_SCORE_TMPL = [
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
  ]

  KING_SCORE_TMPL = [
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0,   0,   0,   0,   0,   0,
     0,   0,   0, -15, -15,   0,   5,   0,
     0,   0,  20, -15, -15,   0,  30,   0
  ]

  PAWN_SCORE   = [white_order(PAWN_SCORE_TMPL), PAWN_SCORE_TMPL]
  KNIGHT_SCORE = [white_order(KNIGHT_SCORE_TMPL), KNIGHT_SCORE_TMPL]
  BISHOP_SCORE = [white_order(BISHOP_SCORE_TMPL), BISHOP_SCORE_TMPL]
  ROOK_SCORE   = [white_order(ROOK_SCORE_TMPL), ROOK_SCORE_TMPL]
  QUEEN_SCORE  = [white_order(QUEEN_SCORE_TMPL), QUEEN_SCORE_TMPL]
  KING_SCORE   = [white_order(KING_SCORE_TMPL), KING_SCORE_TMPL]

  def white_order(arr)
    raise Exception.new("array should have 64 elems") if arr.size != 64
    arr.each_slice(8).to_a.reverse.flatten
  end

  class Eval
    def self.eval(board : Board, side)
      score = eval_player(board.white, WHITE) - eval_player(board.black, BLACK)
      side == WHITE ? score : -score
    end

    def self.eval_player(player, side)
      score = 0
      Fork.iterate_bitboard(player[PAWN]) do |index|
        score += PAWN_VAL + PAWN_SCORE[side][index]
      end
      Fork.iterate_bitboard(player[KNIGHT]) do |index|
        score += KNIGHT_VAL + KNIGHT_SCORE[side][index]
      end
      Fork.iterate_bitboard(player[BISHOP]) do |index|
        score += BISHOP_VAL + BISHOP_SCORE[side][index]
      end
      Fork.iterate_bitboard(player[ROOK]) do |index|
        score += ROOK_VAL + ROOK_SCORE[side][index]
      end
      Fork.iterate_bitboard(player[QUEEN]) do |index|
        score += QUEEN_VAL + QUEEN_SCORE[side][index]
      end
      Fork.iterate_bitboard(player[KING]) do |index|
        score += KING_VAL + KING_SCORE[side][index]
      end
      score
    end
  end
end