Subversion Repositories Games.Chess Giants

Rev

Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 154 Rev 169
Line 4... Line 4...
4
  Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
4
  Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
  Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
5
  Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
 
6
 
7
  Stockfish is free software: you can redistribute it and/or modify
7
  Stockfish is free software: you can redistribute it and/or modify
8
  it under the terms of the GNU General Public License as published by
8
  it under the terms of the GNU General Public License as published by
9
  the Free Software Foundation, either version 3 of the License, or
9
  the Free Software Foundation, either version 3 of the License, or
10
  (at your option) any later version.
10
  (at your option) any later version.
Line 81... Line 81...
81
        sq = ~sq;
81
        sq = ~sq;
82
 
82
 
83
    return sq;
83
    return sq;
84
  }
84
  }
85
 
85
 
86
  // Get the material key of Position out of the given endgame key code
-
 
87
  // like "KBPKN". The trick here is to first forge an ad-hoc FEN string
-
 
88
  // and then let a Position object do the work for us.
-
 
89
  Key key(const string& code, Color c) {
-
 
90
 
-
 
91
    assert(code.length() > 0 && code.length() < 8);
-
 
92
    assert(code[0] == 'K');
-
 
93
 
-
 
94
    string sides[] = { code.substr(code.find('K', 1)),      // Weak
-
 
95
                       code.substr(0, code.find('K', 1)) }; // Strong
-
 
96
 
-
 
97
    std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
-
 
98
 
-
 
99
    string fen =  sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
-
 
100
                + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
-
 
101
 
-
 
102
    StateInfo st;
-
 
103
    return Position().set(fen, false, &st, nullptr).material_key();
-
 
104
  }
-
 
105
 
-
 
106
} // namespace
86
} // namespace
107
 
87
 
108
 
88
 
109
/// Endgames members definitions
89
/// Endgames members definitions
110
 
90
 
111
Endgames::Endgames() {
91
Endgames::Endgames() {
112
 
92
 
Line 125... Line 105...
125
  add<KRPKB>("KRPKB");
105
  add<KRPKB>("KRPKB");
126
  add<KBPKB>("KBPKB");
106
  add<KBPKB>("KBPKB");
127
  add<KBPKN>("KBPKN");
107
  add<KBPKN>("KBPKN");
128
  add<KBPPKB>("KBPPKB");
108
  add<KBPPKB>("KBPPKB");
129
  add<KRPPKRP>("KRPPKRP");
109
  add<KRPPKRP>("KRPPKRP");
130
}
-
 
131
 
-
 
132
 
-
 
133
template<EndgameType E, typename T>
-
 
134
void Endgames::add(const string& code) {
-
 
135
  map<T>()[key(code, WHITE)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
-
 
136
  map<T>()[key(code, BLACK)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
-
 
137
}
110
}
138
 
111
 
139
 
112
 
140
/// Mate with KX vs K. This function is used to evaluate positions with
113
/// Mate with KX vs K. This function is used to evaluate positions with
141
/// king and plenty of material vs a lone king. It simply gives the
114
/// king and plenty of material vs a lone king. It simply gives the
Line 160... Line 133...
160
                + PushClose[distance(winnerKSq, loserKSq)];
133
                + PushClose[distance(winnerKSq, loserKSq)];
161
 
134
 
162
  if (   pos.count<QUEEN>(strongSide)
135
  if (   pos.count<QUEEN>(strongSide)
163
      || pos.count<ROOK>(strongSide)
136
      || pos.count<ROOK>(strongSide)
164
      ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
137
      ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
165
      ||(pos.count<BISHOP>(strongSide) > 1 && opposite_colors(pos.squares<BISHOP>(strongSide)[0],
138
      || (   (pos.pieces(strongSide, BISHOP) & ~DarkSquares)
166
                                                              pos.squares<BISHOP>(strongSide)[1])))
139
          && (pos.pieces(strongSide, BISHOP) &  DarkSquares)))
167
      result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
140
      result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
168
 
141
 
169
  return strongSide == pos.side_to_move() ? result : -result;
142
  return strongSide == pos.side_to_move() ? result : -result;
170
}
143
}
171
 
144
 
Line 549... Line 522...
549
  {
522
  {
550
      Square ksq = pos.square<KING>(weakSide);
523
      Square ksq = pos.square<KING>(weakSide);
551
      Square bsq = pos.square<BISHOP>(weakSide);
524
      Square bsq = pos.square<BISHOP>(weakSide);
552
      Square psq = pos.square<PAWN>(strongSide);
525
      Square psq = pos.square<PAWN>(strongSide);
553
      Rank rk = relative_rank(strongSide, psq);
526
      Rank rk = relative_rank(strongSide, psq);
554
      Square push = pawn_push(strongSide);
527
      Direction push = pawn_push(strongSide);
555
 
528
 
556
      // If the pawn is on the 5th rank and the pawn (currently) is on
529
      // If the pawn is on the 5th rank and the pawn (currently) is on
557
      // the same color square as the bishop then there is a chance of
530
      // the same color square as the bishop then there is a chance of
558
      // a fortress. Depending on the king position give a moderate
531
      // a fortress. Depending on the king position give a moderate
559
      // reduction or a stronger one if the defending king is near the
532
      // reduction or a stronger one if the defending king is near the
Line 623... Line 596...
623
  Square ksq = pos.square<KING>(weakSide);
596
  Square ksq = pos.square<KING>(weakSide);
624
  Bitboard pawns = pos.pieces(strongSide, PAWN);
597
  Bitboard pawns = pos.pieces(strongSide, PAWN);
625
 
598
 
626
  // If all pawns are ahead of the king, on a single rook file and
599
  // If all pawns are ahead of the king, on a single rook file and
627
  // the king is within one file of the pawns, it's a draw.
600
  // the king is within one file of the pawns, it's a draw.
628
  if (   !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
601
  if (   !(pawns & ~forward_ranks_bb(weakSide, ksq))
629
      && !((pawns & ~FileABB) && (pawns & ~FileHBB))
602
      && !((pawns & ~FileABB) && (pawns & ~FileHBB))
630
      &&  distance<File>(ksq, lsb(pawns)) <= 1)
603
      &&  distance<File>(ksq, lsb(pawns)) <= 1)
631
      return SCALE_FACTOR_DRAW;
604
      return SCALE_FACTOR_DRAW;
632
 
605
 
633
  return SCALE_FACTOR_NONE;
606
  return SCALE_FACTOR_NONE;
Line 669... Line 642...
669
      // These rules are probably not perfect, but in practice they work
642
      // These rules are probably not perfect, but in practice they work
670
      // reasonably well.
643
      // reasonably well.
671
 
644
 
672
      if (relative_rank(strongSide, pawnSq) <= RANK_5)
645
      if (relative_rank(strongSide, pawnSq) <= RANK_5)
673
          return SCALE_FACTOR_DRAW;
646
          return SCALE_FACTOR_DRAW;
674
      else
-
 
675
      {
-
 
676
          Bitboard path = forward_bb(strongSide, pawnSq);
-
 
677
 
647
 
-
 
648
      Bitboard path = forward_file_bb(strongSide, pawnSq);
-
 
649
 
678
          if (path & pos.pieces(weakSide, KING))
650
      if (path & pos.pieces(weakSide, KING))
679
              return SCALE_FACTOR_DRAW;
651
          return SCALE_FACTOR_DRAW;
680
 
652
 
681
          if (  (pos.attacks_from<BISHOP>(weakBishopSq) & path)
653
      if (  (pos.attacks_from<BISHOP>(weakBishopSq) & path)
682
              && distance(weakBishopSq, pawnSq) >= 3)
654
          && distance(weakBishopSq, pawnSq) >= 3)
683
              return SCALE_FACTOR_DRAW;
655
          return SCALE_FACTOR_DRAW;
684
      }
-
 
685
  }
656
  }
686
  return SCALE_FACTOR_NONE;
657
  return SCALE_FACTOR_NONE;
687
}
658
}
688
 
659
 
689
 
660
 
Line 807... Line 778...
807
  Square bishopSq = pos.square<BISHOP>(weakSide);
778
  Square bishopSq = pos.square<BISHOP>(weakSide);
808
  Square weakKingSq = pos.square<KING>(weakSide);
779
  Square weakKingSq = pos.square<KING>(weakSide);
809
 
780
 
810
  // King needs to get close to promoting pawn to prevent knight from blocking.
781
  // King needs to get close to promoting pawn to prevent knight from blocking.
811
  // Rules for this are very tricky, so just approximate.
782
  // Rules for this are very tricky, so just approximate.
812
  if (forward_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
783
  if (forward_file_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
813
      return ScaleFactor(distance(weakKingSq, pawnSq));
784
      return ScaleFactor(distance(weakKingSq, pawnSq));
814
 
785
 
815
  return SCALE_FACTOR_NONE;
786
  return SCALE_FACTOR_NONE;
816
}
787
}
817
 
788