25.7. Ocena sytuacji na planszy

Ponieważ opisywana aplikacja ma potrafić grać w szachy z człowiekiem, więc potrzebna jest implementacja algorytmu określającego jaki następny ruch ma zostać wykonany przez komputer. Z kolei taki algorytm porzebuje sposobu oceny różnych stanów gry. Algorytm oceniający jest zaimplementowany w pliku Rank.scala. Plik zawiera definicję klasy Rank i jej obiektu towarzyszącego.

Plik Rank.scala:
package chess

import language.implicitConversions

object Rank {

  def figureRank(figure: Figure) = figure.figureType match {
    case Queen => 900
    case Rook => 450
    case Knight | Bishop => 300
    case Pawn => 100
    case _ => 0
  }

  def fieldRank(field: Field) = {
    def colRowRank(cr: Int) = if (cr>=5) 9-cr else cr
    2*colRowRank(field.col) * colRowRank(field.row)
  }

  implicit def Game2Rank(game: Game): Rank = new Rank(game) 

}

class Rank(game: Game) {
  import Rank._
  import FigureMoves._

  def figureDefendingOtherFiguresRank(field:Field, figure:Figure) =
    game.sameColorDestinations(figure.figureColor, figureMoves(figure,field,true)).size/2

  def checkRank(color: Color) =
    if (game.color == color.other && game.isKingUnderCheck) 50
    else 0

  def colorRank(color: Color) =
    (for ((field, figure) <- game.board.iterator
      if figure.figureColor == color;
      r1 = figureRank(figure);
      r2 = fieldRank(field);
      r3 = game.figureDefendingOtherFiguresRank(field, figure))
    yield r1 + r2 + r3).sum + game.checkRank(color)

  def rank(color: Color) =
    game.colorRank(color)-game.colorRank(color.other)

}

Metoda rank klasy Rank zwraca liczbę całkowitą reprezentującą ocenę stanu gry z punktu widzenia określonego gracza. Im większa jest ta liczba, tym lepsza jest ocena danej sytuacji na planszy. Klasa Rank ma parametr game typu Game, który reprezentuje oceniany stan gry. Dzięki niejawnej konwersji obiektów typu Game na obiekty typu Rank, zdefiniowanej w wierszu , możliwe jest wywoływanie metody rank na obiektach typu Game.

scala> import chess._, Rank._
import chess._
import Rank._

scala> GameStart.rank(White)
res0: Int = 0

Metoda rank zwraca różnicę punktów otrzymanych dzięki wywołaniom metody colorRank, oceniającej sytuację na planszy z punktu widzenia konkretnego gracza. Metoda działa w ten sposób, że przypisuje punktację każdej z figur danego koloru i dodaje te punkty, a do tak uzyskanej sumy dodaje jeszcze wynik metody checkRank. Punkty przyznawane są każdej z figur według trzech kryteriów, ocenianych przez metody figureRank, fieldRank oraz figureDefendingOtherFiguresRank. Metoda figureRank przypisuje każdej z figur określoną punktację, zależną od rodzaju figury. Najlepiej oceniany jest hetman, później wieża, następnie równo skoczek i goniec, a najmniej pion. Król nie otrzymuje punktów, gdyż i tak każda ze stron ma przez cały czas trwania partii po jednym i tylko jednym królu.

scala> figureRank(Figure(Queen,White))
res1: Int = 900

scala> figureRank(Figure(Knight,Black))
res2: Int = 300

Metoda fieldRank przypisuje punktację w zależności od pozycji figury na planszy, przy czym lepiej są oceniane pola w centrum planszy, a gorzej pola dalsze od centrum.

scala> fieldRank(Field(1,1))
res3: Int = 2

scala> fieldRank(Field(2,5))
res4: Int = 16
scala> fieldRank(Field(4,4))
res5: Int = 32

Metoda figureDefendingOtherFiguresRank przypisuje punktację zależną od tego, ilu figur tego samego koloru broni dana figura. Im więcej figur jest bronionych, tym lepiej.

scala> GameStart.figureDefendingOtherFiguresRank(Field(4,1),Figure(Queen,White))
res6: Int = 2

scala> GameStart.figureDefendingOtherFiguresRank(Field(4,7),Figure(Pawn,Black))
res7: Int = 0

Metoda checkRank przypisuje dodatkowe punkty, jeśli król przeciwnika jest szachowany.

scala> GameStart.checkRank(White)
res8: Int = 0

scala> val g = GameStart.move(Field(7,2),Field(7,4),None).get.
     | move(Field(5,7),Field(5,6),None).get.
     | move(Field(6,2),Field(6,4),None).get.
     | move(Field(4,8),Field(8,4),None).get
g: chess.OngoingGame =
Last move: Black d8 to h4
 abcdefgh
8RNB.KBNR8
7PPPP.PPP7
6....P...6
5........5
4.....ppQ4
3........3
2ppppp..p2
1rnbqkbnr1
 abcdefgh

scala> g.checkRank(Black)
res9: Int = 50

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.